diff options
Diffstat (limited to 'src/3rdparty/v8/src/scopes.cc')
-rw-r--r-- | src/3rdparty/v8/src/scopes.cc | 399 |
1 files changed, 277 insertions, 122 deletions
diff --git a/src/3rdparty/v8/src/scopes.cc b/src/3rdparty/v8/src/scopes.cc index 6580378..d2a919a 100644 --- a/src/3rdparty/v8/src/scopes.cc +++ b/src/3rdparty/v8/src/scopes.cc @@ -29,6 +29,7 @@ #include "scopes.h" +#include "accessors.h" #include "bootstrapper.h" #include "compiler.h" #include "messages.h" @@ -59,7 +60,9 @@ static bool Match(void* key1, void* key2) { } -VariableMap::VariableMap() : ZoneHashMap(Match, 8) {} +VariableMap::VariableMap(Zone* zone) + : ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)), + zone_(zone) {} VariableMap::~VariableMap() {} @@ -71,24 +74,26 @@ Variable* VariableMap::Declare( Variable::Kind kind, InitializationFlag initialization_flag, Interface* interface) { - Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true); + Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true, + ZoneAllocationPolicy(zone())); if (p->value == NULL) { // The variable has not been declared yet -> insert it. ASSERT(p->key == name.location()); - p->value = new Variable(scope, - name, - mode, - is_valid_lhs, - kind, - initialization_flag, - interface); + p->value = new(zone()) Variable(scope, + name, + mode, + is_valid_lhs, + kind, + initialization_flag, + interface); } return reinterpret_cast<Variable*>(p->value); } Variable* VariableMap::Lookup(Handle<String> name) { - Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false); + Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false, + ZoneAllocationPolicy(NULL)); if (p != NULL) { ASSERT(*reinterpret_cast<String**>(p->key) == *name); ASSERT(p->value != NULL); @@ -101,39 +106,40 @@ Variable* VariableMap::Lookup(Handle<String> name) { // ---------------------------------------------------------------------------- // Implementation of Scope -Scope::Scope(Scope* outer_scope, ScopeType type) +Scope::Scope(Scope* outer_scope, ScopeType type, Zone* zone) : isolate_(Isolate::Current()), - inner_scopes_(4), - variables_(), - temps_(4), - params_(4), - unresolved_(16), - decls_(4), + inner_scopes_(4, zone), + variables_(zone), + temps_(4, zone), + params_(4, zone), + unresolved_(16, zone), + decls_(4, zone), interface_(FLAG_harmony_modules && (type == MODULE_SCOPE || type == GLOBAL_SCOPE) - ? Interface::NewModule() : NULL), - already_resolved_(false) { + ? Interface::NewModule(zone) : NULL), + already_resolved_(false), + zone_(zone) { SetDefaults(type, outer_scope, Handle<ScopeInfo>::null()); - // At some point we might want to provide outer scopes to - // eval scopes (by walking the stack and reading the scope info). - // In that case, the ASSERT below needs to be adjusted. - ASSERT_EQ(type == GLOBAL_SCOPE, outer_scope == NULL); + // The outermost scope must be a global scope. + ASSERT(type == GLOBAL_SCOPE || outer_scope != NULL); ASSERT(!HasIllegalRedeclaration()); } Scope::Scope(Scope* inner_scope, ScopeType type, - Handle<ScopeInfo> scope_info) + Handle<ScopeInfo> scope_info, + Zone* zone) : isolate_(Isolate::Current()), - inner_scopes_(4), - variables_(), - temps_(4), - params_(4), - unresolved_(16), - decls_(4), + inner_scopes_(4, zone), + variables_(zone), + temps_(4, zone), + params_(4, zone), + unresolved_(16, zone), + decls_(4, zone), interface_(NULL), - already_resolved_(true) { + already_resolved_(true), + zone_(zone) { SetDefaults(type, NULL, scope_info); if (!scope_info.is_null()) { num_heap_slots_ = scope_info_->ContextLength(); @@ -145,16 +151,17 @@ Scope::Scope(Scope* inner_scope, } -Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) +Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone) : isolate_(Isolate::Current()), - inner_scopes_(1), - variables_(), - temps_(0), - params_(0), - unresolved_(0), - decls_(0), + inner_scopes_(1, zone), + variables_(zone), + temps_(0, zone), + params_(0, zone), + unresolved_(0, zone), + decls_(0, zone), interface_(NULL), - already_resolved_(true) { + already_resolved_(true), + zone_(zone) { SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); AddInnerScope(inner_scope); ++num_var_or_const_; @@ -204,36 +211,53 @@ void Scope::SetDefaults(ScopeType type, } -Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope) { +Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope, + Zone* zone) { // Reconstruct the outer scope chain from a closure's context chain. Scope* current_scope = NULL; Scope* innermost_scope = NULL; bool contains_with = false; - while (!context->IsGlobalContext()) { + while (!context->IsNativeContext()) { if (context->IsWithContext()) { - Scope* with_scope = new Scope(current_scope, - WITH_SCOPE, - Handle<ScopeInfo>::null()); + Scope* with_scope = new(zone) Scope(current_scope, + WITH_SCOPE, + Handle<ScopeInfo>::null(), + zone); current_scope = with_scope; // All the inner scopes are inside a with. contains_with = true; for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { s->scope_inside_with_ = true; } + } else if (context->IsGlobalContext()) { + ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); + current_scope = new(zone) Scope(current_scope, + GLOBAL_SCOPE, + Handle<ScopeInfo>(scope_info), + zone); + } else if (context->IsModuleContext()) { + ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info()); + current_scope = new(zone) Scope(current_scope, + MODULE_SCOPE, + Handle<ScopeInfo>(scope_info), + zone); } else if (context->IsFunctionContext()) { ScopeInfo* scope_info = context->closure()->shared()->scope_info(); - current_scope = new Scope(current_scope, - FUNCTION_SCOPE, - Handle<ScopeInfo>(scope_info)); + current_scope = new(zone) Scope(current_scope, + FUNCTION_SCOPE, + Handle<ScopeInfo>(scope_info), + zone); } else if (context->IsBlockContext()) { ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); - current_scope = new Scope(current_scope, - BLOCK_SCOPE, - Handle<ScopeInfo>(scope_info)); + current_scope = new(zone) Scope(current_scope, + BLOCK_SCOPE, + Handle<ScopeInfo>(scope_info), + zone); } else { ASSERT(context->IsCatchContext()); String* name = String::cast(context->extension()); - current_scope = new Scope(current_scope, Handle<String>(name)); + current_scope = new(zone) Scope( + current_scope, Handle<String>(name), zone); } if (contains_with) current_scope->RecordWithStatement(); if (innermost_scope == NULL) innermost_scope = current_scope; @@ -265,7 +289,8 @@ bool Scope::Analyze(CompilationInfo* info) { // Allocate the variables. { - AstNodeFactory<AstNullVisitor> ast_node_factory(info->isolate()); + AstNodeFactory<AstNullVisitor> ast_node_factory(info->isolate(), + info->zone()); if (!top->AllocateVariables(info, &ast_node_factory)) return false; } @@ -309,7 +334,7 @@ void Scope::Initialize() { // Add this scope as a new inner scope of the outer scope. if (outer_scope_ != NULL) { - outer_scope_->inner_scopes_.Add(this); + outer_scope_->inner_scopes_.Add(this, zone()); scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); } else { scope_inside_with_ = is_with_scope(); @@ -374,7 +399,7 @@ Scope* Scope::FinalizeBlockScope() { // Move unresolved variables for (int i = 0; i < unresolved_.length(); i++) { - outer_scope()->unresolved_.Add(unresolved_[i]); + outer_scope()->unresolved_.Add(unresolved_[i], zone()); } return NULL; @@ -405,13 +430,8 @@ Variable* Scope::LocalLookup(Handle<String> name) { init_flag = kCreatedInitialized; } - Variable* var = - variables_.Declare(this, - name, - mode, - true, - Variable::NORMAL, - init_flag); + Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, + init_flag); var->AllocateTo(location, index); return var; } @@ -426,7 +446,7 @@ Variable* Scope::LookupFunctionVar(Handle<String> name, VariableMode mode; int index = scope_info_->FunctionContextSlotIndex(*name, &mode); if (index < 0) return NULL; - Variable* var = new Variable( + Variable* var = new(zone()) Variable( this, name, mode, true /* is valid LHS */, Variable::NORMAL, kCreatedInitialized); VariableProxy* proxy = factory->NewVariableProxy(var); @@ -455,9 +475,9 @@ Variable* Scope::Lookup(Handle<String> name) { void Scope::DeclareParameter(Handle<String> name, VariableMode mode) { ASSERT(!already_resolved()); ASSERT(is_function_scope()); - Variable* var = variables_.Declare( - this, name, mode, true, Variable::NORMAL, kCreatedInitialized); - params_.Add(var); + Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, + kCreatedInitialized); + params_.Add(var, zone()); } @@ -469,17 +489,14 @@ Variable* Scope::DeclareLocal(Handle<String> name, // This function handles VAR and CONST modes. DYNAMIC variables are // introduces during variable allocation, INTERNAL variables are allocated // explicitly, and TEMPORARY variables are allocated via NewTemporary(). - ASSERT(mode == VAR || - mode == CONST || - mode == CONST_HARMONY || - mode == LET); + ASSERT(IsDeclaredVariableMode(mode)); ++num_var_or_const_; return variables_.Declare( this, name, mode, true, Variable::NORMAL, init_flag, interface); } -Variable* Scope::DeclareGlobal(Handle<String> name) { +Variable* Scope::DeclareDynamicGlobal(Handle<String> name) { ASSERT(is_global_scope()); return variables_.Declare(this, name, @@ -504,19 +521,19 @@ void Scope::RemoveUnresolved(VariableProxy* var) { Variable* Scope::NewTemporary(Handle<String> name) { ASSERT(!already_resolved()); - Variable* var = new Variable(this, - name, - TEMPORARY, - true, - Variable::NORMAL, - kCreatedInitialized); - temps_.Add(var); + Variable* var = new(zone()) Variable(this, + name, + TEMPORARY, + true, + Variable::NORMAL, + kCreatedInitialized); + temps_.Add(var, zone()); return var; } void Scope::AddDeclaration(Declaration* declaration) { - decls_.Add(declaration); + decls_.Add(declaration, zone()); } @@ -582,6 +599,21 @@ VariableProxy* Scope::CheckAssignmentToConst() { } +class VarAndOrder { + public: + VarAndOrder(Variable* var, int order) : var_(var), order_(order) { } + Variable* var() const { return var_; } + int order() const { return order_; } + static int Compare(const VarAndOrder* a, const VarAndOrder* b) { + return a->order_ - b->order_; + } + + private: + Variable* var_; + int order_; +}; + + void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals) { ASSERT(stack_locals != NULL); @@ -592,21 +624,29 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, Variable* var = temps_[i]; if (var->is_used()) { ASSERT(var->IsStackLocal()); - stack_locals->Add(var); + stack_locals->Add(var, zone()); } } + ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); + // Collect declared local variables. for (VariableMap::Entry* p = variables_.Start(); p != NULL; p = variables_.Next(p)) { Variable* var = reinterpret_cast<Variable*>(p->value); if (var->is_used()) { - if (var->IsStackLocal()) { - stack_locals->Add(var); - } else if (var->IsContextSlot()) { - context_locals->Add(var); - } + vars.Add(VarAndOrder(var, p->order), zone()); + } + } + vars.Sort(VarAndOrder::Compare); + int var_count = vars.length(); + for (int i = 0; i < var_count; i++) { + Variable* var = vars[i].var(); + if (var->IsStackLocal()) { + stack_locals->Add(var, zone()); + } else if (var->IsContextSlot()) { + context_locals->Add(var, zone()); } } } @@ -629,12 +669,13 @@ bool Scope::AllocateVariables(CompilationInfo* info, // 3) Allocate variables. AllocateVariablesRecursively(); - return true; -} - + // 4) Allocate and link module instance objects. + if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) { + AllocateModules(info); + LinkModules(info); + } -bool Scope::AllowsLazyCompilation() const { - return !force_eager_compilation_ && HasTrivialOuterContext(); + return true; } @@ -662,23 +703,36 @@ bool Scope::HasTrivialOuterContext() const { } -bool Scope::AllowsLazyRecompilation() const { - return !force_eager_compilation_ && - !TrivialDeclarationScopesBeforeWithScope(); -} - - -bool Scope::TrivialDeclarationScopesBeforeWithScope() const { +bool Scope::HasLazyCompilableOuterContext() const { Scope* outer = outer_scope_; - if (outer == NULL) return false; + if (outer == NULL) return true; + // There are several reasons that prevent lazy compilation: + // - This scope is inside a with scope and all declaration scopes between + // them have empty contexts. Such declaration scopes become invisible + // during scope info deserialization. + // - This scope is inside a strict eval scope with variables that are + // potentially context allocated in an artificial function scope that + // is not deserialized correctly. outer = outer->DeclarationScope(); - while (outer != NULL) { - if (outer->is_with_scope()) return true; - if (outer->is_declaration_scope() && outer->num_heap_slots() > 0) - return false; - outer = outer->outer_scope_; + bool found_non_trivial_declarations = false; + for (const Scope* scope = outer; scope != NULL; scope = scope->outer_scope_) { + if (scope->is_eval_scope()) return false; + if (scope->is_with_scope() && !found_non_trivial_declarations) return false; + if (scope->is_declaration_scope() && scope->num_heap_slots() > 0) { + found_non_trivial_declarations = true; + } } - return false; + return true; +} + + +bool Scope::AllowsLazyCompilation() const { + return !force_eager_compilation_ && HasLazyCompilableOuterContext(); +} + + +bool Scope::AllowsLazyCompilationWithoutContext() const { + return !force_eager_compilation_ && HasTrivialOuterContext(); } @@ -703,7 +757,7 @@ Scope* Scope::DeclarationScope() { Handle<ScopeInfo> Scope::GetScopeInfo() { if (scope_info_.is_null()) { - scope_info_ = ScopeInfo::Create(this); + scope_info_ = ScopeInfo::Create(this, zone()); } return scope_info_; } @@ -889,7 +943,7 @@ void Scope::Print(int n) { Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) { - if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); + if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone()); VariableMap* map = dynamics_->GetMap(mode); Variable* var = map->Lookup(name); if (var == NULL) { @@ -979,6 +1033,24 @@ bool Scope::ResolveVariable(CompilationInfo* info, switch (binding_kind) { case BOUND: // We found a variable binding. + if (is_qml_mode()) { + Handle<GlobalObject> global = isolate_->global_object(); + +#ifdef ENABLE_DEBUGGER_SUPPORT + if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { + // Get the context before the debugger was entered. + SaveContext *save = isolate_->save_context(); + while (save != NULL && *save->context() == *isolate_->debug()->debug_context()) + save = save->prev(); + + global = Handle<GlobalObject>(save->context()->global_object()); + } +#endif + + if (!global->HasProperty(*(proxy->name()))) { + var->set_is_qml_global(true); + } + } break; case BOUND_EVAL_SHADOWED: @@ -986,11 +1058,11 @@ bool Scope::ResolveVariable(CompilationInfo* info, // gave up on it (e.g. by encountering a local with the same in the outer // scope which was not promoted to a context, this can happen if we use // debugger to evaluate arbitrary expressions at a break point). - if (var->is_global()) { + if (var->IsGlobalObjectProperty()) { var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); if (is_qml_mode()) { - Handle<GlobalObject> global = isolate_->global(); + Handle<GlobalObject> global = isolate_->global_object(); #ifdef ENABLE_DEBUGGER_SUPPORT if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { @@ -999,11 +1071,11 @@ bool Scope::ResolveVariable(CompilationInfo* info, while (save != NULL && *save->context() == *isolate_->debug()->debug_context()) save = save->prev(); - global = Handle<GlobalObject>(save->context()->global()); + global = Handle<GlobalObject>(save->context()->global_object()); } #endif - if (is_qml_mode() && !global->HasProperty(*(proxy->name()))) { + if (!global->HasProperty(*(proxy->name()))) { var->set_is_qml_global(true); } } @@ -1017,11 +1089,11 @@ bool Scope::ResolveVariable(CompilationInfo* info, break; case UNBOUND: - // No binding has been found. Declare a variable in global scope. - var = info->global_scope()->DeclareGlobal(proxy->name()); + // No binding has been found. Declare a variable on the global object. + var = info->global_scope()->DeclareDynamicGlobal(proxy->name()); if (is_qml_mode()) { - Handle<GlobalObject> global = isolate_->global(); + Handle<GlobalObject> global = isolate_->global_object(); #ifdef ENABLE_DEBUGGER_SUPPORT if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { @@ -1030,7 +1102,7 @@ bool Scope::ResolveVariable(CompilationInfo* info, while (save != NULL && *save->context() == *isolate_->debug()->debug_context()) save = save->prev(); - global = Handle<GlobalObject>(save->context()->global()); + global = Handle<GlobalObject>(save->context()->global_object()); } #endif @@ -1047,7 +1119,7 @@ bool Scope::ResolveVariable(CompilationInfo* info, var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); if (is_qml_mode()) { - Handle<GlobalObject> global = isolate_->global(); + Handle<GlobalObject> global = isolate_->global_object(); #ifdef ENABLE_DEBUGGER_SUPPORT if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { @@ -1056,11 +1128,11 @@ bool Scope::ResolveVariable(CompilationInfo* info, while (save != NULL && *save->context() == *isolate_->debug()->debug_context()) save = save->prev(); - global = Handle<GlobalObject>(save->context()->global()); + global = Handle<GlobalObject>(save->context()->global_object()); } #endif - if (is_qml_mode() && !global->HasProperty(*(proxy->name()))) { + if (!global->HasProperty(*(proxy->name()))) { var->set_is_qml_global(true); } } @@ -1082,7 +1154,7 @@ bool Scope::ResolveVariable(CompilationInfo* info, if (FLAG_print_interface_details) PrintF("# Resolve %s:\n", var->name()->ToAsciiArray()); #endif - proxy->interface()->Unify(var->interface(), &ok); + proxy->interface()->Unify(var->interface(), zone(), &ok); if (!ok) { #ifdef DEBUG if (FLAG_print_interfaces) { @@ -1165,11 +1237,13 @@ bool Scope::MustAllocate(Variable* var) { inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() || - is_block_scope())) { + is_block_scope() || + is_module_scope() || + is_global_scope())) { var->set_is_used(true); } // Global variables do not need to be allocated. - return !var->is_global() && var->is_used(); + return !var->IsGlobalObjectProperty() && var->is_used(); } @@ -1183,11 +1257,11 @@ bool Scope::MustAllocateInContext(Variable* var) { // catch-bound variables are always allocated in a context. if (var->mode() == TEMPORARY) return false; if (is_catch_scope() || is_block_scope() || is_module_scope()) return true; + if (is_global_scope() && IsLexicalVariableMode(var->mode())) return true; return var->has_forced_context_allocation() || scope_calls_eval_ || inner_scope_calls_eval_ || - scope_contains_with_ || - var->is_global(); + scope_contains_with_; } @@ -1288,11 +1362,19 @@ void Scope::AllocateNonParameterLocals() { AllocateNonParameterLocal(temps_[i]); } + ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); + for (VariableMap::Entry* p = variables_.Start(); p != NULL; p = variables_.Next(p)) { Variable* var = reinterpret_cast<Variable*>(p->value); - AllocateNonParameterLocal(var); + vars.Add(VarAndOrder(var, p->order), zone()); + } + + vars.Sort(VarAndOrder::Compare); + int var_count = vars.length(); + for (int i = 0; i < var_count; i++) { + AllocateNonParameterLocal(vars[i].var()); } // For now, function_ must be allocated at the very end. If it gets @@ -1353,4 +1435,77 @@ int Scope::ContextLocalCount() const { (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); } + +void Scope::AllocateModules(CompilationInfo* info) { + ASSERT(is_global_scope() || is_module_scope()); + + if (is_module_scope()) { + ASSERT(interface_->IsFrozen()); + ASSERT(scope_info_.is_null()); + + // TODO(rossberg): This has to be the initial compilation of this code. + // We currently do not allow recompiling any module definitions. + Handle<ScopeInfo> scope_info = GetScopeInfo(); + Factory* factory = info->isolate()->factory(); + Handle<Context> context = factory->NewModuleContext(scope_info); + Handle<JSModule> instance = factory->NewJSModule(context, scope_info); + context->set_module(*instance); + + bool ok; + interface_->MakeSingleton(instance, &ok); + ASSERT(ok); + } + + // Allocate nested modules. + for (int i = 0; i < inner_scopes_.length(); i++) { + Scope* inner_scope = inner_scopes_.at(i); + if (inner_scope->is_module_scope()) { + inner_scope->AllocateModules(info); + } + } +} + + +void Scope::LinkModules(CompilationInfo* info) { + ASSERT(is_global_scope() || is_module_scope()); + + if (is_module_scope()) { + Handle<JSModule> instance = interface_->Instance(); + + // Populate the module instance object. + const PropertyAttributes ro_attr = + static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE | DONT_ENUM); + const PropertyAttributes rw_attr = + static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM); + for (Interface::Iterator it = interface_->iterator(); + !it.done(); it.Advance()) { + if (it.interface()->IsModule()) { + Handle<Object> value = it.interface()->Instance(); + ASSERT(!value.is_null()); + JSReceiver::SetProperty( + instance, it.name(), value, ro_attr, kStrictMode); + } else { + Variable* var = LocalLookup(it.name()); + ASSERT(var != NULL && var->IsContextSlot()); + PropertyAttributes attr = var->is_const_mode() ? ro_attr : rw_attr; + Handle<AccessorInfo> info = + Accessors::MakeModuleExport(it.name(), var->index(), attr); + Handle<Object> result = SetAccessor(instance, info); + ASSERT(!(result.is_null() || result->IsUndefined())); + USE(result); + } + } + USE(JSObject::PreventExtensions(instance)); + } + + // Link nested modules. + for (int i = 0; i < inner_scopes_.length(); i++) { + Scope* inner_scope = inner_scopes_.at(i); + if (inner_scope->is_module_scope()) { + inner_scope->LinkModules(info); + } + } +} + + } } // namespace v8::internal |