Support for global var shortcuts in script contexts.
authorishell <ishell@chromium.org>
Mon, 6 Jul 2015 16:36:28 +0000 (09:36 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 6 Jul 2015 16:36:39 +0000 (16:36 +0000)
Review URL: https://codereview.chromium.org/1218783005

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

34 files changed:
src/arm/full-codegen-arm.cc
src/arm64/full-codegen-arm64.cc
src/ast.cc
src/ast.h
src/compiler/ast-graph-builder.cc
src/contexts.cc
src/contexts.h
src/factory.cc
src/globals.h
src/heap/heap.cc
src/heap/heap.h
src/hydrogen.cc
src/ia32/full-codegen-ia32.cc
src/liveedit.cc
src/mips/full-codegen-mips.cc
src/mips64/full-codegen-mips64.cc
src/objects.h
src/parser.cc
src/ppc/full-codegen-ppc.cc
src/prettyprinter.cc
src/runtime/runtime-debug.cc
src/runtime/runtime-scopes.cc
src/scopeinfo.cc
src/scopeinfo.h
src/scopes.cc
src/scopes.h
src/typing.cc
src/variables.cc
src/variables.h
src/x64/full-codegen-x64.cc
src/x87/full-codegen-x87.cc
test/cctest/compiler/test-loop-assignment-analysis.cc
test/cctest/test-feedback-vector.cc
test/mjsunit/call-counts.js

index 059ffe6..65abe07 100644 (file)
@@ -351,7 +351,7 @@ void FullCodeGenerator::Generate() {
         VariableDeclaration* function = scope()->function();
         DCHECK(function->proxy()->var()->mode() == CONST ||
                function->proxy()->var()->mode() == CONST_LEGACY);
-        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
+        DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot());
         VisitVariableDeclaration(function);
       }
       VisitDeclarations(scope()->declarations());
@@ -875,7 +875,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
   Variable* variable = proxy->var();
   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       globals_->Add(variable->name(), zone());
       globals_->Add(variable->binding_needs_init()
                         ? isolate()->factory()->the_hole_value()
@@ -883,8 +884,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
                     zone());
       break;
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
@@ -892,7 +893,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         EmitDebugCheckDeclarationContext(variable);
@@ -903,7 +904,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
       __ mov(r2, Operand(variable->name()));
       // Declaration nodes are always introduced in one of four modes.
@@ -934,7 +935,8 @@ void FullCodeGenerator::VisitFunctionDeclaration(
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       globals_->Add(variable->name(), zone());
       Handle<SharedFunctionInfo> function =
           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
@@ -944,15 +946,15 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       VisitForAccumulatorValue(declaration->fun());
       __ str(result_register(), StackOperand(variable));
       break;
     }
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       VisitForAccumulatorValue(declaration->fun());
@@ -971,7 +973,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       __ mov(r2, Operand(variable->name()));
       __ mov(r1, Operand(Smi::FromInt(NONE)));
@@ -989,20 +991,21 @@ void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       // TODO(rossberg)
       break;
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ ImportDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       // TODO(rossberg)
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::LOOKUP:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::LOOKUP:
       UNREACHABLE();
   }
 }
