| Index: src/x64/full-codegen-x64.cc
|
| diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
|
| index 1381a94dd31047902035a488b68adc08febc8afe..5d9217b6c186d9e8d34fcdc172c1a1dee3dc605f 100644
|
| --- a/src/x64/full-codegen-x64.cc
|
| +++ b/src/x64/full-codegen-x64.cc
|
| @@ -2051,6 +2051,27 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
| }
|
|
|
|
|
| +void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
|
| + int arg_count) {
|
| + // Push copy of the first argument or undefined if it doesn't exist.
|
| + if (arg_count > 0) {
|
| + __ push(Operand(rsp, arg_count * kPointerSize));
|
| + } else {
|
| + __ PushRoot(Heap::kUndefinedValueRootIndex);
|
| + }
|
| +
|
| + // Push the receiver of the enclosing function and do runtime call.
|
| + __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
|
| +
|
| + // Push the strict mode flag.
|
| + __ Push(Smi::FromInt(strict_mode_flag()));
|
| +
|
| + __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
|
| + ? Runtime::kResolvePossiblyDirectEvalNoLookup
|
| + : Runtime::kResolvePossiblyDirectEval, 4);
|
| +}
|
| +
|
| +
|
| void FullCodeGenerator::VisitCall(Call* expr) {
|
| #ifdef DEBUG
|
| // We want to verify that RecordJSReturnSite gets called on all paths
|
| @@ -2078,21 +2099,30 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
| VisitForStackValue(args->at(i));
|
| }
|
|
|
| - // Push copy of the function - found below the arguments.
|
| - __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
|
| -
|
| - // Push copy of the first argument or undefined if it doesn't exist.
|
| - if (arg_count > 0) {
|
| - __ push(Operand(rsp, arg_count * kPointerSize));
|
| - } else {
|
| - __ PushRoot(Heap::kUndefinedValueRootIndex);
|
| + // If we know that eval can only be shadowed by eval-introduced
|
| + // variables we attempt to load the global eval function directly
|
| + // in generated code. If we succeed, there is no need to perform a
|
| + // context lookup in the runtime system.
|
| + Label done;
|
| + if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
|
| + Label slow;
|
| + EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
|
| + NOT_INSIDE_TYPEOF,
|
| + &slow);
|
| + // Push the function and resolve eval.
|
| + __ push(rax);
|
| + EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
|
| + __ jmp(&done);
|
| + __ bind(&slow);
|
| }
|
|
|
| - // Push the receiver of the enclosing function and do runtime call.
|
| - __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
|
| - // Push the strict mode flag.
|
| - __ Push(Smi::FromInt(strict_mode_flag()));
|
| - __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
|
| + // Push copy of the function (found below the arguments) and
|
| + // resolve eval.
|
| + __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
|
| + EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
|
| + if (done.is_linked()) {
|
| + __ bind(&done);
|
| + }
|
|
|
| // The runtime call returns a pair of values in rax (function) and
|
| // rdx (receiver). Touch up the stack with the right values.
|
|
|