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

Unified Diff: src/interpreter/bytecode-generator.cc

Issue 2302783002: [modules] Basic support of exports (Closed)
Patch Set: . Created 4 years, 3 months 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
Index: src/interpreter/bytecode-generator.cc
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
index d5fa0d0bc0fabf1bd920e75f93acfaeaff290dc7..56d0292109523d4dc75bab0bdc535e5df11addb2 100644
--- a/src/interpreter/bytecode-generator.cc
+++ b/src/interpreter/bytecode-generator.cc
@@ -743,7 +743,6 @@ void BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) {
VisitGeneratorPrologue();
}
- // Build function context only if there are context allocated variables.
neis 2016/09/02 12:06:07 This comment was not quite right: a scope may not
if (scope()->NeedsContext()) {
// Push a new inner context scope for the function.
VisitNewLocalFunctionContext();
neis 2016/09/02 12:06:07 I'm not happy with this name, as it can also creat
adamk 2016/09/02 17:51:51 BuildNewContext?
rmcilroy 2016/09/05 11:36:07 Could we do a rename pass on all the context creat
@@ -940,7 +939,8 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
break;
}
case VariableLocation::MODULE:
- UNREACHABLE();
+ // Nothing to do here.
+ break;
}
}
@@ -980,7 +980,11 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
break;
}
case VariableLocation::MODULE:
- UNREACHABLE();
+ DCHECK(variable->mode() == LET);
+ VisitForAccumulatorValue(decl->fun());
+ VisitVariableAssignment(variable, Token::INIT,
+ FeedbackVectorSlot::Invalid());
+ break;
}
}
@@ -1986,8 +1990,21 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable,
builder()->LoadLookupSlot(variable->name(), typeof_mode);
break;
}
- case VariableLocation::MODULE:
- UNREACHABLE();
+ case VariableLocation::MODULE: {
+ ModuleDescriptor* descriptor = scope()->GetModuleScope()->module();
+ if (variable->IsExport()) {
+ auto it = descriptor->regular_exports().find(variable->raw_name());
+ DCHECK(it != descriptor->regular_exports().end());
+ Register export_name = register_allocator()->NewRegister();
+ builder()
+ ->LoadLiteral(it->second->export_name->string())
+ .StoreAccumulatorInRegister(export_name)
+ .CallRuntime(Runtime::kLoadModuleExport, export_name, 1);
+ } else {
+ UNIMPLEMENTED();
+ }
+ break;
+ }
}
execution_result()->SetResultInAccumulator();
}
@@ -2185,8 +2202,33 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
builder()->StoreLookupSlot(variable->name(), language_mode());
break;
}
- case VariableLocation::MODULE:
- UNREACHABLE();
+ case VariableLocation::MODULE: {
+ DCHECK(IsDeclaredVariableMode(mode));
+
+ if (mode == CONST && op != Token::INIT) {
+ builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
+ break;
+ }
+
+ // If we don't throw above, we know that we're dealing with an
+ // export because imports are const and we do not generate initializing
+ // assignments for them.
+ DCHECK(variable->IsExport());
+
+ ModuleDescriptor* mod = scope()->GetModuleScope()->module();
+ auto it = mod->regular_exports().find(variable->raw_name());
+ DCHECK(it != mod->regular_exports().end());
+
+ register_allocator()->PrepareForConsecutiveAllocations(2);
+ Register export_name = register_allocator()->NextConsecutiveRegister();
+ Register value = register_allocator()->NextConsecutiveRegister();
+ builder()
+ ->StoreAccumulatorInRegister(value)
+ .LoadLiteral(it->second->export_name->string())
+ .StoreAccumulatorInRegister(export_name)
+ .CallRuntime(Runtime::kStoreModuleExport, export_name, 2);
+ break;
+ }
}
}
@@ -3143,8 +3185,26 @@ void BytecodeGenerator::VisitNewLocalFunctionContext() {
AccumulatorResultScope accumulator_execution_result(this);
Scope* scope = this->scope();
- // Allocate a new local context.
- if (scope->is_script_scope()) {
+ // Create the appropriate context.
+ if (scope->is_module_scope()) {
+ // We don't need to do anything for the outer script scope.
+ DCHECK(scope->outer_scope()->is_script_scope());
+
+ RegisterAllocationScope register_scope(this);
+ Register module = register_allocator()->NewRegister();
+ Register closure = register_allocator()->NewRegister();
+ Register scope_info = register_allocator()->NewRegister();
+ DCHECK(Register::AreContiguous(module, closure, scope_info));
rmcilroy 2016/09/05 11:36:07 Please use PrepareForConsecutiveAllocations / Next
+ // A JSFunction representing a module is called with the module object as
+ // its sole argument, which we pass on to PushModuleContext.
+ builder()
+ ->MoveRegister(builder()->Parameter(1), module)
+ .LoadAccumulatorWithRegister(Register::function_closure())
+ .StoreAccumulatorInRegister(closure)
rmcilroy 2016/09/05 11:36:07 .MoveRegister(Register::function_closure(), closur
+ .LoadLiteral(scope->scope_info())
+ .StoreAccumulatorInRegister(scope_info)
+ .CallRuntime(Runtime::kPushModuleContext, module, 3);
+ } else if (scope->is_script_scope()) {
rmcilroy 2016/09/05 11:36:07 nit - could we do script scope first.
RegisterAllocationScope register_scope(this);
Register closure = register_allocator()->NewRegister();
Register scope_info = register_allocator()->NewRegister();
@@ -3292,8 +3352,7 @@ void BytecodeGenerator::VisitFunctionClosureForContext() {
AccumulatorResultScope accumulator_execution_result(this);
DeclarationScope* closure_scope =
execution_context()->scope()->GetClosureScope();
- if (closure_scope->is_script_scope() ||
- closure_scope->is_module_scope()) {
+ if (closure_scope->is_script_scope()) {
// Contexts nested in the native context have a canonical empty function as
// their closure, not the anonymous closure containing the global code.
Register native_context = register_allocator()->NewRegister();
@@ -3309,7 +3368,8 @@ void BytecodeGenerator::VisitFunctionClosureForContext() {
builder()->LoadContextSlot(execution_context()->reg(),
Context::CLOSURE_INDEX);
} else {
- DCHECK(closure_scope->is_function_scope());
+ DCHECK(closure_scope->is_function_scope() ||
+ closure_scope->is_module_scope());
builder()->LoadAccumulatorWithRegister(Register::function_closure());
}
execution_result()->SetResultInAccumulator();

Powered by Google App Engine
This is Rietveld 408576698