@@ -1499,7 +1502,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
   // Three cases: global variables, lookup variables, and all other types of
   // variables.
   switch (var->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Comment cmnt(masm_, "[ Global variable");
       __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
       __ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
@@ -1510,9 +1514,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
                                                : "[ Stack variable");
       if (var->binding_needs_init()) {
@@ -1581,7 +1585,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ Lookup variable");
       Label done, slow;
       // Generate code for loading from variables potentially shadowed
@@ -2737,7 +2741,7 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
                                                FeedbackVectorICSlot slot) {
-  if (var->IsUnallocated()) {
+  if (var->IsUnallocatedOrGlobalSlot()) {
     // Global var, const, or let.
     __ mov(StoreDescriptor::NameRegister(), Operand(var->name()));
     __ ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
@@ -4797,7 +4801,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // "delete this" is allowed.
         bool is_this = var->HasThisName(isolate());
         DCHECK(is_sloppy(language_mode()) || is_this);
-        if (var->IsUnallocated()) {
+        if (var->IsUnallocatedOrGlobalSlot()) {
           __ ldr(r2, GlobalObjectOperand());
           __ mov(r1, Operand(var->name()));
           __ mov(r0, Operand(Smi::FromInt(SLOPPY)));
@@ -5154,7 +5158,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   DCHECK(!context()->IsEffect());
   DCHECK(!context()->IsTest());
   VariableProxy* proxy = expr->AsVariableProxy();
-  if (proxy != NULL && proxy->var()->IsUnallocated()) {
+  if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
     Comment cmnt(masm_, "[ Global variable");
     __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
     __ mov(LoadDescriptor::NameRegister(), Operand(proxy->name()));
index 0345751..ece2017 100644 (file)
@@ -354,7 +354,7 @@ void FullCodeGenerator::Generate() {
         VariableDeclaration* function = scope()->function();
         DCHECK(function->proxy()->var()->mode() == CONST ||
                function->proxy()->var()->mode() == CONST_LEGACY);
-        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
+        DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot());
         VisitVariableDeclaration(function);
       }
       VisitDeclarations(scope()->declarations());
@@ -873,7 +873,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
 
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       globals_->Add(variable->name(), zone());
       globals_->Add(variable->binding_needs_init()
                         ? isolate()->factory()->the_hole_value()
@@ -881,8 +882,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
                     zone());
       break;
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         __ LoadRoot(x10, Heap::kTheHoleValueRootIndex);
@@ -890,7 +891,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         EmitDebugCheckDeclarationContext(variable);
@@ -901,7 +902,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
       __ Mov(x2, Operand(variable->name()));
       // Declaration nodes are always introduced in one of four modes.
@@ -932,7 +933,8 @@ void FullCodeGenerator::VisitFunctionDeclaration(
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       globals_->Add(variable->name(), zone());
       Handle<SharedFunctionInfo> function =
           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
@@ -942,15 +944,15 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       Comment cmnt(masm_, "[ Function Declaration");
       VisitForAccumulatorValue(declaration->fun());
       __ Str(result_register(), StackOperand(variable));
       break;
     }
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ Function Declaration");
       EmitDebugCheckDeclarationContext(variable);
       VisitForAccumulatorValue(declaration->fun());
@@ -969,7 +971,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ Function Declaration");
       __ Mov(x2, Operand(variable->name()));
       __ Mov(x1, Smi::FromInt(NONE));
@@ -987,20 +989,21 @@ void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       // TODO(rossberg)
       break;
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ ImportDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       // TODO(rossberg)
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::LOOKUP:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::LOOKUP:
       UNREACHABLE();
   }
 }
@@ -1478,7 +1481,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
   // Three cases: global variables, lookup variables, and all other types of
   // variables.
   switch (var->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Comment cmnt(masm_, "Global variable");
       __ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
       __ Mov(LoadDescriptor::NameRegister(), Operand(var->name()));
@@ -1489,9 +1493,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, var->IsContextSlot()
                               ? "Context variable"
                               : "Stack variable");
@@ -1561,7 +1565,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Label done, slow;
       // Generate code for loading from variables potentially shadowed by
       // eval-introduced variables.
@@ -2423,7 +2427,7 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
                                                FeedbackVectorICSlot slot) {
   ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment");
-  if (var->IsUnallocated()) {
+  if (var->IsUnallocatedOrGlobalSlot()) {
     // Global var, const, or let.
     __ Mov(StoreDescriptor::NameRegister(), Operand(var->name()));
     __ Ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
@@ -4486,7 +4490,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // "delete this" is allowed.
         bool is_this = var->HasThisName(isolate());
         DCHECK(is_sloppy(language_mode()) || is_this);
-        if (var->IsUnallocated()) {
+        if (var->IsUnallocatedOrGlobalSlot()) {
           __ Ldr(x12, GlobalObjectMemOperand());
           __ Mov(x11, Operand(var->name()));
           __ Mov(x10, Smi::FromInt(SLOPPY));
@@ -4841,7 +4845,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   DCHECK(!context()->IsEffect());
   DCHECK(!context()->IsTest());
   VariableProxy* proxy = expr->AsVariableProxy();
-  if (proxy != NULL && proxy->var()->IsUnallocated()) {
+  if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
     Comment cmnt(masm_, "Global variable");
     __ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
     __ Mov(LoadDescriptor::NameRegister(), Operand(proxy->name()));
index 93331d5..8ce5e7e 100644 (file)
@@ -54,7 +54,7 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
   Variable* var = var_proxy->var();
   // The global identifier "undefined" is immutable. Everything
   // else could be reassigned.
-  return var != NULL && var->location() == Variable::UNALLOCATED &&
+  return var != NULL && var->IsUnallocatedOrGlobalSlot() &&
          var_proxy->raw_name()->IsOneByteEqualTo("undefined");
 }
 
@@ -95,7 +95,7 @@ void VariableProxy::BindTo(Variable* var) {
 void VariableProxy::SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                                            ICSlotCache* cache) {
   variable_feedback_slot_ = slot;
-  if (var()->IsUnallocated()) {
+  if (var()->IsUnallocatedOrGlobalSlot()) {
     cache->Add(VariableICSlotPair(var(), slot));
   }
 }
@@ -106,7 +106,7 @@ FeedbackVectorRequirements VariableProxy::ComputeFeedbackRequirements(
   if (UsesVariableFeedbackSlot()) {
     // VariableProxies that point to the same Variable within a function can
     // make their loads from the same IC slot.
-    if (var()->IsUnallocated()) {
+    if (var()->IsUnallocatedOrGlobalSlot()) {
       for (int i = 0; i < cache->length(); i++) {
         VariableICSlotPair& pair = cache->at(i);
         if (pair.variable() == var()) {
@@ -127,7 +127,7 @@ static int GetStoreICSlots(Expression* expr) {
     Property* property = expr->AsProperty();
     LhsKind assign_type = Property::GetAssignType(property);
     if ((assign_type == VARIABLE &&
-         expr->AsVariableProxy()->var()->IsUnallocated()) ||
+         expr->AsVariableProxy()->var()->IsUnallocatedOrGlobalSlot()) ||
         assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) {
       ic_slots++;
     }
@@ -289,7 +289,8 @@ FeedbackVectorRequirements ClassLiteral::ComputeFeedbackRequirements(
     if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
   }
 
-  if (scope() != NULL && class_variable_proxy()->var()->IsUnallocated()) {
+  if (scope() != NULL &&
+      class_variable_proxy()->var()->IsUnallocatedOrGlobalSlot()) {
     ic_slots++;
   }
 
@@ -752,7 +753,7 @@ Call::CallType Call::GetCallType(Isolate* isolate) const {
   if (proxy != NULL) {
     if (proxy->var()->is_possibly_eval(isolate)) {
       return POSSIBLY_EVAL_CALL;
-    } else if (proxy->var()->IsUnallocated()) {
+    } else if (proxy->var()->IsUnallocatedOrGlobalSlot()) {
       return GLOBAL_CALL;
     } else if (proxy->var()->IsLookupSlot()) {
       return LOOKUP_SLOT_CALL;
index c281408..e5842c2 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1660,7 +1660,7 @@ class VariableProxy final : public Expression {
   void BindTo(Variable* var);
 
   bool UsesVariableFeedbackSlot() const {
-    return var()->IsUnallocated() || var()->IsLookupSlot();
+    return var()->IsUnallocatedOrGlobalSlot() || var()->IsLookupSlot();
   }
 
   virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
@@ -1853,7 +1853,7 @@ class Call final : public Expression {
 
   bool global_call() const {
     VariableProxy* proxy = expression_->AsVariableProxy();
-    return proxy != NULL && proxy->var()->IsUnallocated();
+    return proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot();
   }
 
   bool known_global_function() const {
index 31cd3fd..93a33f5 100644 (file)
@@ -638,8 +638,8 @@ void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
 // Gets the bailout id just before reading a variable proxy, but only for
 // unallocated variables.
 static BailoutId BeforeId(VariableProxy* proxy) {
-  return proxy->var()->location() == Variable::UNALLOCATED ? proxy->BeforeId()
-                                                           : BailoutId::None();
+  return proxy->var()->IsUnallocatedOrGlobalSlot() ? proxy->BeforeId()
+                                                   : BailoutId::None();
 }
 
 
@@ -1057,7 +1057,8 @@ void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
   VariableMode mode = decl->mode();
   bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Handle<Oddball> value = variable->binding_needs_init()
                                   ? isolate()->factory()->the_hole_value()
                                   : isolate()->factory()->undefined_value();
@@ -1065,21 +1066,21 @@ void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
       globals()->push_back(value);
       break;
     }
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         Node* value = jsgraph()->TheHoleConstant();
         environment()->Bind(variable, value);
       }
       break;
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         Node* value = jsgraph()->TheHoleConstant();
         const Operator* op = javascript()->StoreContext(0, variable->index());
         NewNode(op, current_context(), value);
       }
       break;
-    case Variable::LOOKUP:
+    case VariableLocation::LOOKUP:
       UNIMPLEMENTED();
   }
 }
@@ -1088,7 +1089,8 @@ void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
   Variable* variable = decl->proxy()->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
           decl->fun(), info()->script(), info());
       // Check for stack-overflow exception.
@@ -1097,21 +1099,21 @@ void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
       globals()->push_back(function);
       break;
     }
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       VisitForValue(decl->fun());
       Node* value = environment()->Pop();
       environment()->Bind(variable, value);
       break;
     }
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       VisitForValue(decl->fun());
       Node* value = environment()->Pop();
       const Operator* op = javascript()->StoreContext(0, variable->index());
       NewNode(op, current_context(), value);
       break;
     }
-    case Variable::LOOKUP:
+    case VariableLocation::LOOKUP:
       UNIMPLEMENTED();
   }
 }
@@ -2084,9 +2086,9 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
   switch (assign_type) {
     case VARIABLE: {
       Variable* variable = expr->target()->AsVariableProxy()->var();
-      if (variable->location() == Variable::PARAMETER ||
-          variable->location() == Variable::LOCAL ||
-          variable->location() == Variable::CONTEXT) {
+      if (variable->location() == VariableLocation::PARAMETER ||
+          variable->location() == VariableLocation::LOCAL ||
+          variable->location() == VariableLocation::CONTEXT) {
         needs_frame_state_before = false;
       }
       break;
@@ -2342,7 +2344,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
     }
     case Call::LOOKUP_SLOT_CALL: {
       Variable* variable = callee->AsVariableProxy()->var();
-      DCHECK(variable->location() == Variable::LOOKUP);
+      DCHECK(variable->location() == VariableLocation::LOOKUP);
       Node* name = jsgraph()->Constant(variable->name());
       const Operator* op =
           javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
@@ -3236,7 +3238,8 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
   Node* the_hole = jsgraph()->TheHoleConstant();
   VariableMode mode = variable->mode();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       // Global var, const, or let variable.
       Node* global = BuildLoadGlobalObject();
       Handle<Name> name = variable->name();
@@ -3244,8 +3247,8 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
       states.AddToNode(value, bailout_id, combine);
       return value;
     }
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       // Local var, const, or let variable.
       Node* value = environment()->Lookup(variable);
       if (mode == CONST_LEGACY) {
@@ -3266,7 +3269,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
       }
       return value;
     }
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       // Context variable (potentially up the context chain).
       int depth = current_scope()->ContextChainLength(variable->scope());
       bool immutable = variable->maybe_assigned() == kNotAssigned;
@@ -3286,7 +3289,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
       }
       return value;
     }
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       // Dynamic lookup of context variable (anywhere in the chain).
       Node* value = jsgraph()->TheHoleConstant();
       Handle<String> name = variable->name();
@@ -3298,7 +3301,8 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
         states.AddToNode(value, bailout_id, combine);
       } else if (mode == DYNAMIC_LOCAL) {
         Variable* local = variable->local_if_not_shadowed();
-        DCHECK(local->location() == Variable::CONTEXT);  // Must be context.
+        DCHECK(local->location() ==
+               VariableLocation::CONTEXT);  // Must be context.
         int depth = current_scope()->ContextChainLength(local->scope());
         uint32_t check_bitset = ComputeBitsetForDynamicContext(variable);
         const Operator* op = javascript()->LoadDynamicContext(
@@ -3333,7 +3337,8 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
                                            BailoutId bailout_id,
                                            OutputFrameStateCombine combine) {
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       // Global var, const, or let variable.
       Node* global = BuildLoadGlobalObject();
       Node* name = jsgraph()->Constant(variable->name());
@@ -3342,13 +3347,13 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
       PrepareFrameState(result, bailout_id, combine);
       return result;
     }
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::CONTEXT: {
       // Local var, const, or let variable or context variable.
       return jsgraph()->BooleanConstant(variable->HasThisName(isolate()));
     }
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       // Dynamic lookup of context variable (anywhere in the chain).
       Node* name = jsgraph()->Constant(variable->name());
       const Operator* op =
@@ -3370,7 +3375,8 @@ Node* AstGraphBuilder::BuildVariableAssignment(
   Node* the_hole = jsgraph()->TheHoleConstant();
   VariableMode mode = variable->mode();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       // Global var, const, or let variable.
       Node* global = BuildLoadGlobalObject();
       Handle<Name> name = variable->name();
@@ -3379,8 +3385,8 @@ Node* AstGraphBuilder::BuildVariableAssignment(
       states.AddToNode(store, bailout_id, combine);
       return store;
     }
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       // Local var, const, or let variable.
       if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
         // Perform an initialization check for legacy const variables.
@@ -3419,7 +3425,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
       }
       environment()->Bind(variable, value);
       return value;
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       // Context variable (potentially up the context chain).
       int depth = current_scope()->ContextChainLength(variable->scope());
       if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
@@ -3453,7 +3459,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
       const Operator* op = javascript()->StoreContext(depth, variable->index());
       return NewNode(op, current_context(), value);
     }
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       // Dynamic lookup of context variable (anywhere in the chain).
       Node* name = jsgraph()->Constant(variable->name());
       Node* language = jsgraph()->Constant(language_mode());
index 0c27681..b29405b 100644 (file)
@@ -40,10 +40,10 @@ bool ScriptContextTable::Lookup(Handle<ScriptContextTable> table,
     DCHECK(context->IsScriptContext());
     Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
     int slot_index = ScopeInfo::ContextSlotIndex(
-        scope_info, name, &result->mode, &result->init_flag,
+        scope_info, name, &result->mode, &result->location, &result->init_flag,
         &result->maybe_assigned_flag);
 
-    if (slot_index >= 0) {
+    if (slot_index >= 0 && result->location == VariableLocation::CONTEXT) {
       result->context_index = i;
       result->slot_index = slot_index;
       return true;
@@ -287,14 +287,15 @@ Handle<Object> Context::Lookup(Handle<String> name,
             ScopeInfo::cast(context->extension()), isolate);
       }
       VariableMode mode;
+      VariableLocation location;
       InitializationFlag init_flag;
       // TODO(sigurds) Figure out whether maybe_assigned_flag should
       // be used to compute binding_flags.
       MaybeAssignedFlag maybe_assigned_flag;
       int slot_index = ScopeInfo::ContextSlotIndex(
-          scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
+          scope_info, name, &mode, &location, &init_flag, &maybe_assigned_flag);
       DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS);
-      if (slot_index >= 0) {
+      if (slot_index >= 0 && location == VariableLocation::CONTEXT) {
         if (FLAG_trace_contexts) {
           PrintF("=> found local in context slot %d (mode = %d)\n",
                  slot_index, mode);
@@ -352,6 +353,27 @@ Handle<Object> Context::Lookup(Handle<String> name,
 }
 
 
+void Context::InitializeGlobalSlots() {
+  DCHECK(IsScriptContext());
+  DisallowHeapAllocation no_gc;
+
+  ScopeInfo* scope_info = ScopeInfo::cast(extension());
+
+  int context_globals = scope_info->ContextGlobalCount();
+  if (context_globals > 0) {
+    PropertyCell* empty_cell = GetHeap()->empty_property_cell();
+
+    int context_locals = scope_info->ContextLocalCount();
+    int index = Context::MIN_CONTEXT_SLOTS + context_locals;
+    for (int i = 0; i < context_globals; i++) {
+      // Clear both read and write slots.
+      set(index++, empty_cell);
+      set(index++, empty_cell);
+    }
+  }
+}
+
+
 void Context::AddOptimizedFunction(JSFunction* function) {
   DCHECK(IsNativeContext());
 #ifdef ENABLE_SLOW_DCHECKS
index 6412b4f..1210848 100644 (file)
@@ -226,6 +226,7 @@ class ScriptContextTable : public FixedArray {
     int context_index;
     int slot_index;
     VariableMode mode;
+    VariableLocation location;
     InitializationFlag init_flag;
     MaybeAssignedFlag maybe_assigned_flag;
   };
@@ -558,6 +559,9 @@ class Context: public FixedArray {
         that->global_object()->native_context()->security_token();
   }
 
+  // Initializes global variable bindings in given script context.
+  void InitializeGlobalSlots();
+
   // A native context holds a list of all functions with optimized code.
   void AddOptimizedFunction(JSFunction* function);
   void RemoveOptimizedFunction(JSFunction* function);
index 7df095d..2b79a5b 100644 (file)
@@ -689,7 +689,8 @@ Handle<Symbol> Factory::NewPrivateSymbol(Handle<Object> name) {
 
 
 Handle<Context> Factory::NewNativeContext() {
-  Handle<FixedArray> array = NewFixedArray(Context::NATIVE_CONTEXT_SLOTS);
+  Handle<FixedArray> array =
+      NewFixedArray(Context::NATIVE_CONTEXT_SLOTS, TENURED);
   array->set_map_no_write_barrier(*native_context_map());
   Handle<Context> context = Handle<Context>::cast(array);
   context->set_js_array_maps(*undefined_value());
index 0f6fa2f..f85e929 100644 (file)
@@ -851,6 +851,40 @@ inline bool IsImmutableVariableMode(VariableMode mode) {
 }
 
 
+enum class VariableLocation {
+  // Before and during variable allocation, a variable whose location is
+  // not yet determined.  After allocation, a variable looked up as a
+  // property on the global object (and possibly absent).  name() is the
+  // variable name, index() is invalid.
+  UNALLOCATED,
+
+  // A slot in the parameter section on the stack.  index() is the
+  // parameter index, counting left-to-right.  The receiver is index -1;
+  // the first parameter is index 0.
+  PARAMETER,
+
+  // A slot in the local section on the stack.  index() is the variable
+  // index in the stack frame, starting at 0.
+  LOCAL,
+
+  // An indexed slot in a heap context.  index() is the variable index in
+  // the context object on the heap, starting at 0.  scope() is the
+  // corresponding scope.
+  CONTEXT,
+
+  // An indexed slot in a script context that contains a respective global
+  // property cell.  name() is the variable name, index() is the variable
+  // index in the context object on the heap, starting at 0.  scope() is the
+  // corresponding script scope.
+  GLOBAL,
+
+  // A named slot in a heap context.  name() is the variable name in the
+  // context object on the heap, with lookup starting at the current
+  // context.  index() is invalid.
+  LOOKUP
+};
+
+
 // ES6 Draft Rev3 10.2 specifies declarative environment records with mutable
 // and immutable bindings that can be in two states: initialized and
 // uninitialized. In ES5 only immutable bindings have these two states. When
index 56a7941..51d4dfe 100644 (file)
@@ -3409,6 +3409,10 @@ void Heap::CreateInitialObjects() {
   cell->set_value(Smi::FromInt(Isolate::kArrayProtectorValid));
   set_array_protector(*cell);
 
+  cell = factory->NewPropertyCell();
+  cell->set_value(the_hole_value());
+  set_empty_property_cell(*cell);
+
   set_weak_stack_trace_list(Smi::FromInt(0));
 
   set_allocation_sites_scratchpad(
index 3ce381d..be280a0 100644 (file)
@@ -192,6 +192,7 @@ namespace internal {
   V(ArrayList, retained_maps, RetainedMaps)                                    \
   V(WeakHashTable, weak_object_to_code_table, WeakObjectToCodeTable)           \
   V(PropertyCell, array_protector, ArrayProtector)                             \
+  V(PropertyCell, empty_property_cell, EmptyPropertyCell)                      \
   V(Object, weak_stack_trace_list, WeakStackTraceList)
 
 // Entries in this list are limited to Smis and are not visited during GC.
index ae3b715..640befc 100644 (file)
@@ -5411,7 +5411,8 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
   DCHECK(current_block()->HasPredecessor());
   Variable* variable = expr->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       if (IsLexicalVariableMode(variable->mode())) {
         // TODO(rossberg): should this be an DCHECK?
         return Bailout(kReferenceToGlobalLexicalVariable);
@@ -5517,8 +5518,8 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
       }
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       HValue* value = LookupAndMakeLive(variable);
       if (value == graph()->GetConstantHole()) {
         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
@@ -5528,7 +5529,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
       return ast_context()->ReturnValue(value);
     }
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       HValue* context = BuildContextChainWalk(variable);
       HLoadContextSlot::Mode mode;
       switch (variable->mode()) {
@@ -5548,7 +5549,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
       return ast_context()->ReturnInstruction(instr, expr->id());
     }
 
-    case Variable::LOOKUP:
+    case VariableLocation::LOOKUP:
       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
   }
 }
@@ -6759,14 +6760,15 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
     CHECK_ALIVE(VisitForValue(operation));
 
     switch (var->location()) {
-      case Variable::UNALLOCATED:
+      case VariableLocation::GLOBAL:
+      case VariableLocation::UNALLOCATED:
         HandleGlobalVariableAssignment(var,
                                        Top(),
                                        expr->AssignmentId());
         break;
 
-      case Variable::PARAMETER:
-      case Variable::LOCAL:
+      case VariableLocation::PARAMETER:
+      case VariableLocation::LOCAL:
         if (var->mode() == CONST_LEGACY)  {
           return Bailout(kUnsupportedConstCompoundAssignment);
         }
@@ -6776,7 +6778,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
         BindIfLive(var, Top());
         break;
 
-      case Variable::CONTEXT: {
+      case VariableLocation::CONTEXT: {
         // Bail out if we try to mutate a parameter value in a function
         // using the arguments object.  We do not (yet) correctly handle the
         // arguments property of the function.
@@ -6815,7 +6817,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
         break;
       }
 
-      case Variable::LOOKUP:
+      case VariableLocation::LOOKUP:
         return Bailout(kCompoundAssignmentToLookupSlot);
     }
     return ast_context()->ReturnValue(Pop());
@@ -6885,15 +6887,16 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
 
     // Handle the assignment.
     switch (var->location()) {
-      case Variable::UNALLOCATED:
+      case VariableLocation::GLOBAL:
+      case VariableLocation::UNALLOCATED:
         CHECK_ALIVE(VisitForValue(expr->value()));
         HandleGlobalVariableAssignment(var,
                                        Top(),
                                        expr->AssignmentId());
         return ast_context()->ReturnValue(Pop());
 
-      case Variable::PARAMETER:
-      case Variable::LOCAL: {
+      case VariableLocation::PARAMETER:
+      case VariableLocation::LOCAL: {
         // Perform an initialization check for let declared variables
         // or parameters.
         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
@@ -6911,7 +6914,7 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
         return ast_context()->ReturnValue(value);
       }
 
-      case Variable::CONTEXT: {
+      case VariableLocation::CONTEXT: {
         // Bail out if we try to mutate a parameter value in a function using
         // the arguments object.  We do not (yet) correctly handle the
         // arguments property of the function.
@@ -6961,7 +6964,7 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
         return ast_context()->ReturnValue(Pop());
       }
 
-      case Variable::LOOKUP:
+      case VariableLocation::LOOKUP:
         return Bailout(kAssignmentToLOOKUPVariable);
     }
   } else {
@@ -10218,7 +10221,7 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
     return ast_context()->ReturnInstruction(instr, expr->id());
   } else if (proxy != NULL) {
     Variable* var = proxy->var();
-    if (var->IsUnallocated()) {
+    if (var->IsUnallocatedOrGlobalSlot()) {
       Bailout(kDeleteWithGlobalVariable);
     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
       // Result of deleting non-global variables is false.  'this' is not really
@@ -10404,18 +10407,19 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
     Push(after);
 
     switch (var->location()) {
-      case Variable::UNALLOCATED:
+      case VariableLocation::GLOBAL:
+      case VariableLocation::UNALLOCATED:
         HandleGlobalVariableAssignment(var,
                                        after,
                                        expr->AssignmentId());
         break;
 
-      case Variable::PARAMETER:
-      case Variable::LOCAL:
+      case VariableLocation::PARAMETER:
+      case VariableLocation::LOCAL:
         BindIfLive(var, after);
         break;
 
-      case Variable::CONTEXT: {
+      case VariableLocation::CONTEXT: {
         // Bail out if we try to mutate a parameter value in a function
         // using the arguments object.  We do not (yet) correctly handle the
         // arguments property of the function.
@@ -10442,7 +10446,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
         break;
       }
 
-      case Variable::LOOKUP:
+      case VariableLocation::LOOKUP:
         return Bailout(kLookupVariableInCountOperation);
     }
 
@@ -11664,20 +11668,21 @@ void HOptimizedGraphBuilder::VisitVariableDeclaration(
   Variable* variable = proxy->var();
   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       globals_.Add(variable->name(), zone());
       globals_.Add(variable->binding_needs_init()
                        ? isolate()->factory()->the_hole_value()
                        : isolate()->factory()->undefined_value(), zone());
       return;
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         HValue* value = graph()->GetConstantHole();
         environment()->Bind(variable, value);
       }
       break;
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         HValue* value = graph()->GetConstantHole();
         HValue* context = environment()->context();
@@ -11688,7 +11693,7 @@ void HOptimizedGraphBuilder::VisitVariableDeclaration(
         }
       }
       break;
-    case Variable::LOOKUP:
+    case VariableLocation::LOOKUP:
       return Bailout(kUnsupportedLookupSlotInDeclaration);
   }
 }
@@ -11699,7 +11704,8 @@ void HOptimizedGraphBuilder::VisitFunctionDeclaration(
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       globals_.Add(variable->name(), zone());
       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
           declaration->fun(), current_info()->script(), top_info());
@@ -11708,14 +11714,14 @@ void HOptimizedGraphBuilder::VisitFunctionDeclaration(
       globals_.Add(function, zone());
       return;
     }
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       CHECK_ALIVE(VisitForValue(declaration->fun()));
       HValue* value = Pop();
       BindIfLive(variable, value);
       break;
     }
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       CHECK_ALIVE(VisitForValue(declaration->fun()));
       HValue* value = Pop();
       HValue* context = environment()->context();
@@ -11726,7 +11732,7 @@ void HOptimizedGraphBuilder::VisitFunctionDeclaration(
       }
       break;
     }
-    case Variable::LOOKUP:
+    case VariableLocation::LOOKUP:
       return Bailout(kUnsupportedLookupSlotInDeclaration);
   }
 }
index 132a949..5fd4414 100644 (file)
@@ -353,7 +353,7 @@ void FullCodeGenerator::Generate() {
         VariableDeclaration* function = scope()->function();
         DCHECK(function->proxy()->var()->mode() == CONST ||
                function->proxy()->var()->mode() == CONST_LEGACY);
-        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
+        DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot());
         VisitVariableDeclaration(function);
       }
       VisitDeclarations(scope()->declarations());
@@ -823,15 +823,16 @@ void FullCodeGenerator::VisitVariableDeclaration(
   Variable* variable = proxy->var();
   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       globals_->Add(variable->name(), zone());
       globals_->Add(variable->binding_needs_init()
                         ? isolate()->factory()->the_hole_value()
                         : isolate()->factory()->undefined_value(), zone());
       break;
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         __ mov(StackOperand(variable),
@@ -839,7 +840,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         EmitDebugCheckDeclarationContext(variable);
@@ -850,7 +851,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
       __ push(esi);
       __ push(Immediate(variable->name()));
@@ -880,7 +881,8 @@ void FullCodeGenerator::VisitFunctionDeclaration(
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       globals_->Add(variable->name(), zone());
       Handle<SharedFunctionInfo> function =
           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
@@ -890,15 +892,15 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       VisitForAccumulatorValue(declaration->fun());
       __ mov(StackOperand(variable), result_register());
       break;
     }
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       VisitForAccumulatorValue(declaration->fun());
@@ -915,7 +917,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       __ push(esi);
       __ push(Immediate(variable->name()));
@@ -932,20 +934,21 @@ void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       // TODO(rossberg)
       break;
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ ImportDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       // TODO(rossberg)
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::LOOKUP:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::LOOKUP:
       UNREACHABLE();
   }
 }
@@ -1426,7 +1429,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
   // Three cases: global variables, lookup variables, and all other types of
   // variables.
   switch (var->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Comment cmnt(masm_, "[ Global variable");
       __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
       __ mov(LoadDescriptor::NameRegister(), var->name());
@@ -1437,9 +1441,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
                                                : "[ Stack variable");
       if (var->binding_needs_init()) {
@@ -1507,7 +1511,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ Lookup variable");
       Label done, slow;
       // Generate code for loading from variables potentially shadowed
@@ -2645,7 +2649,7 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
                                                FeedbackVectorICSlot slot) {
-  if (var->IsUnallocated()) {
+  if (var->IsUnallocatedOrGlobalSlot()) {
     // Global var, const, or let.
     __ mov(StoreDescriptor::NameRegister(), var->name());
     __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
@@ -4728,7 +4732,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // "delete this" is allowed.
         bool is_this = var->HasThisName(isolate());
         DCHECK(is_sloppy(language_mode()) || is_this);
-        if (var->IsUnallocated()) {
+        if (var->IsUnallocatedOrGlobalSlot()) {
           __ push(GlobalObjectOperand());
           __ push(Immediate(var->name()));
           __ push(Immediate(Smi::FromInt(SLOPPY)));
@@ -5093,7 +5097,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   DCHECK(!context()->IsEffect());
   DCHECK(!context()->IsTest());
 
-  if (proxy != NULL && proxy->var()->IsUnallocated()) {
+  if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
     Comment cmnt(masm_, "[ Global variable");
     __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
     __ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name()));
index afa0e13..150dcb8 100644 (file)
@@ -764,7 +764,10 @@ class FunctionInfoListener {
       ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone);
       ZoneList<Variable*> context_list(
           current_scope->ContextLocalCount(), zone);
-      current_scope->CollectStackAndContextLocals(&stack_list, &context_list);
+      ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(),
+                                       zone);
+      current_scope->CollectStackAndContextLocals(&stack_list, &context_list,
+                                                  &globals_list);
       context_list.Sort(&Variable::CompareIndex);
 
       for (int i = 0; i < context_list.length(); i++) {
index b9df1e1..de4f424 100644 (file)
@@ -369,7 +369,7 @@ void FullCodeGenerator::Generate() {
         VariableDeclaration* function = scope()->function();
         DCHECK(function->proxy()->var()->mode() == CONST ||
                function->proxy()->var()->mode() == CONST_LEGACY);
-        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
+        DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot());
         VisitVariableDeclaration(function);
       }
       VisitDeclarations(scope()->declarations());
@@ -875,7 +875,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
   Variable* variable = proxy->var();
   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       globals_->Add(variable->name(), zone());
       globals_->Add(variable->binding_needs_init()
                         ? isolate()->factory()->the_hole_value()
@@ -883,8 +884,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
                     zone());
       break;
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
@@ -892,7 +893,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-      case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         EmitDebugCheckDeclarationContext(variable);
@@ -903,7 +904,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
       __ li(a2, Operand(variable->name()));
       // Declaration nodes are always introduced in one of four modes.
@@ -935,7 +936,8 @@ void FullCodeGenerator::VisitFunctionDeclaration(
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       globals_->Add(variable->name(), zone());
       Handle<SharedFunctionInfo> function =
           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
@@ -945,15 +947,15 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       VisitForAccumulatorValue(declaration->fun());
       __ sw(result_register(), StackOperand(variable));
       break;
     }
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       VisitForAccumulatorValue(declaration->fun());
@@ -972,7 +974,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       __ li(a2, Operand(variable->name()));
       __ li(a1, Operand(Smi::FromInt(NONE)));
@@ -990,20 +992,21 @@ void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       // TODO(rossberg)
       break;
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ ImportDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       // TODO(rossberg)
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::LOOKUP:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::LOOKUP:
       UNREACHABLE();
   }
 }
@@ -1491,7 +1494,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
   // Three cases: global variables, lookup variables, and all other types of
   // variables.
   switch (var->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Comment cmnt(masm_, "[ Global variable");
       __ lw(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
       __ li(LoadDescriptor::NameRegister(), Operand(var->name()));
@@ -1502,9 +1506,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
                                                : "[ Stack variable");
       if (var->binding_needs_init()) {
@@ -1575,7 +1579,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ Lookup variable");
       Label done, slow;
       // Generate code for loading from variables potentially shadowed
@@ -2724,7 +2728,7 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
                                                FeedbackVectorICSlot slot) {
-  if (var->IsUnallocated()) {
+  if (var->IsUnallocatedOrGlobalSlot()) {
     // Global var, const, or let.
     __ mov(StoreDescriptor::ValueRegister(), result_register());
     __ li(StoreDescriptor::NameRegister(), Operand(var->name()));
@@ -4816,7 +4820,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // "delete this" is allowed.
         bool is_this = var->HasThisName(isolate());
         DCHECK(is_sloppy(language_mode()) || is_this);
-        if (var->IsUnallocated()) {
+        if (var->IsUnallocatedOrGlobalSlot()) {
           __ lw(a2, GlobalObjectOperand());
           __ li(a1, Operand(var->name()));
           __ li(a0, Operand(Smi::FromInt(SLOPPY)));
@@ -5177,7 +5181,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   DCHECK(!context()->IsEffect());
   DCHECK(!context()->IsTest());
   VariableProxy* proxy = expr->AsVariableProxy();
-  if (proxy != NULL && proxy->var()->IsUnallocated()) {
+  if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
     Comment cmnt(masm_, "[ Global variable");
     __ lw(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
     __ li(LoadDescriptor::NameRegister(), Operand(proxy->name()));
index 50e0dfe..ed6bd15 100644 (file)
@@ -364,7 +364,7 @@ void FullCodeGenerator::Generate() {
         VariableDeclaration* function = scope()->function();
         DCHECK(function->proxy()->var()->mode() == CONST ||
                function->proxy()->var()->mode() == CONST_LEGACY);
-        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
+        DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot());
         VisitVariableDeclaration(function);
       }
       VisitDeclarations(scope()->declarations());
@@ -872,7 +872,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
   Variable* variable = proxy->var();
   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       globals_->Add(variable->name(), zone());
       globals_->Add(variable->binding_needs_init()
                         ? isolate()->factory()->the_hole_value()
@@ -880,8 +881,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
                     zone());
       break;
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
@@ -889,7 +890,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-      case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         EmitDebugCheckDeclarationContext(variable);
@@ -900,7 +901,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
       __ li(a2, Operand(variable->name()));
       // Declaration nodes are always introduced in one of four modes.
@@ -932,7 +933,8 @@ void FullCodeGenerator::VisitFunctionDeclaration(
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       globals_->Add(variable->name(), zone());
       Handle<SharedFunctionInfo> function =
           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
@@ -942,15 +944,15 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       VisitForAccumulatorValue(declaration->fun());
       __ sd(result_register(), StackOperand(variable));
       break;
     }
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       VisitForAccumulatorValue(declaration->fun());
@@ -969,7 +971,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       __ li(a2, Operand(variable->name()));
       __ li(a1, Operand(Smi::FromInt(NONE)));
@@ -987,20 +989,21 @@ void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       // TODO(rossberg)
       break;
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ ImportDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       // TODO(rossberg)
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::LOOKUP:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::LOOKUP:
       UNREACHABLE();
   }
 }
@@ -1488,7 +1491,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
   // Three cases: global variables, lookup variables, and all other types of
   // variables.
   switch (var->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Comment cmnt(masm_, "[ Global variable");
       // Use inline caching. Variable name is passed in a2 and the global
       // object (receiver) in a0.
@@ -1501,9 +1505,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
                                                : "[ Stack variable");
       if (var->binding_needs_init()) {
@@ -1574,7 +1578,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ Lookup variable");
       Label done, slow;
       // Generate code for loading from variables potentially shadowed
@@ -2724,7 +2728,7 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
                                                FeedbackVectorICSlot slot) {
-  if (var->IsUnallocated()) {
+  if (var->IsUnallocatedOrGlobalSlot()) {
     // Global var, const, or let.
     __ mov(StoreDescriptor::ValueRegister(), result_register());
     __ li(StoreDescriptor::NameRegister(), Operand(var->name()));
@@ -4820,7 +4824,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // "delete this" is allowed.
         bool is_this = var->HasThisName(isolate());
         DCHECK(is_sloppy(language_mode()) || is_this);
-        if (var->IsUnallocated()) {
+        if (var->IsUnallocatedOrGlobalSlot()) {
           __ ld(a2, GlobalObjectOperand());
           __ li(a1, Operand(var->name()));
           __ li(a0, Operand(Smi::FromInt(SLOPPY)));
@@ -5181,7 +5185,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   DCHECK(!context()->IsEffect());
   DCHECK(!context()->IsTest());
   VariableProxy* proxy = expr->AsVariableProxy();
-  if (proxy != NULL && proxy->var()->IsUnallocated()) {
+  if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
     Comment cmnt(masm_, "[ Global variable");
     __ ld(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
     __ li(LoadDescriptor::NameRegister(), Operand(proxy->name()));
index c52ccc9..dc96725 100644 (file)
@@ -4011,7 +4011,8 @@ class ScopeInfo : public FixedArray {
   // If the slot is present and mode != NULL, sets *mode to the corresponding
   // mode for that variable.
   static int ContextSlotIndex(Handle<ScopeInfo> scope_info, Handle<String> name,
-                              VariableMode* mode, InitializationFlag* init_flag,
+                              VariableMode* mode, VariableLocation* location,
+                              InitializationFlag* init_flag,
                               MaybeAssignedFlag* maybe_assigned_flag);
 
   // Lookup support for serialized scope info. Returns the
@@ -4061,6 +4062,7 @@ class ScopeInfo : public FixedArray {
   V(ParameterCount)               \
   V(StackLocalCount)              \
   V(ContextLocalCount)            \
+  V(ContextGlobalCount)           \
   V(StrongModeFreeVariableCount)
 
 #define FIELD_ACCESSORS(name)                            \
@@ -4129,12 +4131,18 @@ class ScopeInfo : public FixedArray {
   int StackLocalFirstSlotIndex();
   int StackLocalEntriesIndex();
   int ContextLocalNameEntriesIndex();
+  int ContextGlobalNameEntriesIndex();
   int ContextLocalInfoEntriesIndex();
+  int ContextGlobalInfoEntriesIndex();
   int StrongModeFreeVariableNameEntriesIndex();
   int StrongModeFreeVariablePositionEntriesIndex();
   int ReceiverEntryIndex();
   int FunctionNameEntryIndex();
 
+  int Lookup(Handle<String> name, int start, int end, VariableMode* mode,
+             VariableLocation* location, InitializationFlag* init_flag,
+             MaybeAssignedFlag* maybe_assigned_flag);
+
   // Used for the function name variable for named function expressions, and for
   // the receiver.
   enum VariableAllocationInfo { NONE, STACK, CONTEXT, UNUSED };
index 147f562..d795b3c 100644 (file)
@@ -2095,7 +2095,7 @@ Variable* Parser::Declare(Declaration* declaration,
     // TODO(sigurds) figure out if kNotAssigned is OK here
     var = new (zone()) Variable(declaration_scope, name, mode, kind,
                                 declaration->initialization(), kNotAssigned);
-    var->AllocateTo(Variable::LOOKUP, -1);
+    var->AllocateTo(VariableLocation::LOOKUP, -1);
     resolve = true;
   }
 
index e8bae82..2175863 100644 (file)
@@ -363,7 +363,7 @@ void FullCodeGenerator::Generate() {
         VariableDeclaration* function = scope()->function();
         DCHECK(function->proxy()->var()->mode() == CONST ||
                function->proxy()->var()->mode() == CONST_LEGACY);
-        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
+        DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot());
         VisitVariableDeclaration(function);
       }
       VisitDeclarations(scope()->declarations());
@@ -850,7 +850,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
   Variable* variable = proxy->var();
   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       globals_->Add(variable->name(), zone());
       globals_->Add(variable->binding_needs_init()
                         ? isolate()->factory()->the_hole_value()
@@ -858,8 +859,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
                     zone());
       break;
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
@@ -867,7 +868,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         EmitDebugCheckDeclarationContext(variable);
@@ -878,7 +879,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
       __ mov(r5, Operand(variable->name()));
       // Declaration nodes are always introduced in one of four modes.
@@ -909,7 +910,8 @@ void FullCodeGenerator::VisitFunctionDeclaration(
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       globals_->Add(variable->name(), zone());
       Handle<SharedFunctionInfo> function =
           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
@@ -919,15 +921,15 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       VisitForAccumulatorValue(declaration->fun());
       __ StoreP(result_register(), StackOperand(variable));
       break;
     }
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       VisitForAccumulatorValue(declaration->fun());
@@ -941,7 +943,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       __ mov(r5, Operand(variable->name()));
       __ LoadSmiLiteral(r4, Smi::FromInt(NONE));
@@ -959,20 +961,21 @@ void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       // TODO(rossberg)
       break;
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ ImportDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       // TODO(rossberg)
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::LOOKUP:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::LOOKUP:
       UNREACHABLE();
   }
 }
@@ -1467,7 +1470,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
   // Three cases: global variables, lookup variables, and all other types of
   // variables.
   switch (var->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Comment cmnt(masm_, "[ Global variable");
       __ LoadP(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
       __ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
@@ -1478,9 +1482,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
                                                : "[ Stack variable");
       if (var->binding_needs_init()) {
@@ -1549,7 +1553,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ Lookup variable");
       Label done, slow;
       // Generate code for loading from variables potentially shadowed
index 03ef4de..6a7718a 100644 (file)
@@ -1436,18 +1436,21 @@ void AstPrinter::VisitVariableProxy(VariableProxy* node) {
   EmbeddedVector<char, 128> buf;
   int pos = SNPrintF(buf, "VAR PROXY");
   switch (var->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::UNALLOCATED:
       break;
-    case Variable::PARAMETER:
+    case VariableLocation::PARAMETER:
       SNPrintF(buf + pos, " parameter[%d]", var->index());
       break;
-    case Variable::LOCAL:
+    case VariableLocation::LOCAL:
       SNPrintF(buf + pos, " local[%d]", var->index());
       break;
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       SNPrintF(buf + pos, " context[%d]", var->index());
       break;
-    case Variable::LOOKUP:
+    case VariableLocation::GLOBAL:
+      SNPrintF(buf + pos, " global[%d]", var->index());
+      break;
+    case VariableLocation::LOOKUP:
       SNPrintF(buf + pos, " lookup");
       break;
   }
index e8919b5..9aa4341 100644 (file)
@@ -681,11 +681,13 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
       if (scope_info->LocalIsSynthetic(i)) continue;
       Handle<String> name(scope_info->LocalName(i));
       VariableMode mode;
+      VariableLocation location;
       InitializationFlag init_flag;
       MaybeAssignedFlag maybe_assigned_flag;
       locals->set(local * 2, *name);
       int context_slot_index = ScopeInfo::ContextSlotIndex(
-          scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
+          scope_info, name, &mode, &location, &init_flag, &maybe_assigned_flag);
+      DCHECK(VariableLocation::CONTEXT == location);
       Object* value = context->get(context_slot_index);
       locals->set(local * 2 + 1, value);
       local++;
@@ -856,10 +858,11 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
 static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,
                                               Handle<String> parameter_name) {
   VariableMode mode;
+  VariableLocation location;
   InitializationFlag init_flag;
   MaybeAssignedFlag maybe_assigned_flag;
-  return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
-                                     &maybe_assigned_flag) != -1;
+  return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &location,
+                                     &init_flag, &maybe_assigned_flag) != -1;
 }
 
 
@@ -872,14 +875,15 @@ static Handle<Context> MaterializeReceiver(Isolate* isolate,
   Handle<Object> receiver;
   switch (scope_info->scope_type()) {
     case FUNCTION_SCOPE: {
-      VariableMode variable_mode;
+      VariableMode mode;
+      VariableLocation location;
       InitializationFlag init_flag;
       MaybeAssignedFlag maybe_assigned_flag;
 
       // Don't bother creating a fake context node if "this" is in the context
       // already.
       if (ScopeInfo::ContextSlotIndex(
-              scope_info, isolate->factory()->this_string(), &variable_mode,
+              scope_info, isolate->factory()->this_string(), &mode, &location,
               &init_flag, &maybe_assigned_flag) >= 0) {
         return target;
       }
@@ -1077,10 +1081,12 @@ static bool SetContextLocalValue(Isolate* isolate, Handle<ScopeInfo> scope_info,
     Handle<String> next_name(scope_info->ContextLocalName(i));
     if (String::Equals(variable_name, next_name)) {
       VariableMode mode;
+      VariableLocation location;
       InitializationFlag init_flag;
       MaybeAssignedFlag maybe_assigned_flag;
-      int context_index = ScopeInfo::ContextSlotIndex(
-          scope_info, next_name, &mode, &init_flag, &maybe_assigned_flag);
+      int context_index =
+          ScopeInfo::ContextSlotIndex(scope_info, next_name, &mode, &location,
+                                      &init_flag, &maybe_assigned_flag);
       context->set(context_index, *new_value);
       return true;
     }
@@ -2671,6 +2677,14 @@ RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
 }
 
 
+static inline bool IsDebugContext(Isolate* isolate, Context* context) {
+  // Try to unwrap script context if it exist.
+  if (context->IsScriptContext()) context = context->previous();
+  DCHECK_NOT_NULL(context);
+  return context == *isolate->debug()->debug_context();
+}
+
+
 RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
   HandleScope scope(isolate);
 
@@ -2690,7 +2704,7 @@ RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
   // Enter the top context from before the debugger was invoked.
   SaveContext save(isolate);
   SaveContext* top = &save;
-  while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
+  while (top != NULL && IsDebugContext(isolate, *top->context())) {
     top = top->prev();
   }
   if (top != NULL) {
index 8b34b6c..700925d 100644 (file)
@@ -632,7 +632,6 @@ RUNTIME_FUNCTION(Runtime_NewScriptContext) {
   Handle<ScriptContextTable> script_context_table(
       native_context->script_context_table());
 
-  Handle<String> clashed_name;
   Object* name_clash_result =
       FindNameClash(scope_info, global_object, script_context_table);
   if (isolate->has_pending_exception()) return name_clash_result;
@@ -640,12 +639,16 @@ RUNTIME_FUNCTION(Runtime_NewScriptContext) {
   // Script contexts have a canonical empty function as their closure, not the
   // anonymous closure containing the global code.  See
   // FullCodeGenerator::PushFunctionArgumentForContextAllocation.
-  Handle<JSFunction> closure(native_context->closure());
+  Handle<JSFunction> closure(global_object->IsJSBuiltinsObject()
+                                 ? *function
+                                 : native_context->closure());
   Handle<Context> result =
       isolate->factory()->NewScriptContext(closure, scope_info);
 
+  result->InitializeGlobalSlots();
+
   DCHECK(function->context() == isolate->context());
-  DCHECK(function->context()->global_object() == result->global_object());
+  DCHECK(*global_object == result->global_object());
 
   Handle<ScriptContextTable> new_script_context_table =
       ScriptContextTable::Extend(script_context_table, result);
index f77ef96..4ed22b1 100644 (file)
@@ -19,16 +19,20 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
   // Collect stack and context locals.
   ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
   ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
+  ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone);
   ZoneList<Variable*> strong_mode_free_variables(0, zone);
 
   scope->CollectStackAndContextLocals(&stack_locals, &context_locals,
+                                      &context_globals,
                                       &strong_mode_free_variables);
   const int stack_local_count = stack_locals.length();
   const int context_local_count = context_locals.length();
+  const int context_global_count = context_globals.length();
   const int strong_mode_free_variable_count =
       strong_mode_free_variables.length();
   // Make sure we allocate the correct amount.
-  DCHECK(scope->ContextLocalCount() == context_local_count);
+  DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
+  DCHECK_EQ(scope->ContextGlobalCount(), context_global_count);
 
   bool simple_parameter_list =
       scope->is_function_scope() ? scope->is_simple_parameter_list() : true;
@@ -67,12 +71,14 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
     function_name_info = NONE;
     function_variable_mode = VAR;
   }
+  DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE);
 
   const bool has_function_name = function_name_info != NONE;
   const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
   const int parameter_count = scope->num_parameters();
   const int length = kVariablePartIndex + parameter_count +
                      (1 + stack_local_count) + 2 * context_local_count +
+                     2 * context_global_count +
                      3 * strong_mode_free_variable_count +
                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
 
@@ -94,6 +100,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
   scope_info->SetParameterCount(parameter_count);
   scope_info->SetStackLocalCount(stack_local_count);
   scope_info->SetContextLocalCount(context_local_count);
+  scope_info->SetContextGlobalCount(context_global_count);
   scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
 
   int index = kVariablePartIndex;
@@ -134,6 +141,12 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
     scope_info->set(index++, *context_locals[i]->name());
   }
 
+  // Add context globals' names.
+  DCHECK(index == scope_info->ContextGlobalNameEntriesIndex());
+  for (int i = 0; i < context_global_count; ++i) {
+    scope_info->set(index++, *context_globals[i]->name());
+  }
+
   // Add context locals' info.
   DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
   for (int i = 0; i < context_local_count; ++i) {
@@ -145,6 +158,18 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
     scope_info->set(index++, Smi::FromInt(value));
   }
 
+  // Add context globals' info.
+  DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex());
+  for (int i = 0; i < context_global_count; ++i) {
+    Variable* var = context_globals[i];
+    // TODO(ishell): do we need this kind of info for globals here?
+    uint32_t value =
+        ContextLocalMode::encode(var->mode()) |
+        ContextLocalInitFlag::encode(var->initialization_flag()) |
+        ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
+    scope_info->set(index++, Smi::FromInt(value));
+  }
+
   DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
   for (int i = 0; i < strong_mode_free_variable_count; ++i) {
     scope_info->set(index++, *strong_mode_free_variables[i]->name());
@@ -197,6 +222,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
 
   const int stack_local_count = 0;
   const int context_local_count = 1;
+  const int context_global_count = 0;
   const int strong_mode_free_variable_count = 0;
   const bool simple_parameter_list = true;
   const VariableAllocationInfo receiver_info = CONTEXT;
@@ -207,6 +233,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
   const int parameter_count = 0;
   const int length = kVariablePartIndex + parameter_count +
                      (1 + stack_local_count) + 2 * context_local_count +
+                     2 * context_global_count +
                      3 * strong_mode_free_variable_count +
                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
 
@@ -227,6 +254,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
   scope_info->SetParameterCount(parameter_count);
   scope_info->SetStackLocalCount(stack_local_count);
   scope_info->SetContextLocalCount(context_local_count);
+  scope_info->SetContextGlobalCount(context_global_count);
   scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
 
   int index = kVariablePartIndex;
@@ -301,16 +329,19 @@ int ScopeInfo::StackSlotCount() {
 int ScopeInfo::ContextLength() {
   if (length() > 0) {
     int context_locals = ContextLocalCount();
+    int context_globals = ContextGlobalCount();
     bool function_name_context_slot =
         FunctionVariableField::decode(Flags()) == CONTEXT;
-    bool has_context = context_locals > 0 || function_name_context_slot ||
+    bool has_context = context_locals > 0 || context_globals > 0 ||
+                       function_name_context_slot ||
                        scope_type() == WITH_SCOPE ||
                        (scope_type() == ARROW_SCOPE && CallsSloppyEval()) ||
                        (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
                        scope_type() == MODULE_SCOPE;
+
     if (has_context) {
-      return Context::MIN_CONTEXT_SLOTS + context_locals +
-          (function_name_context_slot ? 1 : 0);
+      return Context::MIN_CONTEXT_SLOTS + context_locals + 2 * context_globals +
+             (function_name_context_slot ? 1 : 0);
     }
   }
   return 0;
@@ -396,14 +427,14 @@ int ScopeInfo::StackLocalIndex(int var) {
 
 
 String* ScopeInfo::ContextLocalName(int var) {
-  DCHECK(0 <= var && var < ContextLocalCount());
+  DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
   int info_index = ContextLocalNameEntriesIndex() + var;
   return String::cast(get(info_index));
 }
 
 
 VariableMode ScopeInfo::ContextLocalMode(int var) {
-  DCHECK(0 <= var && var < ContextLocalCount());
+  DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
   int info_index = ContextLocalInfoEntriesIndex() + var;
   int value = Smi::cast(get(info_index))->value();
   return ContextLocalMode::decode(value);
@@ -411,7 +442,7 @@ VariableMode ScopeInfo::ContextLocalMode(int var) {
 
 
 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
-  DCHECK(0 <= var && var < ContextLocalCount());
+  DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
   int info_index = ContextLocalInfoEntriesIndex() + var;
   int value = Smi::cast(get(info_index))->value();
   return ContextLocalInitFlag::decode(value);
@@ -419,7 +450,7 @@ InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
 
 
 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
-  DCHECK(0 <= var && var < ContextLocalCount());
+  DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
   int info_index = ContextLocalInfoEntriesIndex() + var;
   int value = Smi::cast(get(info_index))->value();
   return ContextLocalMaybeAssignedFlag::decode(value);
@@ -485,39 +516,56 @@ int ScopeInfo::StackSlotIndex(String* name) {
 
 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
                                 Handle<String> name, VariableMode* mode,
+                                VariableLocation* location,
                                 InitializationFlag* init_flag,
                                 MaybeAssignedFlag* maybe_assigned_flag) {
   DCHECK(name->IsInternalizedString());
   DCHECK(mode != NULL);
+  DCHECK(location != NULL);
   DCHECK(init_flag != NULL);
   if (scope_info->length() > 0) {
     ContextSlotCache* context_slot_cache =
         scope_info->GetIsolate()->context_slot_cache();
-    int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
-                                            maybe_assigned_flag);
+    int result = context_slot_cache->Lookup(*scope_info, *name, mode, location,
+                                            init_flag, maybe_assigned_flag);
     if (result != ContextSlotCache::kNotFound) {
       DCHECK(result < scope_info->ContextLength());
       return result;
     }
 
+    DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(),
+              scope_info->ContextLocalNameEntriesIndex() +
+                  scope_info->ContextLocalCount());
     int start = scope_info->ContextLocalNameEntriesIndex();
-    int end = scope_info->ContextLocalNameEntriesIndex() +
-        scope_info->ContextLocalCount();
+    int end = scope_info->ContextGlobalNameEntriesIndex() +
+              scope_info->ContextGlobalCount();
     for (int i = start; i < end; ++i) {
       if (*name == scope_info->get(i)) {
         int var = i - start;
         *mode = scope_info->ContextLocalMode(var);
         *init_flag = scope_info->ContextLocalInitFlag(var);
         *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
-        result = Context::MIN_CONTEXT_SLOTS + var;
-        context_slot_cache->Update(scope_info, name, *mode, *init_flag,
-                                   *maybe_assigned_flag, result);
+
+        if (var < scope_info->ContextLocalCount()) {
+          *location = VariableLocation::CONTEXT;
+          result = Context::MIN_CONTEXT_SLOTS + var;
+        } else {
+          var -= scope_info->ContextLocalCount();
+          *location = VariableLocation::GLOBAL;
+          result = Context::MIN_CONTEXT_SLOTS +
+                   scope_info->ContextLocalCount() + 2 * var;
+        }
+
+        context_slot_cache->Update(scope_info, name, *mode, *location,
+                                   *init_flag, *maybe_assigned_flag, result);
         DCHECK(result < scope_info->ContextLength());
         return result;
       }
     }
-    // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
-    context_slot_cache->Update(scope_info, name, INTERNAL, kNeedsInitialization,
+    // Cache as not found. Mode, location, init flag and maybe assigned flag
+    // don't matter.
+    context_slot_cache->Update(scope_info, name, INTERNAL,
+                               VariableLocation::CONTEXT, kNeedsInitialization,
                                kNotAssigned, -1);
   }
   return -1;
@@ -615,16 +663,26 @@ int ScopeInfo::ContextLocalNameEntriesIndex() {
 }
 
 
-int ScopeInfo::ContextLocalInfoEntriesIndex() {
+int ScopeInfo::ContextGlobalNameEntriesIndex() {
   return ContextLocalNameEntriesIndex() + ContextLocalCount();
 }
 
 
-int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
+int ScopeInfo::ContextLocalInfoEntriesIndex() {
+  return ContextGlobalNameEntriesIndex() + ContextGlobalCount();
+}
+
+
+int ScopeInfo::ContextGlobalInfoEntriesIndex() {
   return ContextLocalInfoEntriesIndex() + ContextLocalCount();
 }
 
 
+int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
+  return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
+}
+
+
 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
   return StrongModeFreeVariableNameEntriesIndex() +
          StrongModeFreeVariableCount();
@@ -651,6 +709,7 @@ int ContextSlotCache::Hash(Object* data, String* name) {
 
 
 int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
+                             VariableLocation* location,
                              InitializationFlag* init_flag,
                              MaybeAssignedFlag* maybe_assigned_flag) {
   int index = Hash(data, name);
@@ -658,6 +717,7 @@ int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
   if ((key.data == data) && key.name->Equals(name)) {
     Value result(values_[index]);
     if (mode != NULL) *mode = result.mode();
+    if (location != NULL) *location = result.location();
     if (init_flag != NULL) *init_flag = result.initialization_flag();
     if (maybe_assigned_flag != NULL)
       *maybe_assigned_flag = result.maybe_assigned_flag();
@@ -668,7 +728,8 @@ int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
 
 
 void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
-                              VariableMode mode, InitializationFlag init_flag,
+                              VariableMode mode, VariableLocation location,
+                              InitializationFlag init_flag,
                               MaybeAssignedFlag maybe_assigned_flag,
                               int slot_index) {
   DisallowHeapAllocation no_gc;
@@ -681,10 +742,11 @@ void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
     key.data = *data;
     key.name = *internalized_name;
     // Please note value only takes a uint as index.
-    values_[index] = Value(mode, init_flag, maybe_assigned_flag,
+    values_[index] = Value(mode, location, init_flag, maybe_assigned_flag,
                            slot_index - kNotFound).raw();
 #ifdef DEBUG
-    ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index);
+    ValidateEntry(data, name, mode, location, init_flag, maybe_assigned_flag,
+                  slot_index);
 #endif
   }
 }
@@ -699,6 +761,7 @@ void ContextSlotCache::Clear() {
 
 void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
                                      VariableMode mode,
+                                     VariableLocation location,
                                      InitializationFlag init_flag,
                                      MaybeAssignedFlag maybe_assigned_flag,
                                      int slot_index) {
@@ -712,6 +775,7 @@ void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
     DCHECK(key.name->Equals(*name));
     Value result(values_[index]);
     DCHECK(result.mode() == mode);
+    DCHECK(result.location() == location);
     DCHECK(result.initialization_flag() == init_flag);
     DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
     DCHECK(result.index() + kNotFound == slot_index);
index 70a17cd..adefaef 100644 (file)
@@ -21,12 +21,12 @@ class ContextSlotCache {
   // Lookup context slot index for (data, name).
   // If absent, kNotFound is returned.
   int Lookup(Object* data, String* name, VariableMode* mode,
-             InitializationFlag* init_flag,
+             VariableLocation* location, InitializationFlag* init_flag,
              MaybeAssignedFlag* maybe_assigned_flag);
 
   // Update an element in the cache.
   void Update(Handle<Object> data, Handle<String> name, VariableMode mode,
-              InitializationFlag init_flag,
+              VariableLocation location, InitializationFlag init_flag,
               MaybeAssignedFlag maybe_assigned_flag, int slot_index);
 
   // Clear the cache.
@@ -47,7 +47,8 @@ class ContextSlotCache {
 
 #ifdef DEBUG
   void ValidateEntry(Handle<Object> data, Handle<String> name,
-                     VariableMode mode, InitializationFlag init_flag,
+                     VariableMode mode, VariableLocation location,
+                     InitializationFlag init_flag,
                      MaybeAssignedFlag maybe_assigned_flag, int slot_index);
 #endif
 
@@ -58,16 +59,26 @@ class ContextSlotCache {
   };
 
   struct Value {
-    Value(VariableMode mode, InitializationFlag init_flag,
-          MaybeAssignedFlag maybe_assigned_flag, int index) {
+    enum VariableLocationFlag { kContext, kGlobal };
+
+    Value(VariableMode mode, VariableLocation location,
+          InitializationFlag init_flag, MaybeAssignedFlag maybe_assigned_flag,
+          int index) {
+      DCHECK(location == VariableLocation::CONTEXT ||
+             location == VariableLocation::GLOBAL);
+      VariableLocationFlag location_flag =
+          location == VariableLocation::CONTEXT ? kContext : kGlobal;
       DCHECK(ModeField::is_valid(mode));
+      DCHECK(VariableLocationField::is_valid(location_flag));
       DCHECK(InitField::is_valid(init_flag));
       DCHECK(MaybeAssignedField::is_valid(maybe_assigned_flag));
       DCHECK(IndexField::is_valid(index));
       value_ = ModeField::encode(mode) | IndexField::encode(index) |
+               VariableLocationField::encode(location_flag) |
                InitField::encode(init_flag) |
                MaybeAssignedField::encode(maybe_assigned_flag);
       DCHECK(mode == this->mode());
+      DCHECK(location == this->location());
       DCHECK(init_flag == this->initialization_flag());
       DCHECK(maybe_assigned_flag == this->maybe_assigned_flag());
       DCHECK(index == this->index());
@@ -79,6 +90,17 @@ class ContextSlotCache {
 
     VariableMode mode() { return ModeField::decode(value_); }
 
+    VariableLocation location() {
+      switch (VariableLocationField::decode(value_)) {
+        case kContext:
+          return VariableLocation::CONTEXT;
+        case kGlobal:
+          return VariableLocation::GLOBAL;
+      }
+      UNREACHABLE();
+      return VariableLocation::CONTEXT;
+    }
+
     InitializationFlag initialization_flag() {
       return InitField::decode(value_);
     }
@@ -94,7 +116,9 @@ class ContextSlotCache {
     class ModeField : public BitField<VariableMode, 0, 4> {};
     class InitField : public BitField<InitializationFlag, 4, 1> {};
     class MaybeAssignedField : public BitField<MaybeAssignedFlag, 5, 1> {};
-    class IndexField : public BitField<int, 6, 32 - 6> {};
+    class VariableLocationField : public BitField<VariableLocationFlag, 6, 1> {
+    };
+    class IndexField : public BitField<int, 7, 32 - 7> {};
 
    private:
     uint32_t value_;
index 64f9584..f9eef9a 100644 (file)
@@ -14,6 +14,9 @@
 namespace v8 {
 namespace internal {
 
+// TODO(ishell): remove this once compiler support is landed.
+bool enable_context_globals = false;
+
 // ----------------------------------------------------------------------------
 // Implementation of LocalsMap
 //
@@ -178,6 +181,7 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
   num_var_or_const_ = 0;
   num_stack_slots_ = 0;
   num_heap_slots_ = 0;
+  num_global_slots_ = 0;
   num_modules_ = 0;
   module_var_ = NULL,
   rest_parameter_ = NULL;
@@ -388,27 +392,32 @@ Variable* Scope::LookupLocal(const AstRawString* name) {
 
   // Check context slot lookup.
   VariableMode mode;
-  Variable::Location location = Variable::CONTEXT;
+  VariableLocation location;
   InitializationFlag init_flag;
   MaybeAssignedFlag maybe_assigned_flag;
-  int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode,
-                                          &init_flag, &maybe_assigned_flag);
+  int index =
+      ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, &location,
+                                  &init_flag, &maybe_assigned_flag);
   if (index < 0) {
     // Check parameters.
     index = scope_info_->ParameterIndex(*name_handle);
     if (index < 0) return NULL;
 
     mode = DYNAMIC;
-    location = Variable::LOOKUP;
+    location = VariableLocation::LOOKUP;
     init_flag = kCreatedInitialized;
     // Be conservative and flag parameters as maybe assigned. Better information
     // would require ScopeInfo to serialize the maybe_assigned bit also for
     // parameters.
     maybe_assigned_flag = kMaybeAssigned;
+  } else {
+    DCHECK(location != VariableLocation::GLOBAL ||
+           (is_script_scope() && IsDeclaredVariableMode(mode) &&
+            !IsLexicalVariableMode(mode)));
   }
 
   Variable::Kind kind = Variable::NORMAL;
-  if (location == Variable::CONTEXT &&
+  if (location == VariableLocation::CONTEXT &&
       index == scope_info_->ReceiverContextSlotIndex()) {
     kind = Variable::THIS;
   }
@@ -437,7 +446,7 @@ Variable* Scope::LookupFunctionVar(const AstRawString* name,
     VariableDeclaration* declaration = factory->NewVariableDeclaration(
         proxy, mode, this, RelocInfo::kNoPosition);
     DeclareFunctionVar(declaration);
-    var->AllocateTo(Variable::CONTEXT, index);
+    var->AllocateTo(VariableLocation::CONTEXT, index);
     return var;
   } else {
     return NULL;
@@ -603,9 +612,11 @@ class VarAndOrder {
 
 void Scope::CollectStackAndContextLocals(
     ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals,
+    ZoneList<Variable*>* context_globals,
     ZoneList<Variable*>* strong_mode_free_variables) {
   DCHECK(stack_locals != NULL);
   DCHECK(context_locals != NULL);
+  DCHECK(context_globals != NULL);
 
   // Collect internals which are always allocated on the heap.
   for (int i = 0; i < internals_.length(); i++) {
@@ -654,6 +665,8 @@ void Scope::CollectStackAndContextLocals(
       stack_locals->Add(var, zone());
     } else if (var->IsContextSlot()) {
       context_locals->Add(var, zone());
+    } else if (var->IsGlobalSlot()) {
+      context_globals->Add(var, zone());
     }
   }
 }
@@ -693,7 +706,7 @@ bool Scope::HasTrivialContext() const {
   for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
     if (scope->is_eval_scope()) return false;
     if (scope->scope_inside_with_) return false;
-    if (scope->num_heap_slots_ > 0) return false;
+    if (scope->ContextLocalCount() > 0) return false;
   }
   return true;
 }
@@ -828,18 +841,21 @@ static void PrintName(const AstRawString* name) {
 
 static void PrintLocation(Variable* var) {
   switch (var->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::UNALLOCATED:
       break;
-    case Variable::PARAMETER:
+    case VariableLocation::PARAMETER:
       PrintF("parameter[%d]", var->index());
       break;
-    case Variable::LOCAL:
+    case VariableLocation::LOCAL:
       PrintF("local[%d]", var->index());
       break;
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       PrintF("context[%d]", var->index());
       break;
-    case Variable::LOOKUP:
+    case VariableLocation::GLOBAL:
+      PrintF("global[%d]", var->index());
+      break;
+    case VariableLocation::LOOKUP:
       PrintF("lookup");
       break;
   }
@@ -871,7 +887,11 @@ static void PrintVar(int indent, Variable* var) {
 static void PrintMap(int indent, VariableMap* map) {
   for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
     Variable* var = reinterpret_cast<Variable*>(p->value);
-    PrintVar(indent, var);
+    if (var == NULL) {
+      Indent(indent, "<?>\n");
+    } else {
+      PrintVar(indent, var);
+    }
   }
 }
 
@@ -928,10 +948,15 @@ void Scope::Print(int n) {
     Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
   }
   if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
-  if (num_stack_slots_ > 0) { Indent(n1, "// ");
-  PrintF("%d stack slots\n", num_stack_slots_); }
-  if (num_heap_slots_ > 0) { Indent(n1, "// ");
-  PrintF("%d heap slots\n", num_heap_slots_); }
+  if (num_stack_slots_ > 0) {
+    Indent(n1, "// ");
+    PrintF("%d stack slots\n", num_stack_slots_);
+  }
+  if (num_heap_slots_ > 0) {
+    Indent(n1, "// ");
+    PrintF("%d heap slots (including %d global slots)\n", num_heap_slots_,
+           num_global_slots_);
+  }
 
   // Print locals.
   if (function_ != NULL) {
@@ -992,7 +1017,7 @@ Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
                        Variable::NORMAL,
                        init_flag);
     // Allocate it by giving it a dynamic lookup.
-    var->AllocateTo(Variable::LOOKUP, -1);
+    var->AllocateTo(VariableLocation::LOOKUP, -1);
   }
   return var;
 }
@@ -1343,13 +1368,13 @@ void Scope::AllocateStackSlot(Variable* var) {
   if (is_block_scope()) {
     DeclarationScope()->AllocateStackSlot(var);
   } else {
-    var->AllocateTo(Variable::LOCAL, num_stack_slots_++);
+    var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
   }
 }
 
 
 void Scope::AllocateHeapSlot(Variable* var) {
-  var->AllocateTo(Variable::CONTEXT, num_heap_slots_++);
+  var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
 }
 
 
@@ -1414,9 +1439,11 @@ void Scope::AllocateParameter(Variable* var, int index) {
     } else {
       DCHECK(var->IsUnallocated() || var->IsParameter());
       if (var->IsUnallocated()) {
-        var->AllocateTo(Variable::PARAMETER, index);
+        var->AllocateTo(VariableLocation::PARAMETER, index);
       }
     }
+  } else {
+    DCHECK(!var->IsGlobalSlot());
   }
 }
 
@@ -1447,7 +1474,23 @@ void Scope::AllocateNonParameterLocal(Isolate* isolate, Variable* var) {
 }
 
 
-void Scope::AllocateNonParameterLocals(Isolate* isolate) {
+void Scope::AllocateDeclaredGlobal(Isolate* isolate, Variable* var) {
+  DCHECK(var->scope() == this);
+  DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) ||
+         !var->IsStackLocal());
+  if (var->IsUnallocated() && var->IsStaticGlobalObjectProperty()) {
+    DCHECK_EQ(-1, var->index());
+    DCHECK(var->name()->IsString());
+    var->AllocateTo(VariableLocation::GLOBAL, num_heap_slots_);
+    num_global_slots_++;
+    // Each global variable occupies two slots in the context: for reads
+    // and writes.
+    num_heap_slots_ += 2;
+  }
+}
+
+
+void Scope::AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate) {
   // All variables that have no rewrite yet are non-parameter locals.
   for (int i = 0; i < temps_.length(); i++) {
     AllocateNonParameterLocal(isolate, temps_[i]);
@@ -1470,6 +1513,12 @@ void Scope::AllocateNonParameterLocals(Isolate* isolate) {
     AllocateNonParameterLocal(isolate, vars[i].var());
   }
 
+  if (enable_context_globals) {
+    for (int i = 0; i < var_count; i++) {
+      AllocateDeclaredGlobal(isolate, vars[i].var());
+    }
+  }
+
   // For now, function_ must be allocated at the very end.  If it gets
   // allocated in the context, it must be the last slot in the context,
   // because of the current ScopeInfo implementation (see
@@ -1515,7 +1564,7 @@ void Scope::AllocateVariablesRecursively(Isolate* isolate) {
   // Parameters must be allocated first, if any.
   if (is_function_scope()) AllocateParameterLocals(isolate);
   if (has_this_declaration()) AllocateReceiver();
-  AllocateNonParameterLocals(isolate);
+  AllocateNonParameterLocalsAndDeclaredGlobals(isolate);
 
   // Force allocation of a context for this scope if necessary. For a 'with'
   // scope and for a function scope that makes an 'eval' call we need a context,
@@ -1559,8 +1608,13 @@ int Scope::StackLocalCount() const {
 
 int Scope::ContextLocalCount() const {
   if (num_heap_slots() == 0) return 0;
+  bool is_function_var_in_context =
+      function_ != NULL && function_->proxy()->var()->IsContextSlot();
   return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
-      (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
+         2 * num_global_slots() - (is_function_var_in_context ? 1 : 0);
 }
+
+
+int Scope::ContextGlobalCount() const { return num_global_slots(); }
 }  // namespace internal
 }  // namespace v8
index 1b43f8e..4086380 100644 (file)
@@ -442,6 +442,7 @@ class Scope: public ZoneObject {
   // handled separately.
   void CollectStackAndContextLocals(
       ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals,
+      ZoneList<Variable*>* context_globals,
       ZoneList<Variable*>* strong_mode_free_variables = nullptr);
 
   // Current number of var or const locals.
@@ -450,9 +451,11 @@ class Scope: public ZoneObject {
   // Result of variable allocation.
   int num_stack_slots() const { return num_stack_slots_; }
   int num_heap_slots() const { return num_heap_slots_; }
+  int num_global_slots() const { return num_global_slots_; }
 
   int StackLocalCount() const;
   int ContextLocalCount() const;
+  int ContextGlobalCount() const;
 
   // For script scopes, the number of module literals (including nested ones).
   int num_modules() const { return num_modules_; }
@@ -617,6 +620,7 @@ class Scope: public ZoneObject {
   // Computed via AllocateVariables; function, block and catch scopes only.
   int num_stack_slots_;
   int num_heap_slots_;
+  int num_global_slots_;
 
   // The number of modules (including nested ones).
   int num_modules_;
@@ -713,7 +717,8 @@ class Scope: public ZoneObject {
   void AllocateHeapSlot(Variable* var);
   void AllocateParameterLocals(Isolate* isolate);
   void AllocateNonParameterLocal(Isolate* isolate, Variable* var);
-  void AllocateNonParameterLocals(Isolate* isolate);
+  void AllocateDeclaredGlobal(Isolate* isolate, Variable* var);
+  void AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate);
   void AllocateVariablesRecursively(Isolate* isolate);
   void AllocateParameter(Variable* var, int index);
   void AllocateReceiver();
index 6f5cd1c..2f10328 100644 (file)
@@ -105,7 +105,9 @@ void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) {
 
     ZoneList<Variable*> local_vars(locals, zone());
     ZoneList<Variable*> context_vars(scope->ContextLocalCount(), zone());
-    scope->CollectStackAndContextLocals(&local_vars, &context_vars);
+    ZoneList<Variable*> global_vars(scope->ContextGlobalCount(), zone());
+    scope->CollectStackAndContextLocals(&local_vars, &context_vars,
+                                        &global_vars);
     for (int i = 0; i < locals; i++) {
       PrintObserved(local_vars.at(i),
                     frame->GetExpression(i),
index 49846fe..18a45ab 100644 (file)
@@ -39,7 +39,7 @@ Variable::Variable(Scope* scope, const AstRawString* name, VariableMode mode,
       name_(name),
       mode_(mode),
       kind_(kind),
-      location_(UNALLOCATED),
+      location_(VariableLocation::UNALLOCATED),
       index_(-1),
       initializer_position_(RelocInfo::kNoPosition),
       has_strong_mode_reference_(false),
@@ -58,8 +58,14 @@ Variable::Variable(Scope* scope, const AstRawString* name, VariableMode mode,
 bool Variable::IsGlobalObjectProperty() const {
   // Temporaries are never global, they must always be allocated in the
   // activation frame.
-  return (IsDynamicVariableMode(mode_) ||
-          (IsDeclaredVariableMode(mode_) && !IsLexicalVariableMode(mode_))) &&
+  return IsDynamicVariableMode(mode_) || IsStaticGlobalObjectProperty();
+}
+
+
+bool Variable::IsStaticGlobalObjectProperty() const {
+  // Temporaries are never global, they must always be allocated in the
+  // activation frame.
+  return (IsDeclaredVariableMode(mode_) && !IsLexicalVariableMode(mode_)) &&
          scope_ != NULL && scope_->is_script_scope() && !is_this();
 }
 
index 218eefa..deebc5f 100644 (file)
@@ -22,33 +22,6 @@ class Variable: public ZoneObject {
  public:
   enum Kind { NORMAL, FUNCTION, CLASS, THIS, ARGUMENTS };
 
-  enum Location {
-    // Before and during variable allocation, a variable whose location is
-    // not yet determined.  After allocation, a variable looked up as a
-    // property on the global object (and possibly absent).  name() is the
-    // variable name, index() is invalid.
-    UNALLOCATED,
-
-    // A slot in the parameter section on the stack.  index() is the
-    // parameter index, counting left-to-right.  The receiver is index -1;
-    // the first parameter is index 0.
-    PARAMETER,
-
-    // A slot in the local section on the stack.  index() is the variable
-    // index in the stack frame, starting at 0.
-    LOCAL,
-
-    // An indexed slot in a heap context.  index() is the variable index in
-    // the context object on the heap, starting at 0.  scope() is the
-    // corresponding scope.
-    CONTEXT,
-
-    // A named slot in a heap context.  name() is the variable name in the
-    // context object on the heap, with lookup starting at the current
-    // context.  index() is invalid.
-    LOOKUP
-  };
-
   Variable(Scope* scope, const AstRawString* name, VariableMode mode, Kind kind,
            InitializationFlag initialization_flag,
            MaybeAssignedFlag maybe_assigned_flag = kNotAssigned);
@@ -86,13 +59,20 @@ class Variable: public ZoneObject {
     return !is_this() && name().is_identical_to(n);
   }
 
-  bool IsUnallocated() const { return location_ == UNALLOCATED; }
-  bool IsParameter() const { return location_ == PARAMETER; }
-  bool IsStackLocal() const { return location_ == LOCAL; }
+  bool IsUnallocated() const {
+    return location_ == VariableLocation::UNALLOCATED;
+  }
+  bool IsParameter() const { return location_ == VariableLocation::PARAMETER; }
+  bool IsStackLocal() const { return location_ == VariableLocation::LOCAL; }
   bool IsStackAllocated() const { return IsParameter() || IsStackLocal(); }
-  bool IsContextSlot() const { return location_ == CONTEXT; }
-  bool IsLookupSlot() const { return location_ == LOOKUP; }
+  bool IsContextSlot() const { return location_ == VariableLocation::CONTEXT; }
+  bool IsGlobalSlot() const { return location_ == VariableLocation::GLOBAL; }
+  bool IsUnallocatedOrGlobalSlot() const {
+    return IsUnallocated() || IsGlobalSlot();
+  }
+  bool IsLookupSlot() const { return location_ == VariableLocation::LOOKUP; }
   bool IsGlobalObjectProperty() const;
+  bool IsStaticGlobalObjectProperty() const;
 
   bool is_dynamic() const { return IsDynamicVariableMode(mode_); }
   bool is_const_mode() const { return IsImmutableVariableMode(mode_); }
@@ -134,13 +114,13 @@ class Variable: public ZoneObject {
     local_if_not_shadowed_ = local;
   }
 
-  Location location() const { return location_; }
+  VariableLocation location() const { return location_; }
   int index() const { return index_; }
   InitializationFlag initialization_flag() const {
     return initialization_flag_;
   }
 
-  void AllocateTo(Location location, int index) {
+  void AllocateTo(VariableLocation location, int index) {
     location_ = location;
     index_ = index;
   }
@@ -171,7 +151,7 @@ class Variable: public ZoneObject {
   const AstRawString* name_;
   VariableMode mode_;
   Kind kind_;
-  Location location_;
+  VariableLocation location_;
   int index_;
   int initializer_position_;
   // Tracks whether the variable is bound to a VariableProxy which is in strong
index 00a0d8f..0aa76bd 100644 (file)
@@ -351,7 +351,7 @@ void FullCodeGenerator::Generate() {
         VariableDeclaration* function = scope()->function();
         DCHECK(function->proxy()->var()->mode() == CONST ||
                function->proxy()->var()->mode() == CONST_LEGACY);
-        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
+        DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot());
         VisitVariableDeclaration(function);
       }
       VisitDeclarations(scope()->declarations());
@@ -844,7 +844,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
   Variable* variable = proxy->var();
   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       globals_->Add(variable->name(), zone());
       globals_->Add(variable->binding_needs_init()
                         ? isolate()->factory()->the_hole_value()
@@ -852,8 +853,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
                     zone());
       break;
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
@@ -861,7 +862,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         EmitDebugCheckDeclarationContext(variable);
@@ -872,7 +873,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
       __ Push(rsi);
       __ Push(variable->name());
@@ -902,7 +903,8 @@ void FullCodeGenerator::VisitFunctionDeclaration(
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       globals_->Add(variable->name(), zone());
       Handle<SharedFunctionInfo> function =
           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
@@ -912,15 +914,15 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       VisitForAccumulatorValue(declaration->fun());
       __ movp(StackOperand(variable), result_register());
       break;
     }
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       VisitForAccumulatorValue(declaration->fun());
@@ -938,7 +940,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       __ Push(rsi);
       __ Push(variable->name());
@@ -955,20 +957,21 @@ void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::UNALLOCATED:
+    case VariableLocation::GLOBAL:
       // TODO(rossberg)
       break;
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ ImportDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       // TODO(rossberg)
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::LOOKUP:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::LOOKUP:
       UNREACHABLE();
   }
 }
@@ -1463,7 +1466,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
   // Three cases: global variables, lookup variables, and all other types of
   // variables.
   switch (var->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Comment cmnt(masm_, "[ Global variable");
       __ Move(LoadDescriptor::NameRegister(), var->name());
       __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
@@ -1474,9 +1478,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
                                                : "[ Stack slot");
       if (var->binding_needs_init()) {
@@ -1544,7 +1548,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ Lookup slot");
       Label done, slow;
       // Generate code for loading from variables potentially shadowed
@@ -2646,7 +2650,7 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
                                                FeedbackVectorICSlot slot) {
-  if (var->IsUnallocated()) {
+  if (var->IsUnallocatedOrGlobalSlot()) {
     // Global var, const, or let.
     __ Move(StoreDescriptor::NameRegister(), var->name());
     __ movp(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
@@ -4753,7 +4757,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // "delete this" is allowed.
         bool is_this = var->HasThisName(isolate());
         DCHECK(is_sloppy(language_mode()) || is_this);
-        if (var->IsUnallocated()) {
+        if (var->IsUnallocatedOrGlobalSlot()) {
           __ Push(GlobalObjectOperand());
           __ Push(var->name());
           __ Push(Smi::FromInt(SLOPPY));
@@ -5113,7 +5117,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   DCHECK(!context()->IsEffect());
   DCHECK(!context()->IsTest());
 
-  if (proxy != NULL && proxy->var()->IsUnallocated()) {
+  if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
     Comment cmnt(masm_, "[ Global variable");
     __ Move(LoadDescriptor::NameRegister(), proxy->name());
     __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
index b408646..543dffe 100644 (file)
@@ -350,7 +350,7 @@ void FullCodeGenerator::Generate() {
         VariableDeclaration* function = scope()->function();
         DCHECK(function->proxy()->var()->mode() == CONST ||
                function->proxy()->var()->mode() == CONST_LEGACY);
-        DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
+        DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot());
         VisitVariableDeclaration(function);
       }
       VisitDeclarations(scope()->declarations());
@@ -820,15 +820,16 @@ void FullCodeGenerator::VisitVariableDeclaration(
   Variable* variable = proxy->var();
   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       globals_->Add(variable->name(), zone());
       globals_->Add(variable->binding_needs_init()
                         ? isolate()->factory()->the_hole_value()
                         : isolate()->factory()->undefined_value(), zone());
       break;
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         __ mov(StackOperand(variable),
@@ -836,7 +837,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::CONTEXT:
+    case VariableLocation::CONTEXT:
       if (hole_init) {
         Comment cmnt(masm_, "[ VariableDeclaration");
         EmitDebugCheckDeclarationContext(variable);
@@ -847,7 +848,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
       }
       break;
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
       __ push(esi);
       __ push(Immediate(variable->name()));
@@ -877,7 +878,8 @@ void FullCodeGenerator::VisitFunctionDeclaration(
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       globals_->Add(variable->name(), zone());
       Handle<SharedFunctionInfo> function =
           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
@@ -887,15 +889,15 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       VisitForAccumulatorValue(declaration->fun());
       __ mov(StackOperand(variable), result_register());
       break;
     }
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       VisitForAccumulatorValue(declaration->fun());
@@ -908,7 +910,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ FunctionDeclaration");
       __ push(esi);
       __ push(Immediate(variable->name()));
@@ -925,20 +927,21 @@ void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
   VariableProxy* proxy = declaration->proxy();
   Variable* variable = proxy->var();
   switch (variable->location()) {
-    case Variable::UNALLOCATED:
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED:
       // TODO(rossberg)
       break;
 
-    case Variable::CONTEXT: {
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, "[ ImportDeclaration");
       EmitDebugCheckDeclarationContext(variable);
       // TODO(rossberg)
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::LOOKUP:
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::LOOKUP:
       UNREACHABLE();
   }
 }
@@ -1421,7 +1424,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
   // Three cases: global variables, lookup variables, and all other types of
   // variables.
   switch (var->location()) {
-    case Variable::UNALLOCATED: {
+    case VariableLocation::GLOBAL:
+    case VariableLocation::UNALLOCATED: {
       Comment cmnt(masm_, "[ Global variable");
       __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
       __ mov(LoadDescriptor::NameRegister(), var->name());
@@ -1432,9 +1436,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::PARAMETER:
-    case Variable::LOCAL:
-    case Variable::CONTEXT: {
+    case VariableLocation::PARAMETER:
+    case VariableLocation::LOCAL:
+    case VariableLocation::CONTEXT: {
       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
                                                : "[ Stack variable");
       if (var->binding_needs_init()) {
@@ -1502,7 +1506,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       break;
     }
 
-    case Variable::LOOKUP: {
+    case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ Lookup variable");
       Label done, slow;
       // Generate code for loading from variables potentially shadowed
@@ -2638,7 +2642,7 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
                                                FeedbackVectorICSlot slot) {
-  if (var->IsUnallocated()) {
+  if (var->IsUnallocatedOrGlobalSlot()) {
     // Global var, const, or let.
     __ mov(StoreDescriptor::NameRegister(), var->name());
     __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
@@ -4735,7 +4739,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // "delete this" is allowed.
         bool is_this = var->HasThisName(isolate());
         DCHECK(is_sloppy(language_mode()) || is_this);
-        if (var->IsUnallocated()) {
+        if (var->IsUnallocatedOrGlobalSlot()) {
           __ push(GlobalObjectOperand());
           __ push(Immediate(var->name()));
           __ push(Immediate(Smi::FromInt(SLOPPY)));
@@ -5102,7 +5106,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   DCHECK(!context()->IsEffect());
   DCHECK(!context()->IsTest());
 
-  if (proxy != NULL && proxy->var()->IsUnallocated()) {
+  if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
     Comment cmnt(masm_, "[ Global variable");
     __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
     __ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name()));
index 5f9820c..ad05273 100644 (file)
@@ -51,7 +51,7 @@ struct TestHelper : public HandleAndZoneScope {
     i::Variable* var = scope->Lookup(name);
     CHECK(var);
 
-    if (var->location() == Variable::UNALLOCATED) {
+    if (var->location() == VariableLocation::UNALLOCATED) {
       CHECK_EQ(0, expected);
     } else {
       CHECK(var->IsStackAllocated());
index 0750f82..cf8a730 100644 (file)
@@ -311,7 +311,7 @@ TEST(VectorLoadICSlotSharing) {
   // Function f has 3 LoadICs, one for each o, but the ICs share the same
   // feedback vector IC slot.
   CompileRun(
-      "var o = 10;"
+      "o = 10;"
       "function f() {"
       "  var x = o + 10;"
       "  return o + x + o;"
index 628d225..d148824 100644 (file)
@@ -6,35 +6,38 @@
 
 // Locations in the type feedback vector where call counts are maintained for
 // the two calls made from bar();
-const kFooCallExtraIndex = 5;
-const kArrayCallExtraIndex = 9;
-
-function GetCallCount(func, slot) {
-  var vector = %GetTypeFeedbackVector(func);
-  // Call counts are recorded doubled.
-  var value = %FixedArrayGet(vector, slot);
-  return Math.floor(value / 2);
-}
-
-function foo(a) { return a[3] * 16; }
-
-function bar(a) {
-  var result = 0;
-  for (var i = 0; i < 10; i++) {
-    result = foo(a);
-    if (i % 2 === 0) {
-      var r = Array();
-      r[0] = 1;
-      result += r[0];
+
+(function() {
+  const kFooCallExtraIndex = 5;
+  const kArrayCallExtraIndex = 7;
+
+  function GetCallCount(func, slot) {
+    var vector = %GetTypeFeedbackVector(func);
+    // Call counts are recorded doubled.
+    var value = %FixedArrayGet(vector, slot);
+    return Math.floor(value / 2);
+  }
+
+  function foo(a) { return a[3] * 16; }
+
+  function bar(a) {
+    var result = 0;
+    for (var i = 0; i < 10; i++) {
+      result = foo(a);
+      if (i % 2 === 0) {
+        var r = Array();
+        r[0] = 1;
+        result += r[0];
+      }
     }
+    return result;
   }
-  return result;
-}
 
-var a = [1, 2, 3];
-bar(a);
-assertEquals(10, GetCallCount(bar, kFooCallExtraIndex));
-assertEquals(5, GetCallCount(bar, kArrayCallExtraIndex));
+  var a = [1, 2, 3];
+  bar(a);
+  assertEquals(10, GetCallCount(bar, kFooCallExtraIndex));
+  assertEquals(5, GetCallCount(bar, kArrayCallExtraIndex));
 
-%OptimizeFunctionOnNextCall(bar);
-bar(a);
+  %OptimizeFunctionOnNextCall(bar);
+  bar(a);
+})();