| Index: src/x64/codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/codegen-x64.cc (revision 2983)
|
| +++ src/x64/codegen-x64.cc (working copy)
|
| @@ -2704,8 +2704,65 @@
|
| // is resolved in cache misses (this also holds for megamorphic calls).
|
| // ------------------------------------------------------------------------
|
|
|
| - if (var != NULL && !var->is_this() && var->is_global()) {
|
| + if (var != NULL && var->is_possibly_eval()) {
|
| // ----------------------------------
|
| + // JavaScript example: 'eval(arg)' // eval is not known to be shadowed
|
| + // ----------------------------------
|
| +
|
| + // In a call to eval, we first call %ResolvePossiblyDirectEval to
|
| + // resolve the function we need to call and the receiver of the
|
| + // call. Then we call the resolved function using the given
|
| + // arguments.
|
| +
|
| + // Prepare the stack for the call to the resolved function.
|
| + Load(function);
|
| +
|
| + // Allocate a frame slot for the receiver.
|
| + frame_->Push(Factory::undefined_value());
|
| + int arg_count = args->length();
|
| + for (int i = 0; i < arg_count; i++) {
|
| + Load(args->at(i));
|
| + }
|
| +
|
| + // Prepare the stack for the call to ResolvePossiblyDirectEval.
|
| + frame_->PushElementAt(arg_count + 1);
|
| + if (arg_count > 0) {
|
| + frame_->PushElementAt(arg_count);
|
| + } else {
|
| + frame_->Push(Factory::undefined_value());
|
| + }
|
| +
|
| + // Resolve the call.
|
| + Result result =
|
| + frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2);
|
| +
|
| + // Touch up the stack with the right values for the function and the
|
| + // receiver. Use a scratch register to avoid destroying the result.
|
| + Result scratch = allocator_->Allocate();
|
| + ASSERT(scratch.is_valid());
|
| + __ movq(scratch.reg(),
|
| + FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0)));
|
| + frame_->SetElementAt(arg_count + 1, &scratch);
|
| +
|
| + // We can reuse the result register now.
|
| + frame_->Spill(result.reg());
|
| + __ movq(result.reg(),
|
| + FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1)));
|
| + frame_->SetElementAt(arg_count, &result);
|
| +
|
| + // Call the function.
|
| + CodeForSourcePosition(node->position());
|
| + InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
|
| + CallFunctionStub call_function(arg_count, in_loop);
|
| + result = frame_->CallStub(&call_function, arg_count + 1);
|
| +
|
| + // Restore the context and overwrite the function on the stack with
|
| + // the result.
|
| + frame_->RestoreContextRegister();
|
| + frame_->SetElementAt(0, &result);
|
| +
|
| + } else if (var != NULL && !var->is_this() && var->is_global()) {
|
| + // ----------------------------------
|
| // JavaScript example: 'foo(1, 2, 3)' // foo is global
|
| // ----------------------------------
|
|
|
| @@ -2731,6 +2788,7 @@
|
| frame_->RestoreContextRegister();
|
| // Replace the function on the stack with the result.
|
| frame_->SetElementAt(0, &result);
|
| +
|
| } else if (var != NULL && var->slot() != NULL &&
|
| var->slot()->type() == Slot::LOOKUP) {
|
| // ----------------------------------
|
| @@ -2757,6 +2815,7 @@
|
|
|
| // Call the function.
|
| CallWithArguments(args, node->position());
|
| +
|
| } else if (property != NULL) {
|
| // Check if the key is a literal string.
|
| Literal* literal = property->key()->AsLiteral();
|
| @@ -2822,6 +2881,7 @@
|
| // Call the function.
|
| CallWithArguments(args, node->position());
|
| }
|
| +
|
| } else {
|
| // ----------------------------------
|
| // JavaScript example: 'foo(1, 2, 3)' // foo is not global
|
| @@ -2839,65 +2899,6 @@
|
| }
|
|
|
|
|
| -void CodeGenerator::VisitCallEval(CallEval* node) {
|
| - Comment cmnt(masm_, "[ CallEval");
|
| -
|
| - // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve
|
| - // the function we need to call and the receiver of the call.
|
| - // Then we call the resolved function using the given arguments.
|
| -
|
| - ZoneList<Expression*>* args = node->arguments();
|
| - Expression* function = node->expression();
|
| -
|
| - // Prepare the stack for the call to the resolved function.
|
| - Load(function);
|
| -
|
| - // Allocate a frame slot for the receiver.
|
| - frame_->Push(Factory::undefined_value());
|
| - int arg_count = args->length();
|
| - for (int i = 0; i < arg_count; i++) {
|
| - Load(args->at(i));
|
| - }
|
| -
|
| - // Prepare the stack for the call to ResolvePossiblyDirectEval.
|
| - frame_->PushElementAt(arg_count + 1);
|
| - if (arg_count > 0) {
|
| - frame_->PushElementAt(arg_count);
|
| - } else {
|
| - frame_->Push(Factory::undefined_value());
|
| - }
|
| -
|
| - // Resolve the call.
|
| - Result result =
|
| - frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2);
|
| -
|
| - // Touch up the stack with the right values for the function and the
|
| - // receiver. Use a scratch register to avoid destroying the result.
|
| - Result scratch = allocator_->Allocate();
|
| - ASSERT(scratch.is_valid());
|
| - __ movq(scratch.reg(),
|
| - FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0)));
|
| - frame_->SetElementAt(arg_count + 1, &scratch);
|
| -
|
| - // We can reuse the result register now.
|
| - frame_->Spill(result.reg());
|
| - __ movq(result.reg(),
|
| - FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1)));
|
| - frame_->SetElementAt(arg_count, &result);
|
| -
|
| - // Call the function.
|
| - CodeForSourcePosition(node->position());
|
| - InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
|
| - CallFunctionStub call_function(arg_count, in_loop);
|
| - result = frame_->CallStub(&call_function, arg_count + 1);
|
| -
|
| - // Restore the context and overwrite the function on the stack with
|
| - // the result.
|
| - frame_->RestoreContextRegister();
|
| - frame_->SetElementAt(0, &result);
|
| -}
|
| -
|
| -
|
| void CodeGenerator::VisitCallNew(CallNew* node) {
|
| Comment cmnt(masm_, "[ CallNew");
|
|
|
|
|