summaryrefslogtreecommitdiff
path: root/src/3rdparty/v8/src/scopes.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/v8/src/scopes.cc')
-rw-r--r--src/3rdparty/v8/src/scopes.cc399
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