| Index: src/ia32/codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/codegen-ia32.cc (revision 2983)
|
| +++ src/ia32/codegen-ia32.cc (working copy)
|
| @@ -4431,10 +4431,10 @@
|
| void CodeGenerator::VisitCall(Call* node) {
|
| Comment cmnt(masm_, "[ Call");
|
|
|
| + Expression* function = node->expression();
|
| ZoneList<Expression*>* args = node->arguments();
|
|
|
| // Check if the function is a variable or a property.
|
| - Expression* function = node->expression();
|
| Variable* var = function->AsVariableProxy()->AsVariable();
|
| Property* property = function->AsProperty();
|
|
|
| @@ -4447,8 +4447,64 @@
|
| // 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());
|
| + __ mov(scratch.reg(), FieldOperand(result.reg(), FixedArray::kHeaderSize));
|
| + frame_->SetElementAt(arg_count + 1, &scratch);
|
| +
|
| + // We can reuse the result register now.
|
| + frame_->Spill(result.reg());
|
| + __ mov(result.reg(),
|
| + FieldOperand(result.reg(), FixedArray::kHeaderSize + kPointerSize));
|
| + 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
|
| // ----------------------------------
|
|
|
| @@ -4616,64 +4672,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());
|
| - __ mov(scratch.reg(), FieldOperand(result.reg(), FixedArray::kHeaderSize));
|
| - frame_->SetElementAt(arg_count + 1, &scratch);
|
| -
|
| - // We can reuse the result register now.
|
| - frame_->Spill(result.reg());
|
| - __ mov(result.reg(),
|
| - FieldOperand(result.reg(), FixedArray::kHeaderSize + kPointerSize));
|
| - 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::GenerateIsSmi(ZoneList<Expression*>* args) {
|
| ASSERT(args->length() == 1);
|
| Load(args->at(0));
|
|
|