[compiler,modules] Introduce JS operators for module loads and stores.

With this CL, the bytecode graph builder no longer translates module
loads/stores as runtime calls but in terms of two new JS operators.  These are
lowered in typed-lowering to a sequence of LoadField's.

R=bmeurer@chromium.org
CC=adamk@chromium.org
BUG=v8:1569

Review-Url: https://codereview.chromium.org/2489863003
Cr-Commit-Position: refs/heads/master@{#40881}
This commit is contained in:
neis 2016-11-10 02:21:04 -08:00 committed by Commit bot
parent ade3bc6da9
commit a9f593ef6b
11 changed files with 177 additions and 12 deletions

View File

@ -434,6 +434,27 @@ FieldAccess AccessBuilder::ForMapPrototype() {
return access;
}
// static
FieldAccess AccessBuilder::ForModuleRegularExports() {
FieldAccess access = {kTaggedBase,
Module::kRegularExportsOffset,
Handle<Name>(),
Type::OtherInternal(),
MachineType::TaggedPointer(),
kPointerWriteBarrier};
return access;
}
// static
FieldAccess AccessBuilder::ForModuleRegularImports() {
FieldAccess access = {kTaggedBase,
Module::kRegularImportsOffset,
Handle<Name>(),
Type::OtherInternal(),
MachineType::TaggedPointer(),
kPointerWriteBarrier};
return access;
}
// static
FieldAccess AccessBuilder::ForNameHashField() {
@ -611,6 +632,14 @@ FieldAccess AccessBuilder::ForFixedArraySlot(size_t index) {
}
// static
FieldAccess AccessBuilder::ForCellValue() {
FieldAccess access = {
kTaggedBase, Cell::kValueOffset, Handle<Name>(),
Type::Any(), MachineType::AnyTagged(), kFullWriteBarrier};
return access;
}
// static
FieldAccess AccessBuilder::ForContextSlot(size_t index) {
int offset = Context::kHeaderSize + static_cast<int>(index) * kPointerSize;

View File

@ -146,6 +146,12 @@ class V8_EXPORT_PRIVATE AccessBuilder final
// Provides access to Map::prototype() field.
static FieldAccess ForMapPrototype();
// Provides access to Module::regular_exports() field.
static FieldAccess ForModuleRegularExports();
// Provides access to Module::regular_imports() field.
static FieldAccess ForModuleRegularImports();
// Provides access to Name::hash_field() field.
static FieldAccess ForNameHashField();
@ -194,6 +200,9 @@ class V8_EXPORT_PRIVATE AccessBuilder final
// Provides access to JSValue::value() field.
static FieldAccess ForValue();
// Provides access to Cell::value() field.
static FieldAccess ForCellValue();
// Provides access to arguments object fields.
static FieldAccess ForArgumentsLength();
static FieldAccess ForArgumentsCallee();

View File

@ -1117,22 +1117,23 @@ void BytecodeGraphBuilder::VisitStaKeyedPropertyStrict() {
}
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);
int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
Node* module =
NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
environment()->Context());
Node* value = NewNode(javascript()->LoadModule(cell_index), module);
environment()->BindAccumulator(value);
}
void BytecodeGraphBuilder::VisitStaModuleVariable() {
// TODO(neis): Don't call the runtime.
PrepareEagerCheckpoint();
Node* index = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
Node* module =
NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
environment()->Context());
Node* value = environment()->LookupAccumulator();
const Operator* op = javascript()->CallRuntime(Runtime::kStoreModuleVariable);
Node* store = NewNode(op, index, value);
environment()->RecordAfterState(store, Environment::kAttachFrameState);
NewNode(javascript()->StoreModule(cell_index), module, value);
}
void BytecodeGraphBuilder::VisitPushContext() {

View File

@ -625,6 +625,14 @@ void JSGenericLowering::LowerJSStoreMessage(Node* node) {
NodeProperties::ChangeOp(node, machine()->Store(representation));
}
void JSGenericLowering::LowerJSLoadModule(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
}
void JSGenericLowering::LowerJSStoreModule(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
}
void JSGenericLowering::LowerJSGeneratorStore(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
}

View File

@ -765,6 +765,23 @@ const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
access); // parameter
}
const Operator* JSOperatorBuilder::LoadModule(int32_t cell_index) {
return new (zone()) Operator1<int32_t>( // --
IrOpcode::kJSLoadModule, // opcode
Operator::kNoWrite | Operator::kNoThrow, // flags
"JSLoadModule", // name
1, 1, 1, 1, 1, 0, // counts
cell_index); // parameter
}
const Operator* JSOperatorBuilder::StoreModule(int32_t cell_index) {
return new (zone()) Operator1<int32_t>( // --
IrOpcode::kJSStoreModule, // opcode
Operator::kNoRead | Operator::kNoThrow, // flags
"JSStoreModule", // name
2, 1, 1, 0, 1, 0, // counts
cell_index); // parameter
}
const Operator* JSOperatorBuilder::CreateArguments(CreateArgumentsType type) {
return new (zone()) Operator1<CreateArgumentsType>( // --

View File

@ -502,6 +502,9 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* LoadContext(size_t depth, size_t index, bool immutable);
const Operator* StoreContext(size_t depth, size_t index);
const Operator* LoadModule(int32_t cell_index);
const Operator* StoreModule(int32_t cell_index);
const Operator* TypeOf();
const Operator* InstanceOf();

View File

@ -4,6 +4,7 @@
#include "src/compiler/js-typed-lowering.h"
#include "src/ast/modules.h"
#include "src/builtins/builtins-utils.h"
#include "src/code-factory.h"
#include "src/compilation-dependencies.h"
@ -1489,6 +1490,81 @@ Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
return Changed(node);
}
Reduction JSTypedLowering::ReduceJSLoadModule(Node* node) {
DCHECK_EQ(IrOpcode::kJSLoadModule, node->opcode());
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
int32_t cell_index = OpParameter<int32_t>(node);
Node* module = NodeProperties::GetValueInput(node, 0);
Node* array;
int index;
if (ModuleDescriptor::GetCellIndexKind(cell_index) ==
ModuleDescriptor::kExport) {
array = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForModuleRegularExports()),
module, effect, control);
index = cell_index - 1;
} else {
DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
ModuleDescriptor::kImport);
array = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForModuleRegularImports()),
module, effect, control);
index = -cell_index - 1;
}
Node* cell = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForFixedArraySlot(index)), array,
effect, control);
Node* value = effect =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForCellValue()),
cell, effect, control);
ReplaceWithValue(node, value, effect, control);
return Changed(value);
}
Reduction JSTypedLowering::ReduceJSStoreModule(Node* node) {
DCHECK_EQ(IrOpcode::kJSStoreModule, node->opcode());
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
int32_t cell_index = OpParameter<int32_t>(node);
Node* module = NodeProperties::GetValueInput(node, 0);
Node* value = NodeProperties::GetValueInput(node, 1);
Node* array;
int index;
if (ModuleDescriptor::GetCellIndexKind(cell_index) ==
ModuleDescriptor::kExport) {
array = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForModuleRegularExports()),
module, effect, control);
index = cell_index - 1;
} else {
DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
ModuleDescriptor::kImport);
array = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForModuleRegularImports()),
module, effect, control);
index = -cell_index - 1;
}
Node* cell = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForFixedArraySlot(index)), array,
effect, control);
effect =
graph()->NewNode(simplified()->StoreField(AccessBuilder::ForCellValue()),
cell, value, effect, control);
ReplaceWithValue(node, effect, effect, control);
return Changed(value);
}
Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode());
ConvertReceiverMode mode = ConvertReceiverModeOf(node->op());
@ -2126,6 +2202,10 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return ReduceJSLoadContext(node);
case IrOpcode::kJSStoreContext:
return ReduceJSStoreContext(node);
case IrOpcode::kJSLoadModule:
return ReduceJSLoadModule(node);
case IrOpcode::kJSStoreModule:
return ReduceJSStoreModule(node);
case IrOpcode::kJSConvertReceiver:
return ReduceJSConvertReceiver(node);
case IrOpcode::kJSCallConstruct:

