From 8fe17a6780e763d4367b4aeaf44b6f572d4bdd70 Mon Sep 17 00:00:00 2001 From: ishell Date: Mon, 6 Jul 2015 09:36:28 -0700 Subject: [PATCH] Support for global var shortcuts in script contexts. Review URL: https://codereview.chromium.org/1218783005 Cr-Commit-Position: refs/heads/master@{#29498} --- src/arm/full-codegen-arm.cc | 52 +++++----- src/arm64/full-codegen-arm64.cc | 52 +++++----- src/ast.cc | 13 +-- src/ast.h | 4 +- src/compiler/ast-graph-builder.cc | 70 +++++++------ src/contexts.cc | 30 +++++- src/contexts.h | 4 + src/factory.cc | 3 +- src/globals.h | 34 +++++++ src/heap/heap.cc | 4 + src/heap/heap.h | 1 + src/hydrogen.cc | 68 +++++++------ src/ia32/full-codegen-ia32.cc | 52 +++++----- src/liveedit.cc | 5 +- src/mips/full-codegen-mips.cc | 52 +++++----- src/mips64/full-codegen-mips64.cc | 52 +++++----- src/objects.h | 10 +- src/parser.cc | 2 +- src/ppc/full-codegen-ppc.cc | 46 +++++---- src/prettyprinter.cc | 13 ++- src/runtime/runtime-debug.cc | 30 ++++-- src/runtime/runtime-scopes.cc | 9 +- src/scopeinfo.cc | 108 ++++++++++++++++----- src/scopeinfo.h | 36 +++++-- src/scopes.cc | 102 ++++++++++++++----- src/scopes.h | 7 +- src/typing.cc | 4 +- src/variables.cc | 12 ++- src/variables.h | 50 +++------- src/x64/full-codegen-x64.cc | 52 +++++----- src/x87/full-codegen-x87.cc | 52 +++++----- .../compiler/test-loop-assignment-analysis.cc | 2 +- test/cctest/test-feedback-vector.cc | 2 +- test/mjsunit/call-counts.js | 59 +++++------ 34 files changed, 686 insertions(+), 406 deletions(-) diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 059ffe6..65abe07 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -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 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())); diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc index 0345751..ece2017 100644 --- a/src/arm64/full-codegen-arm64.cc +++ b/src/arm64/full-codegen-arm64.cc @@ -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 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())); diff --git a/src/ast.cc b/src/ast.cc index 93331d5..8ce5e7e 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -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; diff --git a/src/ast.h b/src/ast.h index c281408..e5842c2 100644 --- 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 { diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 31cd3fd..93a33f5 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -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 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 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 = 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 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 = 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()); diff --git a/src/contexts.cc b/src/contexts.cc index 0c27681..b29405b 100644 --- a/src/contexts.cc +++ b/src/contexts.cc @@ -40,10 +40,10 @@ bool ScriptContextTable::Lookup(Handle table, DCHECK(context->IsScriptContext()); Handle 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 Context::Lookup(Handle 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 Context::Lookup(Handle 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 diff --git a/src/contexts.h b/src/contexts.h index 6412b4f..1210848 100644 --- a/src/contexts.h +++ b/src/contexts.h @@ -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); diff --git a/src/factory.cc b/src/factory.cc index 7df095d..2b79a5b 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -689,7 +689,8 @@ Handle Factory::NewPrivateSymbol(Handle name) { Handle Factory::NewNativeContext() { - Handle array = NewFixedArray(Context::NATIVE_CONTEXT_SLOTS); + Handle array = + NewFixedArray(Context::NATIVE_CONTEXT_SLOTS, TENURED); array->set_map_no_write_barrier(*native_context_map()); Handle context = Handle::cast(array); context->set_js_array_maps(*undefined_value()); diff --git a/src/globals.h b/src/globals.h index 0f6fa2f..f85e929 100644 --- a/src/globals.h +++ b/src/globals.h @@ -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 diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 56a7941..51d4dfe 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -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( diff --git a/src/heap/heap.h b/src/heap/heap.h index 3ce381d..be280a0 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -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. diff --git a/src/hydrogen.cc b/src/hydrogen.cc index ae3b715..640befc 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -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 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); } } diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 132a949..5fd4414 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -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 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())); diff --git a/src/liveedit.cc b/src/liveedit.cc index afa0e13..150dcb8 100644 --- a/src/liveedit.cc +++ b/src/liveedit.cc @@ -764,7 +764,10 @@ class FunctionInfoListener { ZoneList stack_list(current_scope->StackLocalCount(), zone); ZoneList context_list( current_scope->ContextLocalCount(), zone); - current_scope->CollectStackAndContextLocals(&stack_list, &context_list); + ZoneList 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++) { diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index b9df1e1..de4f424 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -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 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())); diff --git a/src/mips64/full-codegen-mips64.cc b/src/mips64/full-codegen-mips64.cc index 50e0dfe..ed6bd15 100644 --- a/src/mips64/full-codegen-mips64.cc +++ b/src/mips64/full-codegen-mips64.cc @@ -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 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())); diff --git a/src/objects.h b/src/objects.h index c52ccc9..dc96725 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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 scope_info, Handle 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 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 }; diff --git a/src/parser.cc b/src/parser.cc index 147f562..d795b3c 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -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; } diff --git a/src/ppc/full-codegen-ppc.cc b/src/ppc/full-codegen-ppc.cc index e8bae82..2175863 100644 --- a/src/ppc/full-codegen-ppc.cc +++ b/src/ppc/full-codegen-ppc.cc @@ -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 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 diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc index 03ef4de..6a7718a 100644 --- a/src/prettyprinter.cc +++ b/src/prettyprinter.cc @@ -1436,18 +1436,21 @@ void AstPrinter::VisitVariableProxy(VariableProxy* node) { EmbeddedVector 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; } diff --git a/src/runtime/runtime-debug.cc b/src/runtime/runtime-debug.cc index e8919b5..9aa4341 100644 --- a/src/runtime/runtime-debug.cc +++ b/src/runtime/runtime-debug.cc @@ -681,11 +681,13 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { if (scope_info->LocalIsSynthetic(i)) continue; Handle 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 info, Handle 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 MaterializeReceiver(Isolate* isolate, Handle 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 scope_info, Handle 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) { diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc index 8b34b6c..700925d 100644 --- a/src/runtime/runtime-scopes.cc +++ b/src/runtime/runtime-scopes.cc @@ -632,7 +632,6 @@ RUNTIME_FUNCTION(Runtime_NewScriptContext) { Handle script_context_table( native_context->script_context_table()); - Handle 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 closure(native_context->closure()); + Handle closure(global_object->IsJSBuiltinsObject() + ? *function + : native_context->closure()); Handle 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 new_script_context_table = ScriptContextTable::Extend(script_context_table, result); diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc index f77ef96..4ed22b1 100644 --- a/src/scopeinfo.cc +++ b/src/scopeinfo.cc @@ -19,16 +19,20 @@ Handle ScopeInfo::Create(Isolate* isolate, Zone* zone, // Collect stack and context locals. ZoneList stack_locals(scope->StackLocalCount(), zone); ZoneList context_locals(scope->ContextLocalCount(), zone); + ZoneList context_globals(scope->ContextGlobalCount(), zone); ZoneList 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::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::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::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::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::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::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::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 scope_info, Handle 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 data, Handle 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 data, Handle 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 data, Handle name, VariableMode mode, + VariableLocation location, InitializationFlag init_flag, MaybeAssignedFlag maybe_assigned_flag, int slot_index) { @@ -712,6 +775,7 @@ void ContextSlotCache::ValidateEntry(Handle data, Handle 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); diff --git a/src/scopeinfo.h b/src/scopeinfo.h index 70a17cd..adefaef 100644 --- a/src/scopeinfo.h +++ b/src/scopeinfo.h @@ -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 data, Handle 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 data, Handle 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 {}; class InitField : public BitField {}; class MaybeAssignedField : public BitField {}; - class IndexField : public BitField {}; + class VariableLocationField : public BitField { + }; + class IndexField : public BitField {}; private: uint32_t value_; diff --git a/src/scopes.cc b/src/scopes.cc index 64f9584..f9eef9a 100644 --- a/src/scopes.cc +++ b/src/scopes.cc @@ -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* stack_locals, ZoneList* context_locals, + ZoneList* context_globals, ZoneList* 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(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 diff --git a/src/scopes.h b/src/scopes.h index 1b43f8e..4086380 100644 --- a/src/scopes.h +++ b/src/scopes.h @@ -442,6 +442,7 @@ class Scope: public ZoneObject { // handled separately. void CollectStackAndContextLocals( ZoneList* stack_locals, ZoneList* context_locals, + ZoneList* context_globals, ZoneList* 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(); diff --git a/src/typing.cc b/src/typing.cc index 6f5cd1c..2f10328 100644 --- a/src/typing.cc +++ b/src/typing.cc @@ -105,7 +105,9 @@ void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) { ZoneList local_vars(locals, zone()); ZoneList context_vars(scope->ContextLocalCount(), zone()); - scope->CollectStackAndContextLocals(&local_vars, &context_vars); + ZoneList 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), diff --git a/src/variables.cc b/src/variables.cc index 49846fe..18a45ab 100644 --- a/src/variables.cc +++ b/src/variables.cc @@ -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(); } diff --git a/src/variables.h b/src/variables.h index 218eefa..deebc5f 100644 --- a/src/variables.h +++ b/src/variables.h @@ -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 diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 00a0d8f..0aa76bd 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -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 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()); diff --git a/src/x87/full-codegen-x87.cc b/src/x87/full-codegen-x87.cc index b408646..543dffe 100644 --- a/src/x87/full-codegen-x87.cc +++ b/src/x87/full-codegen-x87.cc @@ -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 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())); diff --git a/test/cctest/compiler/test-loop-assignment-analysis.cc b/test/cctest/compiler/test-loop-assignment-analysis.cc index 5f9820c..ad05273 100644 --- a/test/cctest/compiler/test-loop-assignment-analysis.cc +++ b/test/cctest/compiler/test-loop-assignment-analysis.cc @@ -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()); diff --git a/test/cctest/test-feedback-vector.cc b/test/cctest/test-feedback-vector.cc index 0750f82..cf8a730 100644 --- a/test/cctest/test-feedback-vector.cc +++ b/test/cctest/test-feedback-vector.cc @@ -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;" diff --git a/test/mjsunit/call-counts.js b/test/mjsunit/call-counts.js index 628d225..d148824 100644 --- a/test/mjsunit/call-counts.js +++ b/test/mjsunit/call-counts.js @@ -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); +})(); -- 2.7.4