diff --git a/src/arm/fast-codegen-arm.cc b/src/arm/fast-codegen-arm.cc index d21d624f0b..f4d5bd11f9 100644 --- a/src/arm/fast-codegen-arm.cc +++ b/src/arm/fast-codegen-arm.cc @@ -769,30 +769,40 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) { void FastCodeGenerator::VisitCall(Call* expr) { + Comment cmnt(masm_, "[ Call"); Expression* fun = expr->expression(); Variable* var = fun->AsVariableProxy()->AsVariable(); - if (var != NULL && - var->is_possibly_eval()) { - // Call to eval. + if (var != NULL && var->is_possibly_eval()) { + // Call to the identifier 'eval'. + UNREACHABLE(); + } else if (var != NULL && !var->is_this() && var->is_global()) { + // Call to a global variable. + __ mov(r1, Operand(var->name())); + // Push global object as receiver for the call IC lookup. + __ ldr(r0, CodeGenerator::GlobalObject()); + __ stm(db_w, sp, r1.bit() | r0.bit()); + EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT); + } else if (var != NULL && var->slot() != NULL && + var->slot()->type() == Slot::LOOKUP) { + // Call to a lookup slot. UNREACHABLE(); } else if (fun->AsProperty() != NULL) { - // Call on a property. + // Call to an object property. Property* prop = fun->AsProperty(); Literal* key = prop->key()->AsLiteral(); if (key != NULL && key->handle()->IsSymbol()) { - // Call on a named property: foo.x(1,2,3) + // Call to a named property, use call IC. __ mov(r0, Operand(key->handle())); __ push(r0); Visit(prop->obj()); - // Use call IC. EmitCallWithIC(expr, RelocInfo::CODE_TARGET); } else { - // Call on a keyed property : foo[key](1,2,3) - // Use a keyed load IC followed by a call IC. + // Call to a keyed property, use keyed load IC followed by function + // call. Visit(prop->obj()); Visit(prop->key()); - // Record source position of property. + // Record source code position for IC call. SetSourcePosition(prop->position()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); @@ -807,21 +817,8 @@ void FastCodeGenerator::VisitCall(Call* expr) { __ str(r1, MemOperand(sp)); EmitCallWithStub(expr); } - } else if (var != NULL) { - // Call on a global variable - ASSERT(var != NULL && !var->is_this() && var->is_global()); - ASSERT(!var->is_possibly_eval()); - __ mov(r1, Operand(var->name())); - // Push global object as receiver. - __ ldr(r0, CodeGenerator::GlobalObject()); - __ stm(db_w, sp, r1.bit() | r0.bit()); - EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->slot() != NULL && - var->slot()->type() == Slot::LOOKUP) { - // Call inside a with-statement - UNREACHABLE(); } else { - // Call with an arbitrary function expression. + // Call to some other function expression. Visit(expr->expression()); // Load global receiver object. __ ldr(r1, CodeGenerator::GlobalObject()); diff --git a/src/compiler.cc b/src/compiler.cc index 2fa41c48bc..ba96542bfe 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -800,18 +800,13 @@ void CodeGenSelector::VisitCall(Call* expr) { // Check for supported calls if (var != NULL && var->is_possibly_eval()) { - // ---------------------------------- - // JavaScript example: 'eval(arg)' // eval is not known to be shadowed - // ---------------------------------- - BAILOUT("Call to a function named 'eval'"); + BAILOUT("call to the identifier 'eval'"); } else if (var != NULL && !var->is_this() && var->is_global()) { - // ---------------------------------- - // JavaScript example: 'foo(1, 2, 3)' // foo is global - // ---------------------------------- + // Calls to global variables are supported. + } else if (var != NULL && var->slot() != NULL && + var->slot()->type() == Slot::LOOKUP) { + BAILOUT("call to a lookup slot"); } else if (fun->AsProperty() != NULL) { - // ------------------------------------------------------------------ - // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' - // ------------------------------------------------------------------ Property* prop = fun->AsProperty(); Literal* literal_key = prop->key()->AsLiteral(); if (literal_key != NULL && literal_key->handle()->IsSymbol()) { @@ -823,19 +818,11 @@ void CodeGenSelector::VisitCall(Call* expr) { ProcessExpression(prop->key(), Expression::kValue); CHECK_BAILOUT; } - } else if (var != NULL && var->slot() != NULL && - var->slot()->type() == Slot::LOOKUP) { - // ---------------------------------- - // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj - // ---------------------------------- - BAILOUT("Call inside a with-statement"); } else { - // ---------------------------------- - // JavaScript example: 'foo(1, 2, 3)' // foo is any expression, not global - // ---------------------------------- + // Otherwise the call is supported if the function expression is. ProcessExpression(fun, Expression::kValue); } - // Check all arguments to the call. (Relies on TEMP meaning STACK.) + // Check all arguments to the call. for (int i = 0; i < args->length(); i++) { ProcessExpression(args->at(i), Expression::kValue); CHECK_BAILOUT; diff --git a/src/ia32/fast-codegen-ia32.cc b/src/ia32/fast-codegen-ia32.cc index d512fa211e..02c19f67f5 100644 --- a/src/ia32/fast-codegen-ia32.cc +++ b/src/ia32/fast-codegen-ia32.cc @@ -787,29 +787,38 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) { void FastCodeGenerator::VisitCall(Call* expr) { + Comment cmnt(masm_, "[ Call"); Expression* fun = expr->expression(); Variable* var = fun->AsVariableProxy()->AsVariable(); - if (var != NULL && - var->is_possibly_eval()) { - // Call to eval. + if (var != NULL && var->is_possibly_eval()) { + // Call to the identifier 'eval'. + UNREACHABLE(); + } else if (var != NULL && !var->is_this() && var->is_global()) { + // Call to a global variable. + __ push(Immediate(var->name())); + // Push global object as receiver for the call IC lookup. + __ push(CodeGenerator::GlobalObject()); + EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT); + } else if (var != NULL && var->slot() != NULL && + var->slot()->type() == Slot::LOOKUP) { + // Call to a lookup slot. UNREACHABLE(); } else if (fun->AsProperty() != NULL) { - // Call on a property. + // Call to an object property. Property* prop = fun->AsProperty(); Literal* key = prop->key()->AsLiteral(); if (key != NULL && key->handle()->IsSymbol()) { - // Call on a named property: foo.x(1,2,3) + // Call to a named property, use call IC. __ push(Immediate(key->handle())); Visit(prop->obj()); - // Use call IC. EmitCallWithIC(expr, RelocInfo::CODE_TARGET); } else { - // Call on a keyed property: foo[key](1,2,3) - // Use a keyed load IC followed by a call IC. + // Call to a keyed property, use keyed load IC followed by function + // call. Visit(prop->obj()); Visit(prop->key()); - // Record source position of property. + // Record source code position for IC call. SetSourcePosition(prop->position()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); @@ -830,22 +839,8 @@ void FastCodeGenerator::VisitCall(Call* expr) { } EmitCallWithStub(expr); } - } else if (var != NULL) { - // Call on a global variable - ASSERT(var != NULL); - ASSERT(!var->is_this()); - ASSERT(var->is_global()); - ASSERT(!var->is_possibly_eval()); - __ push(Immediate(var->name())); - // Push global object (receiver). - __ push(CodeGenerator::GlobalObject()); - EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->slot() != NULL && - var->slot()->type() == Slot::LOOKUP) { - // Call inside a with-statement - UNREACHABLE(); } else { - // Call with an arbitrary function expression. + // Call to some other function expression. Visit(expr->expression()); // Load global receiver object. __ mov(ebx, CodeGenerator::GlobalObject()); diff --git a/src/x64/fast-codegen-x64.cc b/src/x64/fast-codegen-x64.cc index d5381a210c..bdf14a544f 100644 --- a/src/x64/fast-codegen-x64.cc +++ b/src/x64/fast-codegen-x64.cc @@ -802,29 +802,38 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) { void FastCodeGenerator::VisitCall(Call* expr) { + Comment cmnt(masm_, "[ Call"); Expression* fun = expr->expression(); Variable* var = fun->AsVariableProxy()->AsVariable(); - if (var != NULL && - var->is_possibly_eval()) { - // Call to eval. + if (var != NULL && var->is_possibly_eval()) { + // Call to the identifier 'eval'. + UNREACHABLE(); + } else if (var != NULL && !var->is_this() && var->is_global()) { + // Call to a global variable. + __ Push(var->name()); + // Push global object as receiver for the call IC lookup. + __ push(CodeGenerator::GlobalObject()); + EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT); + } else if (var != NULL && var->slot() != NULL && + var->slot()->type() == Slot::LOOKUP) { + // Call to a lookup slot. UNREACHABLE(); } else if (fun->AsProperty() != NULL) { - // Call on a property. + // Call to an object property. Property* prop = fun->AsProperty(); Literal* key = prop->key()->AsLiteral(); if (key != NULL && key->handle()->IsSymbol()) { - // Call on a named property: foo.x(1,2,3) + // Call to a named property, use call IC. __ Push(key->handle()); Visit(prop->obj()); - // Use call IC EmitCallWithIC(expr, RelocInfo::CODE_TARGET); } else { - // Call on a keyed property: foo[key](1,2,3) - // Use a keyed load IC followed by a call IC. + // Call to a keyed property, use keyed load IC followed by function + // call. Visit(prop->obj()); Visit(prop->key()); - // Record source position of property. + // Record source code position for IC call. SetSourcePosition(prop->position()); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); @@ -845,20 +854,8 @@ void FastCodeGenerator::VisitCall(Call* expr) { } EmitCallWithStub(expr); } - } else if (var != NULL) { - // Call on a global variable - ASSERT(var != NULL && !var->is_this() && var->is_global()); - ASSERT(!var->is_possibly_eval()); - __ Push(var->name()); - // Push global object (receiver). - __ push(CodeGenerator::GlobalObject()); - EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->slot() != NULL && - var->slot()->type() == Slot::LOOKUP) { - // Call inside a with-statement - UNREACHABLE(); } else { - // Call with an arbitrary function expression. + // Call to some other function expression. Visit(expr->expression()); // Load global receiver object. __ movq(rbx, CodeGenerator::GlobalObject());