void FastCodeGenerator::VisitCall(Call* expr) {
Expression* fun = expr->expression();
+ Variable* var = fun->AsVariableProxy()->AsVariable();
- if (fun->AsProperty() != NULL) {
+ if (var != NULL &&
+ var->is_possibly_eval()) {
+ // Call to eval.
+ UNREACHABLE();
+ } else if (fun->AsProperty() != NULL) {
// Call on a property.
Property* prop = fun->AsProperty();
Literal* key = prop->key()->AsLiteral();
__ str(r1, MemOperand(sp));
EmitCallWithStub(expr);
}
- } else if (fun->AsVariableProxy()->AsVariable() != NULL) {
+ } else if (var != NULL) {
// Call on a global variable
- Variable* var = fun->AsVariableProxy()->AsVariable();
ASSERT(var != NULL && !var->is_this() && var->is_global());
ASSERT(!var->is_possibly_eval());
__ mov(r1, Operand(var->name()));
__ ldr(r0, CodeGenerator::GlobalObject());
__ stm(db_w, sp, r1.bit() | r0.bit());
EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
- } else {
- // Calls we cannot handle right now.
- // Should bailout in the CodeGenSelector.
+ } 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.
+ Visit(expr->expression());
+ // Load global receiver object.
+ __ ldr(r1, CodeGenerator::GlobalObject());
+ __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
+ __ push(r1);
+ // Emit function call.
+ EmitCallWithStub(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'");
} else if (var != NULL && !var->is_this() && var->is_global()) {
// ----------------------------------
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 {
- BAILOUT("Unsupported call to a function");
+ // ----------------------------------
+ // JavaScript example: 'foo(1, 2, 3)' // foo is any expression, not global
+ // ----------------------------------
+ ProcessExpression(fun, Expression::kValue);
}
// Check all arguments to the call. (Relies on TEMP meaning STACK.)
for (int i = 0; i < args->length(); i++) {
void FastCodeGenerator::VisitCall(Call* expr) {
Expression* fun = expr->expression();
+ Variable* var = fun->AsVariableProxy()->AsVariable();
- if (fun->AsProperty() != NULL) {
+ if (var != NULL &&
+ var->is_possibly_eval()) {
+ // Call to eval.
+ UNREACHABLE();
+ } else if (fun->AsProperty() != NULL) {
// Call on a property.
Property* prop = fun->AsProperty();
Literal* key = prop->key()->AsLiteral();
}
EmitCallWithStub(expr);
}
- } else if (fun->AsVariableProxy()->AsVariable() != NULL) {
+ } else if (var != NULL) {
// Call on a global variable
- Variable* var = fun->AsVariableProxy()->AsVariable();
- ASSERT(var != NULL && !var->is_this() && var->is_global());
+ 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 {
- // Calls we cannot handle right now.
- // Should bailout in the CodeGenSelector.
+ } 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.
+ Visit(expr->expression());
+ // Load global receiver object.
+ __ mov(ebx, CodeGenerator::GlobalObject());
+ __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
+ // Emit function call.
+ EmitCallWithStub(expr);
}
}
void FastCodeGenerator::VisitCall(Call* expr) {
Expression* fun = expr->expression();
+ Variable* var = fun->AsVariableProxy()->AsVariable();
- if (fun->AsProperty() != NULL) {
+ if (var != NULL &&
+ var->is_possibly_eval()) {
+ // Call to eval.
+ UNREACHABLE();
+ } else if (fun->AsProperty() != NULL) {
// Call on a property.
Property* prop = fun->AsProperty();
Literal* key = prop->key()->AsLiteral();
}
EmitCallWithStub(expr);
}
- } else if (fun->AsVariableProxy()->AsVariable() != NULL) {
+ } else if (var != NULL) {
// Call on a global variable
- Variable* var = fun->AsVariableProxy()->AsVariable();
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 {
- // Calls we cannot handle right now.
- // Should bailout in the CodeGenSelector.
+ } 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.
+ Visit(expr->expression());
+ // Load global receiver object.
+ __ movq(rbx, CodeGenerator::GlobalObject());
+ __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
+ // Emit function call.
+ EmitCallWithStub(expr);
}
}
a = b[c](10);
assertEquals(10, a);
+// Call on a function expression
+function g() { return f; }
+a = g()(8);
+assertEquals(8, a);