View File

@ -55,6 +55,8 @@ class V8_EXPORT_PRIVATE JSTypedLowering final
Reduction ReduceJSInstanceOf(Node* node);
Reduction ReduceJSLoadContext(Node* node);
Reduction ReduceJSStoreContext(Node* node);
Reduction ReduceJSLoadModule(Node* node);
Reduction ReduceJSStoreModule(Node* node);
Reduction ReduceJSEqualTypeOf(Node* node, bool invert);
Reduction ReduceJSEqual(Node* node, bool invert);
Reduction ReduceJSStrictEqual(Node* node, bool invert);

View File

@ -158,6 +158,8 @@
V(JSForInPrepare) \
V(JSLoadMessage) \
V(JSStoreMessage) \
V(JSLoadModule) \
V(JSStoreModule) \
V(JSGeneratorStore) \
V(JSGeneratorRestoreContinuation) \
V(JSGeneratorRestoreRegister) \

View File

@ -1488,6 +1488,13 @@ Type* Typer::Visitor::TypeJSStoreMessage(Node* node) {
return nullptr;
}
Type* Typer::Visitor::TypeJSLoadModule(Node* node) { return Type::Any(); }
Type* Typer::Visitor::TypeJSStoreModule(Node* node) {
UNREACHABLE();
return nullptr;
}
Type* Typer::Visitor::TypeJSGeneratorStore(Node* node) {
UNREACHABLE();
return nullptr;

View File

@ -660,6 +660,13 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kJSStoreMessage:
break;
case IrOpcode::kJSLoadModule:
CheckTypeIs(node, Type::Any());
break;
case IrOpcode::kJSStoreModule:
CheckNotTyped(node);
break;
case IrOpcode::kJSGeneratorStore:
CheckNotTyped(node);
break;