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. |