| 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
|
|
|