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

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

Issue 2302783002: [modules] Basic support of exports (Closed)
Patch Set: Disable module tests for deopt fuzzer. 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
« no previous file with comments | « 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 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();
« no previous file with comments | « src/heap/heap.cc ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698