Index: src/scopes.cc |
diff --git a/src/scopes.cc b/src/scopes.cc |
index c9612577afa22c56e5461e543c8edcb3a9adeb63..8ef969e653f1229ddf9f5c122b7378507024119a 100644 |
--- a/src/scopes.cc |
+++ b/src/scopes.cc |
@@ -108,6 +108,7 @@ Scope::Scope(Scope* outer_scope, ScopeType type, Zone* zone) |
: isolate_(Isolate::Current()), |
inner_scopes_(4, zone), |
variables_(zone), |
+ internals_(4, zone), |
temps_(4, zone), |
params_(4, zone), |
unresolved_(16, zone), |
@@ -131,6 +132,7 @@ Scope::Scope(Scope* inner_scope, |
: isolate_(Isolate::Current()), |
inner_scopes_(4, zone), |
variables_(zone), |
+ internals_(4, zone), |
temps_(4, zone), |
params_(4, zone), |
unresolved_(16, zone), |
@@ -153,6 +155,7 @@ Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone) |
: isolate_(Isolate::Current()), |
inner_scopes_(1, zone), |
variables_(zone), |
+ internals_(0, zone), |
temps_(0, zone), |
params_(0, zone), |
unresolved_(0, zone), |
@@ -197,6 +200,8 @@ void Scope::SetDefaults(ScopeType type, |
num_var_or_const_ = 0; |
num_stack_slots_ = 0; |
num_heap_slots_ = 0; |
+ num_modules_ = 0; |
+ module_var_ = NULL, |
scope_info_ = scope_info; |
start_position_ = RelocInfo::kNoPosition; |
end_position_ = RelocInfo::kNoPosition; |
@@ -375,6 +380,7 @@ void Scope::Initialize() { |
Scope* Scope::FinalizeBlockScope() { |
ASSERT(is_block_scope()); |
+ ASSERT(internals_.is_empty()); |
ASSERT(temps_.is_empty()); |
ASSERT(params_.is_empty()); |
@@ -515,6 +521,19 @@ void Scope::RemoveUnresolved(VariableProxy* var) { |
} |
+Variable* Scope::NewInternal(Handle<String> name) { |
+ ASSERT(!already_resolved()); |
+ Variable* var = new(zone()) Variable(this, |
+ name, |
+ INTERNAL, |
+ false, |
+ Variable::NORMAL, |
+ kCreatedInitialized); |
+ internals_.Add(var, zone()); |
+ return var; |
+} |
+ |
+ |
Variable* Scope::NewTemporary(Handle<String> name) { |
ASSERT(!already_resolved()); |
Variable* var = new(zone()) Variable(this, |
@@ -615,6 +634,15 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, |
ASSERT(stack_locals != NULL); |
ASSERT(context_locals != NULL); |
+ // Collect internals which are always allocated on the heap. |
+ for (int i = 0; i < internals_.length(); i++) { |
+ Variable* var = internals_[i]; |
+ if (var->is_used()) { |
+ ASSERT(var->IsContextSlot()); |
+ context_locals->Add(var, zone()); |
+ } |
+ } |
+ |
// Collect temporaries which are always allocated on the stack. |
for (int i = 0; i < temps_.length(); i++) { |
Variable* var = temps_[i]; |
@@ -624,9 +652,8 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, |
} |
} |
- ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); |
- |
// Collect declared local variables. |
+ ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); |
for (VariableMap::Entry* p = variables_.Start(); |
p != NULL; |
p = variables_.Next(p)) { |
@@ -659,18 +686,18 @@ bool Scope::AllocateVariables(CompilationInfo* info, |
} |
PropagateScopeInfo(outer_scope_calls_non_strict_eval); |
- // 2) Resolve variables. |
+ // 2) Allocate module instances. |
+ if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) { |
+ ASSERT(num_modules_ == 0); |
+ AllocateModulesRecursively(this); |
+ } |
+ |
+ // 3) Resolve variables. |
if (!ResolveVariablesRecursively(info, factory)) return false; |
- // 3) Allocate variables. |
+ // 4) Allocate variables. |
AllocateVariablesRecursively(); |
- // 4) Allocate and link module instance objects. |
- if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) { |
- AllocateModules(info); |
- LinkModules(info); |
- } |
- |
return true; |
} |
@@ -742,6 +769,15 @@ int Scope::ContextChainLength(Scope* scope) { |
} |
+Scope* Scope::GlobalScope() { |
+ Scope* scope = this; |
+ while (!scope->is_global_scope()) { |
+ scope = scope->outer_scope(); |
+ } |
+ return scope; |
+} |
+ |
+ |
Scope* Scope::DeclarationScope() { |
Scope* scope = this; |
while (!scope->is_declaration_scope()) { |
@@ -915,6 +951,11 @@ void Scope::Print(int n) { |
PrintVar(n1, temps_[i]); |
} |
+ Indent(n1, "// internal vars\n"); |
+ for (int i = 0; i < internals_.length(); i++) { |
+ PrintVar(n1, internals_[i]); |
+ } |
+ |
Indent(n1, "// local vars\n"); |
PrintMap(n1, &variables_); |
@@ -1065,7 +1106,6 @@ bool Scope::ResolveVariable(CompilationInfo* info, |
} |
ASSERT(var != NULL); |
- proxy->BindTo(var); |
if (FLAG_harmony_modules) { |
bool ok; |
@@ -1101,6 +1141,8 @@ bool Scope::ResolveVariable(CompilationInfo* info, |
} |
} |
+ proxy->BindTo(var); |
+ |
return true; |
} |
@@ -1175,6 +1217,7 @@ bool Scope::MustAllocateInContext(Variable* var) { |
// Exceptions: temporary variables are never allocated in a context; |
// catch-bound variables are always allocated in a context. |
if (var->mode() == TEMPORARY) return false; |
+ if (var->mode() == INTERNAL) return true; |
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() || |
@@ -1281,15 +1324,17 @@ void Scope::AllocateNonParameterLocals() { |
AllocateNonParameterLocal(temps_[i]); |
} |
- ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); |
+ for (int i = 0; i < internals_.length(); i++) { |
+ AllocateNonParameterLocal(internals_[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); |
vars.Add(VarAndOrder(var, p->order), zone()); |
} |
- |
vars.Sort(VarAndOrder::Compare); |
int var_count = vars.length(); |
for (int i = 0; i < var_count; i++) { |
@@ -1342,89 +1387,35 @@ void Scope::AllocateVariablesRecursively() { |
} |
-int Scope::StackLocalCount() const { |
- return num_stack_slots() - |
- (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
-} |
- |
- |
-int Scope::ContextLocalCount() const { |
- if (num_heap_slots() == 0) return 0; |
- return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
- (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
-} |
- |
- |
-void Scope::AllocateModules(CompilationInfo* info) { |
- ASSERT(is_global_scope() || is_module_scope()); |
- |
+void Scope::AllocateModulesRecursively(Scope* host_scope) { |
+ if (already_resolved()) return; |
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); |
+ const char raw_name[] = ".module"; |
+ Handle<String> name = isolate_->factory()->LookupSymbol( |
+ Vector<const char>(raw_name, StrLength(raw_name))); |
+ ASSERT(module_var_ == NULL); |
+ module_var_ = host_scope->NewInternal(name); |
+ ++host_scope->num_modules_; |
} |
- // 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); |
- } |
+ inner_scope->AllocateModulesRecursively(host_scope); |
} |
} |
-void Scope::LinkModules(CompilationInfo* info) { |
- ASSERT(is_global_scope() || is_module_scope()); |
+int Scope::StackLocalCount() const { |
+ return num_stack_slots() - |
+ (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
+} |
- 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); |
- } |
- } |
+int Scope::ContextLocalCount() const { |
+ if (num_heap_slots() == 0) return 0; |
+ return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
+ (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
} |
- |
} } // namespace v8::internal |