Revert of Add script context with context-allocated "const this" (patchset #7 id...
authormachenbach <machenbach@chromium.org>
Fri, 12 Jun 2015 10:07:22 +0000 (03:07 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 12 Jun 2015 10:07:34 +0000 (10:07 +0000)
Reason for revert:
[Sheriff] Breaks gc mole:
http://build.chromium.org/p/client.v8/builders/V8%20Linux%20-%20gcmole/builds/2435

Original issue's description:
> Add script context with context-allocated "const this"
>
> R=rossberg@chromium.org
> LOG=N
> BUG=498811
>
> Committed: https://crrev.com/fa32d461c16a053cc6d48d3fb326016bc2765765
> Cr-Commit-Position: refs/heads/master@{#28988}

TBR=rossberg@chromium.org,mstarzinger@chromium.org,wingo@igalia.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=498811

Review URL: https://codereview.chromium.org/1180043004

Cr-Commit-Position: refs/heads/master@{#28992}

19 files changed:
src/arm/full-codegen-arm.cc
src/arm64/full-codegen-arm64.cc
src/bootstrapper.cc
src/compiler/ast-graph-builder.cc
src/hydrogen.cc
src/ia32/full-codegen-ia32.cc
src/mips/full-codegen-mips.cc
src/mips64/full-codegen-mips64.cc
src/objects.h
src/ppc/full-codegen-ppc.cc
src/runtime/runtime-compiler.cc
src/runtime/runtime.h
src/scopeinfo.cc
src/scopes.h
src/snapshot/snapshot-common.cc
src/variables.h
src/x64/full-codegen-x64.cc
src/x87/full-codegen-x87.cc
test/unittests/compiler/js-type-feedback-unittest.cc

index a2f24400a4fc53612d0b5123f618266a89f75bfb..9a01faddc1f42738518b1dcac7b70d6d8f04562b 100644 (file)
@@ -3104,15 +3104,20 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
 
 
 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
-  // r4: copy of the first argument or undefined if it doesn't exist.
+  // r5: copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
-    __ ldr(r4, MemOperand(sp, arg_count * kPointerSize));
+    __ ldr(r5, MemOperand(sp, arg_count * kPointerSize));
   } else {
-    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
+    __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
   }
 
+  // r4: the receiver of the enclosing function.
+  __ ldr(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+
   // r3: the receiver of the enclosing function.
-  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  Variable* this_var = scope()->LookupThis();
+  DCHECK_NOT_NULL(this_var);
+  __ ldr(r3, VarOperand(this_var, r3));
 
   // r2: language mode.
   __ mov(r2, Operand(Smi::FromInt(language_mode())));
@@ -3121,8 +3126,9 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
 
   // Do the runtime call.
+  __ Push(r5);
   __ Push(r4, r3, r2, r1);
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
 }
 
 
@@ -3154,9 +3160,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
   Call::CallType call_type = expr->GetCallType(isolate());
 
   if (call_type == Call::POSSIBLY_EVAL_CALL) {
-    // In a call to eval, we first call
-    // RuntimeHidden_asResolvePossiblyDirectEval to resolve the function we need
-    // to call.  Then we call the resolved function using the given arguments.
+    // In a call to eval, we first call RuntimeHidden_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 = expr->arguments();
     int arg_count = args->length();
 
@@ -3176,8 +3183,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
       __ push(r1);
       EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
+      // The runtime call returns a pair of values in r0 (function) and
+      // r1 (receiver). Touch up the stack with the right values.
       __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
+      __ str(r1, MemOperand(sp, arg_count * kPointerSize));
 
       PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
     }
@@ -4774,10 +4783,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         context()->Plug(r0);
       } else if (proxy != NULL) {
         Variable* var = proxy->var();
-        // Delete of an unqualified identifier is disallowed in strict mode but
-        // "delete this" is allowed.
-        bool is_this = var->HasThisName(isolate());
-        DCHECK(is_sloppy(language_mode()) || is_this);
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is allowed.
+        DCHECK(is_sloppy(language_mode()) || var->is_this());
         if (var->IsUnallocated()) {
           __ ldr(r2, GlobalObjectOperand());
           __ mov(r1, Operand(var->name()));
@@ -4788,7 +4796,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         } else if (var->IsStackAllocated() || var->IsContextSlot()) {
           // Result of deleting non-global, non-dynamic variables is false.
           // The subexpression does not have side effects.
-          context()->Plug(is_this);
+          context()->Plug(var->is_this());
         } else {
           // Non-global variable.  Call the runtime to try to delete from the
           // context where the variable was introduced.
index 454bf03ddcbd2862c1ea02a5edc63437c020e3fa..90b57784d9eb75708bd45229ee63f3874c0ef067 100644 (file)
@@ -2799,17 +2799,21 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   }
 
   __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  // Prepare to push the receiver of the enclosing function.
+  Variable* this_var = scope()->LookupThis();
+  DCHECK_NOT_NULL(this_var);
+  __ Ldr(x11, VarOperand(this_var, x11));
 
   // Prepare to push the language mode.
-  __ Mov(x11, Smi::FromInt(language_mode()));
+  __ Mov(x12, Smi::FromInt(language_mode()));
   // Prepare to push the start position of the scope the calls resides in.
-  __ Mov(x12, Smi::FromInt(scope()->start_position()));
+  __ Mov(x13, Smi::FromInt(scope()->start_position()));
 
   // Push.
-  __ Push(x9, x10, x11, x12);
+  __ Push(x9, x10, x11, x12, x13);
 
   // Do the runtime call.
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
 }
 
 
@@ -2841,8 +2845,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
 
   if (call_type == Call::POSSIBLY_EVAL_CALL) {
     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
-    // to resolve the function we need to call.  Then we call the resolved
-    // function using the given arguments.
+    // 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 = expr->arguments();
     int arg_count = args->length();
 
@@ -2863,8 +2868,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
       __ Push(x10);
       EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
-      __ Poke(x0, (arg_count + 1) * kPointerSize);
+      // The runtime call returns a pair of values in x0 (function) and
+      // x1 (receiver). Touch up the stack with the right values.
+      __ PokePair(x1, x0, arg_count * kPointerSize);
 
       PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
     }
@@ -4458,10 +4464,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         context()->Plug(x0);
       } else if (proxy != NULL) {
         Variable* var = proxy->var();
-        // Delete of an unqualified identifier is disallowed in strict mode but
-        // "delete this" is allowed.
-        bool is_this = var->HasThisName(isolate());
-        DCHECK(is_sloppy(language_mode()) || is_this);
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is allowed.
+        DCHECK(is_sloppy(language_mode()) || var->is_this());
         if (var->IsUnallocated()) {
           __ Ldr(x12, GlobalObjectMemOperand());
           __ Mov(x11, Operand(var->name()));
@@ -4472,7 +4477,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         } else if (var->IsStackAllocated() || var->IsContextSlot()) {
           // Result of deleting non-global, non-dynamic variables is false.
           // The subexpression does not have side effects.
-          context()->Plug(is_this);
+          context()->Plug(var->is_this());
         } else {
           // Non-global variable.  Call the runtime to try to delete from the
           // context where the variable was introduced.
index 73dd2989a79d997cdfe20a48bd1a8e020d02a2ba..c675fe7e0d423211669c505a2f1a7a4169a9aa31 100644 (file)
@@ -197,11 +197,6 @@ class Genesis BASE_EMBEDDED {
   // other objects in the snapshot.
   void HookUpGlobalObject(Handle<GlobalObject> global_object,
                           Handle<FixedArray> outdated_contexts);
-  // The native context has a ScriptContextTable that store declarative bindings
-  // made in script scopes.  Add a "this" binding to that table pointing to the
-  // global proxy.
-  void InstallGlobalThisBinding();
-  void HookUpGlobalThisBinding(Handle<FixedArray> outdated_contexts);
   // New context initialization.  Used for creating a context from scratch.
   void InitializeGlobal(Handle<GlobalObject> global_object,
                         Handle<JSFunction> empty_function);
@@ -819,40 +814,6 @@ void Genesis::CreateRoots() {
 }
 
 
-void Genesis::InstallGlobalThisBinding() {
-  Handle<ScriptContextTable> script_contexts(
-      native_context()->script_context_table());
-  Handle<ScopeInfo> scope_info = ScopeInfo::CreateGlobalThisBinding(isolate());
-  Handle<JSFunction> closure(native_context()->closure());
-  Handle<Context> context = factory()->NewScriptContext(closure, scope_info);
-
-  // Go ahead and hook it up while we're at it.
-  int slot = scope_info->ReceiverContextSlotIndex();
-  DCHECK_EQ(slot, Context::MIN_CONTEXT_SLOTS);
-  context->set(slot, native_context()->global_proxy());
-
-  native_context()->set_script_context_table(
-      *ScriptContextTable::Extend(script_contexts, context));
-}
-
-
-void Genesis::HookUpGlobalThisBinding(Handle<FixedArray> outdated_contexts) {
-  // One of these contexts should be the one that declares the global "this"
-  // binding.
-  for (int i = 0; i < outdated_contexts->length(); ++i) {
-    Context* context = Context::cast(outdated_contexts->get(i));
-    if (context->IsScriptContext()) {
-      ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
-      int slot = scope_info->ReceiverContextSlotIndex();
-      if (slot >= 0) {
-        DCHECK_EQ(slot, Context::MIN_CONTEXT_SLOTS);
-        context->set(slot, native_context()->global_proxy());
-      }
-    }
-  }
-}
-
-
 Handle<GlobalObject> Genesis::CreateNewGlobals(
     v8::Handle<v8::ObjectTemplate> global_proxy_template,
     Handle<JSGlobalProxy> global_proxy) {
@@ -1011,7 +972,6 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
   Handle<ScriptContextTable> script_context_table =
       factory->NewScriptContextTable();
   native_context()->set_script_context_table(*script_context_table);
-  InstallGlobalThisBinding();
 
   Handle<String> object_name = factory->Object_string();
   JSObject::AddProperty(
@@ -3126,7 +3086,6 @@ Genesis::Genesis(Isolate* isolate,
     HookUpGlobalObject(global_object, outdated_contexts);
     native_context()->builtins()->set_global_proxy(
         native_context()->global_proxy());
-    HookUpGlobalThisBinding(outdated_contexts);
 
     if (!ConfigureGlobalObjects(global_proxy_template)) return;
   } else {
index cf7bbc99a52a8e830c5b3b5d78fd6e8635649402..43d402094539cfae9c31dd3f2f3395888a17db86 100644 (file)
@@ -2420,17 +2420,37 @@ void AstGraphBuilder::VisitCall(Call* expr) {
     // Create node to ask for help resolving potential eval call. This will
     // provide a fully resolved callee and the corresponding receiver.
     Node* function = GetFunctionClosure();
+    // TODO(wingo): ResolvePossibleDirectEval doesn't really need a receiver,
+    // now that eval scopes don't have "this" declarations.  Remove this hack
+    // once ResolvePossibleDirectEval changes.
+    Node* receiver;
+    {
+      Variable* variable = info()->scope()->LookupThis();
+      if (variable->IsStackAllocated()) {
+        receiver = environment()->Lookup(variable);
+      } else {
+        DCHECK(variable->IsContextSlot());
+        int depth = current_scope()->ContextChainLength(variable->scope());
+        bool immutable = variable->maybe_assigned() == kNotAssigned;
+        const Operator* op =
+            javascript()->LoadContext(depth, variable->index(), immutable);
+        receiver = NewNode(op, current_context());
+      }
+    }
     Node* language = jsgraph()->Constant(language_mode());
     Node* position = jsgraph()->Constant(current_scope()->start_position());
     const Operator* op =
-        javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
-    Node* new_callee =
-        NewNode(op, callee, source, function, language, position);
-    PrepareFrameState(new_callee, expr->EvalOrLookupId(),
+        javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
+    Node* pair =
+        NewNode(op, callee, source, function, receiver, language, position);
+    PrepareFrameState(pair, expr->EvalOrLookupId(),
                       OutputFrameStateCombine::PokeAt(arg_count + 1));
+    Node* new_callee = NewNode(common()->Projection(0), pair);
+    Node* new_receiver = NewNode(common()->Projection(1), pair);
 
-    // Patch callee on the environment.
+    // Patch callee and receiver on the environment.
     environment()->Poke(arg_count + 1, new_callee);
+    environment()->Poke(arg_count + 0, new_receiver);
   }
 
   // Create node to perform the function call.
@@ -2853,9 +2873,7 @@ void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
     // Delete of an unqualified identifier is only allowed in classic mode but
     // deleting "this" is allowed in all language modes.
     Variable* variable = expr->expression()->AsVariableProxy()->var();
-    // Delete of an unqualified identifier is disallowed in strict mode but
-    // "delete this" is allowed.
-    DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
+    DCHECK(is_sloppy(language_mode()) || variable->is_this());
     value = BuildVariableDelete(variable, expr->id(),
                                 ast_context()->GetStateCombine());
   } else if (expr->expression()->IsProperty()) {
@@ -3303,10 +3321,9 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
     }
     case Variable::PARAMETER:
     case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case Variable::CONTEXT:
       // Local var, const, or let variable or context variable.
-      return jsgraph()->BooleanConstant(variable->HasThisName(isolate()));
-    }
+      return jsgraph()->BooleanConstant(variable->is_this());
     case Variable::LOOKUP: {
       // Dynamic lookup of context variable (anywhere in the chain).
       Node* name = jsgraph()->Constant(variable->name());
index ecf05f4bc53555367cf1c19c649c6be9d2d0b0d3..810a8b92210d4bb2389d024490c65b0b88e22eb1 100644 (file)
@@ -10197,11 +10197,12 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
     if (var->IsUnallocated()) {
       Bailout(kDeleteWithGlobalVariable);
     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
-      // Result of deleting non-global variables is false.  'this' is not really
-      // a variable, though we implement it as one.  The subexpression does not
-      // have side effects.
-      HValue* value = var->HasThisName(isolate()) ? graph()->GetConstantTrue()
-                                                  : graph()->GetConstantFalse();
+      // Result of deleting non-global variables is false.  'this' is not
+      // really a variable, though we implement it as one.  The
+      // subexpression does not have side effects.
+      HValue* value = var->is_this()
+          ? graph()->GetConstantTrue()
+          : graph()->GetConstantFalse();
       return ast_context()->ReturnValue(value);
     } else {
       Bailout(kDeleteWithNonGlobalVariable);
index 202740b385cc93bef3ba8e9a966d8d6a2708f004..40d54a6d691dadede991e5ac253e9aa32d025072 100644 (file)
@@ -3006,7 +3006,10 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
 
   // Push the enclosing function.
   __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-
+  // Push the receiver of the enclosing function.
+  Variable* this_var = scope()->LookupThis();
+  DCHECK_NOT_NULL(this_var);
+  __ push(VarOperand(this_var, ecx));
   // Push the language mode.
   __ push(Immediate(Smi::FromInt(language_mode())));
 
@@ -3014,7 +3017,7 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   __ push(Immediate(Smi::FromInt(scope()->start_position())));
 
   // Do the runtime call.
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
 }
 
 
@@ -3046,8 +3049,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
 
   if (call_type == Call::POSSIBLY_EVAL_CALL) {
     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
-    // to resolve the function we need to call.  Then we call the resolved
-    // function using the given arguments.
+    // 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 = expr->arguments();
     int arg_count = args->length();
     { PreservePositionScope pos_scope(masm()->positions_recorder());
@@ -3064,7 +3067,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
       __ push(Operand(esp, (arg_count + 1) * kPointerSize));
       EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
+      // The runtime call returns a pair of values in eax (function) and
+      // edx (receiver). Touch up the stack with the right values.
+      __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
       __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
 
       PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
@@ -4698,10 +4703,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         context()->Plug(eax);
       } else if (proxy != NULL) {
         Variable* var = proxy->var();
-        // Delete of an unqualified identifier is disallowed in strict mode but
-        // "delete this" is allowed.
-        bool is_this = var->HasThisName(isolate());
-        DCHECK(is_sloppy(language_mode()) || is_this);
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is allowed.
+        DCHECK(is_sloppy(language_mode()) || var->is_this());
         if (var->IsUnallocated()) {
           __ push(GlobalObjectOperand());
           __ push(Immediate(var->name()));
@@ -4712,7 +4716,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
           // Result of deleting non-global variables is false.  'this' is
           // not really a variable, though we implement it as one.  The
           // subexpression does not have side effects.
-          context()->Plug(is_this);
+          context()->Plug(var->is_this());
         } else {
           // Non-global variable.  Call the runtime to try to delete from the
           // context where the variable was introduced.
index 2440f9838362534dd70a472b133c2670b92824a7..b7d161193c6ff1ecc693edcf0f1d700a7c5254d5 100644 (file)
@@ -3089,15 +3089,21 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   // t2: the receiver of the enclosing function.
   __ lw(t2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
 
-  // t1: the language mode.
-  __ li(t1, Operand(Smi::FromInt(language_mode())));
+  // t1: the receiver of the enclosing function.
+  Variable* this_var = scope()->LookupThis();
+  DCHECK_NOT_NULL(this_var);
+  __ lw(t1, VarOperand(this_var, t1));
 
-  // t0: the start position of the scope the calls resides in.
-  __ li(t0, Operand(Smi::FromInt(scope()->start_position())));
+  // t0: the language mode.
+  __ li(t0, Operand(Smi::FromInt(language_mode())));
+
+  // a1: the start position of the scope the calls resides in.
+  __ li(a1, Operand(Smi::FromInt(scope()->start_position())));
 
   // Do the runtime call.
-  __ Push(t3, t2, t1, t0);
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+  __ Push(t3);
+  __ Push(t2, t1, t0, a1);
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
 }
 
 
@@ -3130,8 +3136,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
 
   if (call_type == Call::POSSIBLY_EVAL_CALL) {
     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
-    // to resolve the function we need to call.  Then we call the resolved
-    // function using the given arguments.
+    // 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 = expr->arguments();
     int arg_count = args->length();
 
@@ -3151,8 +3158,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
       __ push(a1);
       EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
+      // The runtime call returns a pair of values in v0 (function) and
+      // v1 (receiver). Touch up the stack with the right values.
       __ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
+      __ sw(v1, MemOperand(sp, arg_count * kPointerSize));
 
       PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
     }
@@ -4781,10 +4790,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         context()->Plug(v0);
       } else if (proxy != NULL) {
         Variable* var = proxy->var();
-        // Delete of an unqualified identifier is disallowed in strict mode but
-        // "delete this" is allowed.
-        bool is_this = var->HasThisName(isolate());
-        DCHECK(is_sloppy(language_mode()) || is_this);
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is allowed.
+        DCHECK(is_sloppy(language_mode()) || var->is_this());
         if (var->IsUnallocated()) {
           __ lw(a2, GlobalObjectOperand());
           __ li(a1, Operand(var->name()));
@@ -4795,7 +4803,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         } else if (var->IsStackAllocated() || var->IsContextSlot()) {
           // Result of deleting non-global, non-dynamic variables is false.
           // The subexpression does not have side effects.
-          context()->Plug(is_this);
+          context()->Plug(var->is_this());
         } else {
           // Non-global variable.  Call the runtime to try to delete from the
           // context where the variable was introduced.
index 572b5b3a77569a637834ccfff86a49b553da7e04..4f5139b129dd9ac39d51a70d7fddb9d7547d35ca 100644 (file)
@@ -3081,15 +3081,20 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
 
 
 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
-  // a6: copy of the first argument or undefined if it doesn't exist.
+  // a7: copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
-    __ ld(a6, MemOperand(sp, arg_count * kPointerSize));
+    __ ld(a7, MemOperand(sp, arg_count * kPointerSize));
   } else {
-    __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
+    __ LoadRoot(a7, Heap::kUndefinedValueRootIndex);
   }
 
+  // a6: the receiver of the enclosing function.
+  __ ld(a6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+
   // a5: the receiver of the enclosing function.
-  __ ld(a5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  Variable* this_var = scope()->LookupThis();
+  DCHECK_NOT_NULL(this_var);
+  __ ld(a5, VarOperand(this_var, a5));
 
   // a4: the language mode.
   __ li(a4, Operand(Smi::FromInt(language_mode())));
@@ -3098,8 +3103,9 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   __ li(a1, Operand(Smi::FromInt(scope()->start_position())));
 
   // Do the runtime call.
+  __ Push(a7);
   __ Push(a6, a5, a4, a1);
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
 }
 
 
@@ -3132,8 +3138,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
 
   if (call_type == Call::POSSIBLY_EVAL_CALL) {
     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
-    // to resolve the function we need to call.  Then we call the resolved
-    // function using the given arguments.
+    // 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 = expr->arguments();
     int arg_count = args->length();
 
@@ -3153,8 +3160,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
       __ push(a1);
       EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
+      // The runtime call returns a pair of values in v0 (function) and
+      // v1 (receiver). Touch up the stack with the right values.
       __ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
+      __ sd(v1, MemOperand(sp, arg_count * kPointerSize));
 
       PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
     }
@@ -4784,10 +4793,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         context()->Plug(v0);
       } else if (proxy != NULL) {
         Variable* var = proxy->var();
-        // Delete of an unqualified identifier is disallowed in strict mode but
-        // "delete this" is allowed.
-        bool is_this = var->HasThisName(isolate());
-        DCHECK(is_sloppy(language_mode()) || is_this);
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is allowed.
+        DCHECK(is_sloppy(language_mode()) || var->is_this());
         if (var->IsUnallocated()) {
           __ ld(a2, GlobalObjectOperand());
           __ li(a1, Operand(var->name()));
@@ -4798,7 +4806,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         } else if (var->IsStackAllocated() || var->IsContextSlot()) {
           // Result of deleting non-global, non-dynamic variables is false.
           // The subexpression does not have side effects.
-          context()->Plug(is_this);
+          context()->Plug(var->is_this());
         } else {
           // Non-global variable.  Call the runtime to try to delete from the
           // context where the variable was introduced.
index e9c8378332e5c9d83dc1355211d1e47f1796541a..031ec6e10433cfb9c0c4144aa9f9c5687ac145ec 100644 (file)
@@ -4055,7 +4055,6 @@ class ScopeInfo : public FixedArray {
 
 
   static Handle<ScopeInfo> Create(Isolate* isolate, Zone* zone, Scope* scope);
-  static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate);
 
   // Serializes empty scope info.
   static ScopeInfo* Empty(Isolate* isolate);
index ebd7efe8fbdb5534631ed245aa7fae530a2f119f..0145d006488afab0ebd5d46736d6252a01d87756 100644 (file)
@@ -3094,15 +3094,20 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
 
 
 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
-  // r7: copy of the first argument or undefined if it doesn't exist.
+  // r8: copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
-    __ LoadP(r7, MemOperand(sp, arg_count * kPointerSize), r0);
+    __ LoadP(r8, MemOperand(sp, arg_count * kPointerSize), r0);
   } else {
-    __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
+    __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
   }
 
+  // r7: the receiver of the enclosing function.
+  __ LoadP(r7, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+
   // r6: the receiver of the enclosing function.
-  __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  Variable* this_var = scope()->LookupThis();
+  DCHECK_NOT_NULL(this_var);
+  GetVar(r6, this_var);
 
   // r5: language mode.
   __ LoadSmiLiteral(r5, Smi::FromInt(language_mode()));
@@ -3111,8 +3116,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position()));
 
   // Do the runtime call.
-  __ Push(r7, r6, r5, r4);
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+  __ Push(r8, r7, r6, r5, r4);
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
 }
 
 
@@ -3145,8 +3150,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
 
   if (call_type == Call::POSSIBLY_EVAL_CALL) {
     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
-    // to resolve the function we need to call.  Then we call the resolved
-    // function using the given arguments.
+    // 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 = expr->arguments();
     int arg_count = args->length();
 
@@ -3167,8 +3173,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
       __ push(r4);
       EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
+      // The runtime call returns a pair of values in r3 (function) and
+      // r4 (receiver). Touch up the stack with the right values.
       __ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
+      __ StoreP(r4, MemOperand(sp, arg_count * kPointerSize), r0);
 
       PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
     }
@@ -4797,10 +4805,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         context()->Plug(r3);
       } else if (proxy != NULL) {
         Variable* var = proxy->var();
-        // Delete of an unqualified identifier is disallowed in strict mode but
-        // "delete this" is allowed.
-        bool is_this = var->HasThisName(isolate());
-        DCHECK(is_sloppy(language_mode()) || is_this);
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is allowed.
+        DCHECK(is_sloppy(language_mode()) || var->is_this());
         if (var->IsUnallocated()) {
           __ LoadP(r5, GlobalObjectOperand());
           __ mov(r4, Operand(var->name()));
@@ -4811,7 +4818,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         } else if (var->IsStackAllocated() || var->IsContextSlot()) {
           // Result of deleting non-global, non-dynamic variables is false.
           // The subexpression does not have side effects.
-          context()->Plug(is_this);
+          context()->Plug(var->is_this());
         } else {
           // Non-global variable.  Call the runtime to try to delete from the
           // context where the variable was introduced.
index ba92faa3fafe1bca55007012429250f266be7555..09ac2ab96b22ddb0d33dd24ab899fdaeabf1ad34 100644 (file)
@@ -381,10 +381,11 @@ RUNTIME_FUNCTION(Runtime_CompileString) {
 }
 
 
-static Object* CompileGlobalEval(Isolate* isolate, Handle<String> source,
-                                 Handle<SharedFunctionInfo> outer_info,
-                                 LanguageMode language_mode,
-                                 int scope_position) {
+static ObjectPair CompileGlobalEval(Isolate* isolate, Handle<String> source,
+                                    Handle<SharedFunctionInfo> outer_info,
+                                    Handle<Object> receiver,
+                                    LanguageMode language_mode,
+                                    int scope_position) {
   Handle<Context> context = Handle<Context>(isolate->context());
   Handle<Context> native_context = Handle<Context>(context->native_context());
 
@@ -398,7 +399,7 @@ static Object* CompileGlobalEval(Isolate* isolate, Handle<String> source,
     MaybeHandle<Object> maybe_error = isolate->factory()->NewEvalError(
         MessageTemplate::kCodeGenFromStrings, error_message);
     if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
-    return isolate->heap()->exception();
+    return MakePair(isolate->heap()->exception(), NULL);
   }
 
   // Deal with a normal eval call with a string argument. Compile it
@@ -409,14 +410,14 @@ static Object* CompileGlobalEval(Isolate* isolate, Handle<String> source,
       isolate, compiled,
       Compiler::GetFunctionFromEval(source, outer_info, context, language_mode,
                                     restriction, scope_position),
-      isolate->heap()->exception());
-  return *compiled;
+      MakePair(isolate->heap()->exception(), NULL));
+  return MakePair(*compiled, *receiver);
 }
 
 
-RUNTIME_FUNCTION(Runtime_ResolvePossiblyDirectEval) {
+RUNTIME_FUNCTION_RETURN_PAIR(Runtime_ResolvePossiblyDirectEval) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 5);
+  DCHECK(args.length() == 6);
 
   Handle<Object> callee = args.at<Object>(0);
 
@@ -427,17 +428,17 @@ RUNTIME_FUNCTION(Runtime_ResolvePossiblyDirectEval) {
   // the first argument without doing anything).
   if (*callee != isolate->native_context()->global_eval_fun() ||
       !args[1]->IsString()) {
-    return *callee;
+    return MakePair(*callee, isolate->heap()->undefined_value());
   }
 
-  DCHECK(args[3]->IsSmi());
-  DCHECK(is_valid_language_mode(args.smi_at(3)));
-  LanguageMode language_mode = static_cast<LanguageMode>(args.smi_at(3));
   DCHECK(args[4]->IsSmi());
+  DCHECK(is_valid_language_mode(args.smi_at(4)));
+  LanguageMode language_mode = static_cast<LanguageMode>(args.smi_at(4));
+  DCHECK(args[5]->IsSmi());
   Handle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
                                         isolate);
   return CompileGlobalEval(isolate, args.at<String>(1), outer_info,
-                           language_mode, args.smi_at(4));
+                           args.at<Object>(3), language_mode, args.smi_at(5));
 }
 }  // namespace internal
 }  // namespace v8
index 5e87910f7a8a575ed4edff095e921b78eecbf370..f45ce7d0723de497f95b462f7e4e39f413255fa9 100644 (file)
@@ -127,8 +127,7 @@ namespace internal {
   F(NotifyDeoptimized, 1, 1)            \
   F(CompileForOnStackReplacement, 1, 1) \
   F(TryInstallOptimizedCode, 1, 1)      \
-  F(CompileString, 2, 1)                \
-  F(ResolvePossiblyDirectEval, 5, 1)
+  F(CompileString, 2, 1)
 
 
 #define FOR_EACH_INTRINSIC_DATE(F) \
@@ -698,7 +697,8 @@ namespace internal {
 
 #define FOR_EACH_INTRINSIC_RETURN_PAIR(F) \
   F(LoadLookupSlot, 2, 2)                 \
-  F(LoadLookupSlotNoReferenceError, 2, 2)
+  F(LoadLookupSlotNoReferenceError, 2, 2) \
+  F(ResolvePossiblyDirectEval, 6, 2)
 
 
 #define FOR_EACH_INTRINSIC_RETURN_OBJECT(F) \
index 72c36c2665942f0ad9a66a691d342baf791b6008..b819b172c4ad1db78926b0d59dc253d9841de94f 100644 (file)
@@ -6,7 +6,6 @@
 
 #include "src/v8.h"
 
-#include "src/bootstrapper.h"
 #include "src/scopeinfo.h"
 #include "src/scopes.h"
 
@@ -193,77 +192,6 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
 }
 
 
-Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
-  DCHECK(isolate->bootstrapper()->IsActive());
-
-  const int stack_local_count = 0;
-  const int context_local_count = 1;
-  const int strong_mode_free_variable_count = 0;
-  const bool simple_parameter_list = true;
-  const VariableAllocationInfo receiver_info = CONTEXT;
-  const VariableAllocationInfo function_name_info = NONE;
-  const VariableMode function_variable_mode = VAR;
-  const bool has_function_name = false;
-  const bool has_receiver = true;
-  const int parameter_count = 0;
-  const int length = kVariablePartIndex + parameter_count +
-                     (1 + stack_local_count) + 2 * context_local_count +
-                     3 * strong_mode_free_variable_count +
-                     (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
-
-  Factory* factory = isolate->factory();
-  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
-
-  // Encode the flags.
-  int flags = ScopeTypeField::encode(SCRIPT_SCOPE) |
-              CallsEvalField::encode(false) |
-              LanguageModeField::encode(SLOPPY) |
-              ReceiverVariableField::encode(receiver_info) |
-              FunctionVariableField::encode(function_name_info) |
-              FunctionVariableMode::encode(function_variable_mode) |
-              AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
-              IsSimpleParameterListField::encode(simple_parameter_list) |
-              BlockScopeIsClassScopeField::encode(false) |
-              FunctionKindField::encode(FunctionKind::kNormalFunction);
-  scope_info->SetFlags(flags);
-  scope_info->SetParameterCount(parameter_count);
-  scope_info->SetStackLocalCount(stack_local_count);
-  scope_info->SetContextLocalCount(context_local_count);
-  scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
-
-  int index = kVariablePartIndex;
-  const int first_slot_index = 0;
-  DCHECK(index == scope_info->StackLocalFirstSlotIndex());
-  scope_info->set(index++, Smi::FromInt(first_slot_index));
-  DCHECK(index == scope_info->StackLocalEntriesIndex());
-
-  // Here we add info for context-allocated "this".
-  DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
-  scope_info->set(index++, *isolate->factory()->this_string());
-  DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
-  const uint32_t value = ContextLocalMode::encode(CONST) |
-                         ContextLocalInitFlag::encode(kCreatedInitialized) |
-                         ContextLocalMaybeAssignedFlag::encode(kNotAssigned);
-  scope_info->set(index++, Smi::FromInt(value));
-
-  DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
-  DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
-
-  // And here we record that this scopeinfo binds a receiver.
-  DCHECK(index == scope_info->ReceiverEntryIndex());
-  const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
-  scope_info->set(index++, Smi::FromInt(receiver_index));
-
-  DCHECK(index == scope_info->FunctionNameEntryIndex());
-
-  DCHECK_EQ(index, scope_info->length());
-  DCHECK_EQ(scope_info->ParameterCount(), 0);
-  DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
-
-  return scope_info;
-}
-
-
 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
   return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array());
 }
index 83703716d24e927dfe53a4527b39dde897d3e912..c6baba5e29d07abf52c3b3473349dd16e6a5a7bc 100644 (file)
@@ -355,7 +355,8 @@ class Scope: public ZoneObject {
   // "this" (and no other variable) on the native context.  Script scopes then
   // will not have a "this" declaration.
   bool has_this_declaration() const {
-    return (is_function_scope() && !is_arrow_scope()) || is_module_scope();
+    return (is_function_scope() && !is_arrow_scope()) || is_module_scope() ||
+           is_script_scope();
   }
 
   // The variable corresponding to the 'new.target' value.
index 89fe8af2eb774d8f72ce88303ca4a7344d4b6f90..381a83a722a1ad7c0c69978da46f6bc0ea299d8e 100644 (file)
@@ -77,9 +77,8 @@ MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
   if (!maybe_context.ToHandle(&result)) return MaybeHandle<Context>();
   CHECK(result->IsContext());
   // If the snapshot does not contain a custom script, we need to update
-  // the global object for exactly two contexts: the builtins context and the
-  // script context that has the global "this" binding.
-  CHECK(EmbedsScript(isolate) || (*outdated_contexts_out)->length() == 2);
+  // the global object for exactly one context.
+  CHECK(EmbedsScript(isolate) || (*outdated_contexts_out)->length() == 1);
   if (FLAG_profile_deserialization) {
     double ms = timer.Elapsed().InMillisecondsF();
     int bytes = context_data.length();
index 218eefae08e08a0cd937a14e1d158c5b878d1a0c..0cb50c87e985580c1fd1c7fc5ea9b3fde63f4206 100644 (file)
@@ -105,16 +105,6 @@ class Variable: public ZoneObject {
   bool is_this() const { return kind_ == THIS; }
   bool is_arguments() const { return kind_ == ARGUMENTS; }
 
-  // For script scopes, the "this" binding is provided by a ScriptContext added
-  // to the global's ScriptContextTable.  This binding might not statically
-  // resolve to a Variable::THIS binding, instead being DYNAMIC_LOCAL.  However
-  // any variable named "this" does indeed refer to a Variable::THIS binding;
-  // the grammar ensures this to be the case.  So wherever a "this" binding
-  // might be provided by the global, use HasThisName instead of is_this().
-  bool HasThisName(Isolate* isolate) const {
-    return is_this() || *name() == *isolate->factory()->this_string();
-  }
-
   ClassVariable* AsClassVariable() {
     DCHECK(is_class());
     return reinterpret_cast<ClassVariable*>(this);
index ed29faf4ed424d5fa0898ae2a8f48fdc47b3a5a7..f06eaa9384e0215b94118436004bbab583774304 100644 (file)
@@ -3004,6 +3004,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   // Push the enclosing function.
   __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
 
+  // Push the receiver of the enclosing function and do runtime call.
+  Variable* this_var = scope()->LookupThis();
+  DCHECK_NOT_NULL(this_var);
+  __ Push(VarOperand(this_var, rcx));
+
   // Push the language mode.
   __ Push(Smi::FromInt(language_mode()));
 
@@ -3011,7 +3016,7 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   __ Push(Smi::FromInt(scope()->start_position()));
 
   // Do the runtime call.
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
 }
 
 
@@ -3043,8 +3048,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
 
   if (call_type == Call::POSSIBLY_EVAL_CALL) {
     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
-    // to resolve the function we need to call.  Then we call the resolved
-    // function using the given arguments.
+    // 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 = expr->arguments();
     int arg_count = args->length();
     { PreservePositionScope pos_scope(masm()->positions_recorder());
@@ -3061,7 +3066,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
       __ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
       EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the callee.
+      // The runtime call returns a pair of values in rax (function) and
+      // rdx (receiver). Touch up the stack with the right values.
+      __ movp(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
       __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
 
       PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
@@ -4721,10 +4728,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         context()->Plug(rax);
       } else if (proxy != NULL) {
         Variable* var = proxy->var();
-        // Delete of an unqualified identifier is disallowed in strict mode but
-        // "delete this" is allowed.
-        bool is_this = var->HasThisName(isolate());
-        DCHECK(is_sloppy(language_mode()) || is_this);
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is allowed.
+        DCHECK(is_sloppy(language_mode()) || var->is_this());
         if (var->IsUnallocated()) {
           __ Push(GlobalObjectOperand());
           __ Push(var->name());
@@ -4735,7 +4741,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
           // Result of deleting non-global variables is false.  'this' is
           // not really a variable, though we implement it as one.  The
           // subexpression does not have side effects.
-          context()->Plug(is_this);
+          context()->Plug(var->is_this());
         } else {
           // Non-global variable.  Call the runtime to try to delete from the
           // context where the variable was introduced.
index e2abd9d311181c39cf4e8b17f26aea0c4138bf1d..9fbdd03ae0edabea0c190a9be1fbf7bb9908b81b 100644 (file)
@@ -2997,7 +2997,10 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
 
   // Push the enclosing function.
   __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-
+  // Push the receiver of the enclosing function.
+  Variable* this_var = scope()->LookupThis();
+  DCHECK_NOT_NULL(this_var);
+  __ push(VarOperand(this_var, ecx));
   // Push the language mode.
   __ push(Immediate(Smi::FromInt(language_mode())));
 
@@ -3005,7 +3008,7 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   __ push(Immediate(Smi::FromInt(scope()->start_position())));
 
   // Do the runtime call.
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
 }
 
 
@@ -3037,8 +3040,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
 
   if (call_type == Call::POSSIBLY_EVAL_CALL) {
     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
-    // to resolve the function we need to call.  Then we call the resolved
-    // function using the given arguments.
+    // 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 = expr->arguments();
     int arg_count = args->length();
     { PreservePositionScope pos_scope(masm()->positions_recorder());
@@ -3055,7 +3058,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
       __ push(Operand(esp, (arg_count + 1) * kPointerSize));
       EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
+      // The runtime call returns a pair of values in eax (function) and
+      // edx (receiver). Touch up the stack with the right values.
+      __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
       __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
 
       PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
@@ -4688,10 +4693,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         context()->Plug(eax);
       } else if (proxy != NULL) {
         Variable* var = proxy->var();
-        // Delete of an unqualified identifier is disallowed in strict mode but
-        // "delete this" is allowed.
-        bool is_this = var->HasThisName(isolate());
-        DCHECK(is_sloppy(language_mode()) || is_this);
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is allowed.
+        DCHECK(is_sloppy(language_mode()) || var->is_this());
         if (var->IsUnallocated()) {
           __ push(GlobalObjectOperand());
           __ push(Immediate(var->name()));
@@ -4702,7 +4706,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
           // Result of deleting non-global variables is false.  'this' is
           // not really a variable, though we implement it as one.  The
           // subexpression does not have side effects.
-          context()->Plug(is_this);
+          context()->Plug(var->is_this());
         } else {
           // Non-global variable.  Call the runtime to try to delete from the
           // context where the variable was introduced.
index bb257cb0a5f5ee3085f203a2d8e25951e1eb5235..7737cfeeed72d68cc03350c47aa70113fe3eb1d8 100644 (file)
@@ -83,7 +83,7 @@ class JSTypeFeedbackTest : public TypedGraphTest {
     Node* context = UndefinedConstant();
 
     Unique<Name> name = Unique<Name>::CreateUninitialized(
-        isolate()->factory()->InternalizeUtf8String(string));
+        isolate()->factory()->NewStringFromAsciiChecked(string));
     const Operator* op = javascript()->LoadNamed(name, feedback);
     Node* load = graph()->NewNode(op, global, vector, context);
     if (mode == JSTypeFeedbackSpecializer::kDeoptimizationEnabled) {