Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index e1e87546a9c23cf3ad8d798b07e95590f6f2e041..8822344e192ada7ee16104f1df28f184b9e5d501 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(); |
@@ -940,7 +939,8 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
break; |
} |
case VariableLocation::MODULE: |
- UNREACHABLE(); |
+ // Nothing to do here. |
+ break; |
} |
} |
@@ -979,7 +979,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; |
} |
} |
@@ -1978,8 +1982,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(); |
} |
@@ -2177,8 +2194,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; |
+ } |
} |
} |
@@ -3135,18 +3177,36 @@ void BytecodeGenerator::VisitNewLocalFunctionContext() { |
AccumulatorResultScope accumulator_execution_result(this); |
Scope* scope = this->scope(); |
- // Allocate a new local context. |
+ // Create the appropriate context. |
if (scope->is_script_scope()) { |
RegisterAllocationScope register_scope(this); |
- Register closure = register_allocator()->NewRegister(); |
- Register scope_info = register_allocator()->NewRegister(); |
- DCHECK(Register::AreContiguous(closure, scope_info)); |
+ register_allocator()->PrepareForConsecutiveAllocations(2); |
+ Register closure = register_allocator()->NextConsecutiveRegister(); |
+ Register scope_info = register_allocator()->NextConsecutiveRegister(); |
builder() |
->LoadAccumulatorWithRegister(Register::function_closure()) |
.StoreAccumulatorInRegister(closure) |
.LoadLiteral(scope->scope_info()) |
.StoreAccumulatorInRegister(scope_info) |
.CallRuntime(Runtime::kNewScriptContext, closure, 2); |
+ } else 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_allocator()->PrepareForConsecutiveAllocations(3); |
+ Register module = register_allocator()->NextConsecutiveRegister(); |
+ Register closure = register_allocator()->NextConsecutiveRegister(); |
+ Register scope_info = register_allocator()->NextConsecutiveRegister(); |
+ // 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 { |
int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
builder()->CreateFunctionContext(slot_count); |
@@ -3293,8 +3353,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(); |
@@ -3310,7 +3369,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(); |