Commit dd155e47 authored by neis's avatar neis Committed by Commit bot

[ignition,modules] Introduce bytecodes for loading/storing module variables.

This introduces two new bytecodes LdaModuleVariable and StaModuleVariable,
replacing the corresponding runtime calls.

Support in the bytecode graph builder exists only in the form of runtime calls.

BUG=v8:1569

Review-Url: https://codereview.chromium.org/2471033004
Cr-Commit-Position: refs/heads/master@{#40825}
parent 60d60fd7
......@@ -243,6 +243,7 @@ namespace internal {
V(kUnsupportedLetCompoundAssignment, "Unsupported let compound assignment") \
V(kUnsupportedLookupSlotInDeclaration, \
"Unsupported lookup slot in declaration") \
V(kUnsupportedModuleOperation, "Unsupported module operation") \
V(kUnsupportedNonPrimitiveCompare, "Unsupported non-primitive compare") \
V(kUnsupportedPhiUseOfArguments, "Unsupported phi use of arguments") \
V(kUnsupportedPhiUseOfConstVariable, \
......
......@@ -1138,6 +1138,25 @@ void BytecodeGraphBuilder::VisitStaKeyedPropertyStrict() {
BuildKeyedStore(LanguageMode::STRICT);
}
void BytecodeGraphBuilder::VisitLdaModuleVariable() {
// TODO(neis): Don't call the runtime.
PrepareEagerCheckpoint();
Node* index = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
const Operator* op = javascript()->CallRuntime(Runtime::kLoadModuleVariable);
Node* value = NewNode(op, index);
environment()->BindAccumulator(value, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitStaModuleVariable() {
// TODO(neis): Don't call the runtime.
PrepareEagerCheckpoint();
Node* index = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
Node* value = environment()->LookupAccumulator();
const Operator* op = javascript()->CallRuntime(Runtime::kStoreModuleVariable);
Node* store = NewNode(op, index, value);
environment()->RecordAfterState(store, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitPushContext() {
Node* new_context = environment()->LookupAccumulator();
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0),
......
......@@ -792,6 +792,18 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
int depth) {
OutputStaModuleVariable(cell_index, depth);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
int depth) {
OutputLdaModuleVariable(cell_index, depth);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
Register generator) {
OutputSuspendGenerator(generator);
......
......@@ -99,6 +99,14 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index,
int depth);
// Load from a module variable into the accumulator. |depth| is the depth of
// the current context relative to the module context.
BytecodeArrayBuilder& LoadModuleVariable(int cell_index, int depth);
// Store from the accumulator into a module variable. |depth| is the depth of
// the current context relative to the module context.
BytecodeArrayBuilder& StoreModuleVariable(int cell_index, int depth);
// Register-accumulator transfers.
BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
......
......@@ -1865,11 +1865,8 @@ void BytecodeGenerator::BuildVariableLoad(Variable* variable,
break;
}
case VariableLocation::MODULE: {
Register index = register_allocator()->NewRegister();
builder()
->LoadLiteral(Smi::FromInt(variable->index()))
.StoreAccumulatorInRegister(index)
.CallRuntime(Runtime::kLoadModuleVariable, index);
int depth = execution_context()->ContextChainDepth(variable->scope());
builder()->LoadModuleVariable(variable->index(), depth);
if (hole_check_mode == HoleCheckMode::kRequired) {
BuildThrowIfHole(variable->name());
}
......@@ -2037,18 +2034,16 @@ void BytecodeGenerator::BuildVariableAssignment(Variable* variable,
// assignments for them.
DCHECK(variable->IsExport());
RegisterList args = register_allocator()->NewRegisterList(2);
builder()
->StoreAccumulatorInRegister(args[1])
.LoadLiteral(Smi::FromInt(variable->index()))
.StoreAccumulatorInRegister(args[0]);
int depth = execution_context()->ContextChainDepth(variable->scope());
if (hole_check_mode == HoleCheckMode::kRequired) {
builder()->CallRuntime(Runtime::kLoadModuleVariable, args[0]);
Register value_temp = register_allocator()->NewRegister();
builder()
->StoreAccumulatorInRegister(value_temp)
.LoadModuleVariable(variable->index(), depth);
BuildHoleCheckForVariableAssignment(variable, op);
builder()->LoadAccumulatorWithRegister(value_temp);
}
builder()
->CallRuntime(Runtime::kStoreModuleVariable, args)
.LoadAccumulatorWithRegister(args[1]);
builder()->StoreModuleVariable(variable->index(), depth);
break;
}
}
......
......@@ -94,6 +94,12 @@ namespace interpreter {
V(LdrKeyedProperty, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kIdx, OperandType::kRegOut) \
\
/* Operations on module variables */ \
V(LdaModuleVariable, AccumulatorUse::kWrite, OperandType::kImm, \
OperandType::kUImm) \
V(StaModuleVariable, AccumulatorUse::kRead, OperandType::kImm, \
OperandType::kUImm) \
\
/* Propery stores (StoreIC) operations */ \
V(StaNamedPropertySloppy, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx) \
......
......@@ -928,6 +928,88 @@ void Interpreter::DoStaKeyedPropertyStrict(InterpreterAssembler* assembler) {
DoKeyedStoreIC(ic, assembler);
}
// LdaModuleVariable <cell_index> <depth>
//
// Load the contents of a module variable into the accumulator. The variable is
// identified by <cell_index>. <depth> is the depth of the current context
// relative to the module context.
void Interpreter::DoLdaModuleVariable(InterpreterAssembler* assembler) {
Node* cell_index = __ BytecodeOperandImm(0);
Node* depth = __ BytecodeOperandUImm(1);
Node* module_context = __ GetContextAtDepth(__ GetContext(), depth);
Node* module =
__ LoadContextElement(module_context, Context::EXTENSION_INDEX);
Label if_export(assembler), if_import(assembler), end(assembler);
__ Branch(__ IntPtrGreaterThan(cell_index, __ IntPtrConstant(0)), &if_export,
&if_import);
__ Bind(&if_export);
{
Node* regular_exports =
__ LoadObjectField(module, Module::kRegularExportsOffset);
// The actual array index is (cell_index - 1).
Node* export_index = __ IntPtrSub(cell_index, __ IntPtrConstant(1));
Node* cell = __ LoadFixedArrayElement(regular_exports, export_index);
__ SetAccumulator(__ LoadObjectField(cell, Cell::kValueOffset));
__ Goto(&end);
}
__ Bind(&if_import);
{
Node* regular_imports =
__ LoadObjectField(module, Module::kRegularImportsOffset);
// The actual array index is (-cell_index - 1).
Node* import_index = __ IntPtrSub(__ IntPtrConstant(-1), cell_index);
Node* cell = __ LoadFixedArrayElement(regular_imports, import_index);
__ SetAccumulator(__ LoadObjectField(cell, Cell::kValueOffset));
__ Goto(&end);
}
__ Bind(&end);
__ Dispatch();
}
// StaModuleVariable <cell_index> <depth>
//
// Store accumulator to the module variable identified by <cell_index>.
// <depth> is the depth of the current context relative to the module context.
void Interpreter::DoStaModuleVariable(InterpreterAssembler* assembler) {
Node* value = __ GetAccumulator();
Node* cell_index = __ BytecodeOperandImm(0);
Node* depth = __ BytecodeOperandUImm(1);
Node* module_context = __ GetContextAtDepth(__ GetContext(), depth);
Node* module =
__ LoadContextElement(module_context, Context::EXTENSION_INDEX);
Label if_export(assembler), if_import(assembler), end(assembler);
__ Branch(__ IntPtrGreaterThan(cell_index, __ IntPtrConstant(0)), &if_export,
&if_import);
__ Bind(&if_export);
{
Node* regular_exports =
__ LoadObjectField(module, Module::kRegularExportsOffset);
// The actual array index is (cell_index - 1).
Node* export_index = __ IntPtrSub(cell_index, __ IntPtrConstant(1));
Node* cell = __ LoadFixedArrayElement(regular_exports, export_index);
__ StoreObjectField(cell, Cell::kValueOffset, value);
__ Goto(&end);
}
__ Bind(&if_import);
{
// Not supported (probably never).
__ Abort(kUnsupportedModuleOperation);
__ Goto(&end);
}
__ Bind(&end);
__ Dispatch();
}
// PushContext <context>
//
// Saves the current context in <context>, and pushes the accumulator as the
......
......@@ -332,7 +332,15 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.CreateArrayLiteral(factory->NewFixedArray(2), 0, 0)
.CreateObjectLiteral(factory->NewFixedArray(2), 0, 0, reg);
// Emit generator operations
// Emit load and store operations for module variables.
builder.LoadModuleVariable(-1, 42)
.LoadModuleVariable(0, 42)
.LoadModuleVariable(1, 42)
.StoreModuleVariable(-1, 42)
.StoreModuleVariable(0, 42)
.StoreModuleVariable(1, 42);
// Emit generator operations.
builder.SuspendGenerator(reg)
.ResumeGenerator(reg);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment