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

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
« src/factory.cc ('K') | « src/heap/heap.cc ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/interpreter/bytecode-generator.cc
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
index 8f43b0764da7512cc775eb13a65a956fb545d4f2..7a96246610d15897e18d8eb60a0abed69e082dab 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.
if (scope()->NeedsContext()) {
// Push a new inner context scope for the function.
VisitNewLocalFunctionContext();
@@ -941,7 +940,8 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
break;
}
case VariableLocation::MODULE:
- UNREACHABLE();
+ // Nothing to do here.
+ break;
}
}
@@ -982,7 +982,10 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
break;
}
case VariableLocation::MODULE:
- UNREACHABLE();
+ VisitForAccumulatorValue(decl->fun());
adamk 2016/09/01 23:13:34 Add a DCHECK above here that the mode is LET?
neis 2016/09/02 11:32:58 Done.
+ VisitVariableAssignment(variable, Token::INIT,
+ FeedbackVectorSlot::Invalid());
+ break;
}
}
@@ -1989,8 +1992,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();
}
@@ -2189,8 +2205,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;
+ }
}
}
@@ -3141,8 +3182,26 @@ void BytecodeGenerator::VisitNewLocalFunctionContext() {
AccumulatorResultScope accumulator_execution_result(this);
Scope* scope = this->scope();
- // Allocate a new local context.
- if (scope->is_script_scope()) {
+ // Allocate a new local context. XXX
+ 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));
+ // 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)
+ .LoadLiteral(scope->scope_info())
+ .StoreAccumulatorInRegister(scope_info)
+ .CallRuntime(Runtime::kPushModuleContext, module, 3);
+ } else if (scope->is_script_scope()) {
RegisterAllocationScope register_scope(this);
Register closure = register_allocator()->NewRegister();
Register scope_info = register_allocator()->NewRegister();
@@ -3290,8 +3349,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();
@@ -3307,7 +3365,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();
« src/factory.cc ('K') | « src/heap/heap.cc ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698