Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Unified Diff: src/full-codegen.cc

Issue 11093074: Get rid of static module allocation, do it in code. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed last comments; added other back-ends Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/full-codegen.h ('k') | src/heap.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/full-codegen.cc
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 9592e0afa21c45aec364adb1e1557fae8f4d0551..01d9bd0714be04b4ff4de2f7a66e98da32c67349 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -86,6 +86,10 @@ void BreakableStatementChecker::VisitModuleUrl(ModuleUrl* module) {
}
+void BreakableStatementChecker::VisitModuleStatement(ModuleStatement* stmt) {
+}
+
+
void BreakableStatementChecker::VisitBlock(Block* stmt) {
}
@@ -582,16 +586,137 @@ void FullCodeGenerator::DoTest(const TestContext* context) {
}
+void FullCodeGenerator::AllocateModules(ZoneList<Declaration*>* declarations) {
+ ASSERT(scope_->is_global_scope());
+
+ for (int i = 0; i < declarations->length(); i++) {
+ ModuleDeclaration* declaration = declarations->at(i)->AsModuleDeclaration();
+ if (declaration != NULL) {
+ ModuleLiteral* module = declaration->module()->AsModuleLiteral();
+ if (module != NULL) {
+ Comment cmnt(masm_, "[ Link nested modules");
+ Scope* scope = module->body()->scope();
+ Interface* interface = scope->interface();
+ ASSERT(interface->IsModule() && interface->IsFrozen());
+
+ interface->Allocate(scope->module_var()->index());
+
+ // Set up module context.
+ ASSERT(scope->interface()->Index() >= 0);
+ __ Push(Smi::FromInt(scope->interface()->Index()));
+ __ Push(scope->GetScopeInfo());
+ __ CallRuntime(Runtime::kPushModuleContext, 2);
+ StoreToFrameField(StandardFrameConstants::kContextOffset,
+ context_register());
+
+ AllocateModules(scope->declarations());
+
+ // Pop module context.
+ LoadContextField(context_register(), Context::PREVIOUS_INDEX);
+ // Update local stack frame context field.
+ StoreToFrameField(StandardFrameConstants::kContextOffset,
+ context_register());
+ }
+ }
+ }
+}
+
+
+// Modules have their own local scope, represented by their own context.
+// Module instance objects have an accessor for every export that forwards
+// access to the respective slot from the module's context. (Exports that are
+// modules themselves, however, are simple data properties.)
+//
+// All modules have a _hosting_ scope/context, which (currently) is the
+// (innermost) enclosing global scope. To deal with recursion, nested modules
+// are hosted by the same scope as global ones.
+//
+// For every (global or nested) module literal, the hosting context has an
+// internal slot that points directly to the respective module context. This
+// enables quick access to (statically resolved) module members by 2-dimensional
+// access through the hosting context. For example,
+//
+// module A {
+// let x;
+// module B { let y; }
+// }
+// module C { let z; }
+//
+// allocates contexts as follows:
+//
+// [header| .A | .B | .C | A | C ] (global)
+// | | |
+// | | +-- [header| z ] (module)
+// | |
+// | +------- [header| y ] (module)
+// |
+// +------------ [header| x | B ] (module)
+//
+// Here, .A, .B, .C are the internal slots pointing to the hosted module
+// contexts, whereas A, B, C hold the actual instance objects (note that every
+// module context also points to the respective instance object through its
+// extension slot in the header).
+//
+// To deal with arbitrary recursion and aliases between modules,
+// they are created and initialized in several stages. Each stage applies to
+// all modules in the hosting global scope, including nested ones.
+//
+// 1. Allocate: for each module _literal_, allocate the module contexts and
+// respective instance object and wire them up. This happens in the
+// PushModuleContext runtime function, as generated by AllocateModules
+// (invoked by VisitDeclarations in the hosting scope).
+//
+// 2. Bind: for each module _declaration_ (i.e. literals as well as aliases),
+// assign the respective instance object to respective local variables. This
+// happens in VisitModuleDeclaration, and uses the instance objects created
+// in the previous stage.
+// For each module _literal_, this phase also constructs a module descriptor
+// for the next stage. This happens in VisitModuleLiteral.
+//
+// 3. Populate: invoke the DeclareModules runtime function to populate each
+// _instance_ object with accessors for it exports. This is generated by
+// DeclareModules (invoked by VisitDeclarations in the hosting scope again),
+// and uses the descriptors generated in the previous stage.
+//
+// 4. Initialize: execute the module bodies (and other code) in sequence. This
+// happens by the separate statements generated for module bodies. To reenter
+// the module scopes properly, the parser inserted ModuleStatements.
+
void FullCodeGenerator::VisitDeclarations(
ZoneList<Declaration*>* declarations) {
+ Handle<FixedArray> saved_modules = modules_;
+ int saved_module_index = module_index_;
ZoneList<Handle<Object> >* saved_globals = globals_;
ZoneList<Handle<Object> > inner_globals(10, zone());
globals_ = &inner_globals;
+ if (scope_->num_modules() != 0) {
+ // This is a scope hosting modules. Allocate a descriptor array to pass
+ // to the runtime for initialization.
+ Comment cmnt(masm_, "[ Allocate modules");
+ ASSERT(scope_->is_global_scope());
+ modules_ =
+ isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED);
+ module_index_ = 0;
+
+ // Generate code for allocating all modules, including nested ones.
+ // The allocated contexts are stored in internal variables in this scope.
+ AllocateModules(declarations);
+ }
+
AstVisitor::VisitDeclarations(declarations);
+
+ if (scope_->num_modules() != 0) {
+ // Initialize modules from descriptor array.
+ ASSERT(module_index_ == modules_->length());
+ DeclareModules(modules_);
+ modules_ = saved_modules;
+ module_index_ = saved_module_index;
+ }
+
if (!globals_->is_empty()) {
// Invoke the platform-dependent code generator to do the actual
- // declaration the global functions and variables.
+ // declaration of the global functions and variables.
Handle<FixedArray> array =
isolate()->factory()->NewFixedArray(globals_->length(), TENURED);
for (int i = 0; i < globals_->length(); ++i)
@@ -604,19 +729,23 @@ void FullCodeGenerator::VisitDeclarations(
void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) {
- // Allocate a module context statically.
Block* block = module->body();
Scope* saved_scope = scope();
scope_ = block->scope();
- Interface* interface = module->interface();
- Handle<JSModule> instance = interface->Instance();
+ Interface* interface = scope_->interface();
Comment cmnt(masm_, "[ ModuleLiteral");
SetStatementPosition(block);
+ ASSERT(!modules_.is_null());
+ ASSERT(module_index_ < modules_->length());
+ int index = module_index_++;
+
// Set up module context.
- __ Push(instance);
- __ CallRuntime(Runtime::kPushModuleContext, 1);
+ ASSERT(interface->Index() >= 0);
+ __ Push(Smi::FromInt(interface->Index()));
+ __ Push(Smi::FromInt(0));
+ __ CallRuntime(Runtime::kPushModuleContext, 2);
StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
{
@@ -624,6 +753,11 @@ void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) {
VisitDeclarations(scope_->declarations());
}
+ // Populate the module description.
+ Handle<ModuleInfo> description =
+ ModuleInfo::Create(isolate(), interface, scope_);
+ modules_->set(index, *description);
+
scope_ = saved_scope;
// Pop module context.
LoadContextField(context_register(), Context::PREVIOUS_INDEX);
@@ -644,8 +778,20 @@ void FullCodeGenerator::VisitModulePath(ModulePath* module) {
}
-void FullCodeGenerator::VisitModuleUrl(ModuleUrl* decl) {
- // TODO(rossberg)
+void FullCodeGenerator::VisitModuleUrl(ModuleUrl* module) {
+ // TODO(rossberg): dummy allocation for now.
+ Scope* scope = module->body()->scope();
+ Interface* interface = scope_->interface();
+
+ ASSERT(interface->IsModule() && interface->IsFrozen());
+ ASSERT(!modules_.is_null());
+ ASSERT(module_index_ < modules_->length());
+ interface->Allocate(scope->module_var()->index());
+ int index = module_index_++;
+
+ Handle<ModuleInfo> description =
+ ModuleInfo::Create(isolate(), interface, scope_);
+ modules_->set(index, *description);
}
@@ -904,37 +1050,28 @@ void FullCodeGenerator::VisitBlock(Block* stmt) {
// Push a block context when entering a block with block scoped variables.
if (stmt->scope() != NULL) {
scope_ = stmt->scope();
- if (scope_->is_module_scope()) {
- // If this block is a module body, then we have already allocated and
- // initialized the declarations earlier. Just push the context.
- ASSERT(!scope_->interface()->Instance().is_null());
- __ Push(scope_->interface()->Instance());
- __ CallRuntime(Runtime::kPushModuleContext, 1);
- StoreToFrameField(
- StandardFrameConstants::kContextOffset, context_register());
- } else {
- { Comment cmnt(masm_, "[ Extend block context");
- Handle<ScopeInfo> scope_info = scope_->GetScopeInfo();
- int heap_slots =
- scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS;
- __ Push(scope_info);
- PushFunctionArgumentForContextAllocation();
- if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) {
- FastNewBlockContextStub stub(heap_slots);
- __ CallStub(&stub);
- } else {
- __ CallRuntime(Runtime::kPushBlockContext, 2);
- }
-
- // Replace the context stored in the frame.
- StoreToFrameField(StandardFrameConstants::kContextOffset,
- context_register());
- }
- { Comment cmnt(masm_, "[ Declarations");
- VisitDeclarations(scope_->declarations());
+ ASSERT(!scope_->is_module_scope());
+ { Comment cmnt(masm_, "[ Extend block context");
+ Handle<ScopeInfo> scope_info = scope_->GetScopeInfo();
+ int heap_slots = scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS;
+ __ Push(scope_info);
+ PushFunctionArgumentForContextAllocation();
+ if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) {
+ FastNewBlockContextStub stub(heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kPushBlockContext, 2);
}
+
+ // Replace the context stored in the frame.
+ StoreToFrameField(StandardFrameConstants::kContextOffset,
+ context_register());
+ }
+ { Comment cmnt(masm_, "[ Declarations");
+ VisitDeclarations(scope_->declarations());
}
}
+
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
VisitStatements(stmt->statements());
scope_ = saved_scope;
@@ -951,6 +1088,26 @@ void FullCodeGenerator::VisitBlock(Block* stmt) {
}
+void FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) {
+ Comment cmnt(masm_, "[ Module context");
+
+ __ Push(Smi::FromInt(stmt->proxy()->interface()->Index()));
+ __ Push(Smi::FromInt(0));
+ __ CallRuntime(Runtime::kPushModuleContext, 2);
+ StoreToFrameField(
+ StandardFrameConstants::kContextOffset, context_register());
+
+ Scope* saved_scope = scope_;
+ scope_ = stmt->body()->scope();
+ VisitStatements(stmt->body()->statements());
+ scope_ = saved_scope;
+ LoadContextField(context_register(), Context::PREVIOUS_INDEX);
+ // Update local stack frame context field.
+ StoreToFrameField(StandardFrameConstants::kContextOffset,
+ context_register());
+}
+
+
void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Comment cmnt(masm_, "[ ExpressionStatement");
SetStatementPosition(stmt);
« no previous file with comments | « src/full-codegen.h ('k') | src/heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698