Commit 21463f73 authored by neis's avatar neis Committed by Commit bot

[modules] Maintain array of cells for imports and local exports.

This makes use of the newly introduced cell indices to speed up variable
accesses. Imports and local exports are now directly stored in (separate)
arrays. In the future, we may merge the two arrays into a single one, or
even into the module context.

This CL also replaces the LoadImport and LoadExport runtime functions with
a single LoadVariable taking a variable index as argument (rather than a
name).

BUG=v8:1569

Review-Url: https://codereview.chromium.org/2465283004
Cr-Commit-Position: refs/heads/master@{#40808}
parent 17318a41
...@@ -212,6 +212,13 @@ void ModuleDescriptor::MakeIndirectExportsExplicit(Zone* zone) { ...@@ -212,6 +212,13 @@ void ModuleDescriptor::MakeIndirectExportsExplicit(Zone* zone) {
} }
} }
ModuleDescriptor::CellIndexKind ModuleDescriptor::GetCellIndexKind(
int cell_index) {
if (cell_index > 0) return kExport;
if (cell_index < 0) return kImport;
return kInvalid;
}
void ModuleDescriptor::AssignCellIndices() { void ModuleDescriptor::AssignCellIndices() {
int export_index = 1; int export_index = 1;
for (auto it = regular_exports_.begin(); it != regular_exports_.end();) { for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
......
...@@ -86,10 +86,12 @@ class ModuleDescriptor : public ZoneObject { ...@@ -86,10 +86,12 @@ class ModuleDescriptor : public ZoneObject {
int module_request; int module_request;
// Import/export entries that are associated with a MODULE-allocated // Import/export entries that are associated with a MODULE-allocated
// variable use the cell_index value to encode the location of their cell. // variable (i.e. regular_imports and regular_exports after Validate) use
// Negative values are used for imports and positive values for exports. // the cell_index value to encode the location of their cell. During
// For entries that are not associated with a MODULE-allocated variable, // variable allocation, this will be be copied into the variable's index
// cell_index is 0. // field.
// Entries that are not associated with a MODULE-allocated variable have
// GetCellIndexKind(cell_index) == kInvalid.
int cell_index; int cell_index;
// TODO(neis): Remove local_name component? // TODO(neis): Remove local_name component?
...@@ -109,6 +111,9 @@ class ModuleDescriptor : public ZoneObject { ...@@ -109,6 +111,9 @@ class ModuleDescriptor : public ZoneObject {
Handle<ModuleInfoEntry> entry); Handle<ModuleInfoEntry> entry);
}; };
enum CellIndexKind { kInvalid, kExport, kImport };
static CellIndexKind GetCellIndexKind(int cell_index);
// Module requests. // Module requests.
const ZoneMap<const AstRawString*, int>& module_requests() const { const ZoneMap<const AstRawString*, int>& module_requests() const {
return module_requests_; return module_requests_;
......
...@@ -794,29 +794,14 @@ void ScopeIterator::CopyModuleVarsToScopeObject(Handle<ScopeInfo> scope_info, ...@@ -794,29 +794,14 @@ void ScopeIterator::CopyModuleVarsToScopeObject(Handle<ScopeInfo> scope_info,
->value(); ->value();
for (int i = 0; i < module_variable_count; ++i) { for (int i = 0; i < module_variable_count; ++i) {
Handle<String> local_name; Handle<String> local_name;
bool is_export; Handle<Object> value;
{ {
String* name; String* name;
int index; int index;
scope_info->ModuleVariable(i, &name, &index); scope_info->ModuleVariable(i, &name, &index);
CHECK(!ScopeInfo::VariableIsSynthetic(name)); CHECK(!ScopeInfo::VariableIsSynthetic(name));
local_name = handle(name, isolate); local_name = handle(name, isolate);
DCHECK_NE(index, 0); value = Module::LoadVariable(handle(context->module(), isolate), index);
is_export = index > 0;
}
Handle<Object> value;
if (is_export) {
value =
Module::LoadExport(handle(context->module(), isolate), local_name);
} else {
Handle<ModuleInfo> module_info(scope_info->ModuleDescriptorInfo(),
isolate);
Handle<ModuleInfoEntry> entry =
ModuleInfo::LookupRegularImport(module_info, local_name);
Handle<String> import_name(String::cast(entry->import_name()), isolate);
value = Module::LoadImport(handle(context->module(), isolate),
import_name, entry->module_request());
} }
// Reflect variables under TDZ as undefined in scope object. // Reflect variables under TDZ as undefined in scope object.
......
...@@ -1817,6 +1817,10 @@ Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) { ...@@ -1817,6 +1817,10 @@ Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) {
isolate()); isolate());
Handle<ObjectHashTable> exports = Handle<ObjectHashTable> exports =
ObjectHashTable::New(isolate(), module_info->RegularExportCount()); ObjectHashTable::New(isolate(), module_info->RegularExportCount());
Handle<FixedArray> regular_exports =
NewFixedArray(module_info->RegularExportCount());
Handle<FixedArray> regular_imports =
NewFixedArray(module_info->regular_imports()->length());
int requested_modules_length = module_info->module_requests()->length(); int requested_modules_length = module_info->module_requests()->length();
Handle<FixedArray> requested_modules = Handle<FixedArray> requested_modules =
requested_modules_length > 0 ? NewFixedArray(requested_modules_length) requested_modules_length > 0 ? NewFixedArray(requested_modules_length)
...@@ -1825,6 +1829,8 @@ Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) { ...@@ -1825,6 +1829,8 @@ Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) {
Handle<Module> module = Handle<Module>::cast(NewStruct(MODULE_TYPE)); Handle<Module> module = Handle<Module>::cast(NewStruct(MODULE_TYPE));
module->set_code(*code); module->set_code(*code);
module->set_exports(*exports); module->set_exports(*exports);
module->set_regular_exports(*regular_exports);
module->set_regular_imports(*regular_imports);
module->set_hash(isolate()->GenerateIdentityHash(Smi::kMaxValue)); module->set_hash(isolate()->GenerateIdentityHash(Smi::kMaxValue));
module->set_module_namespace(isolate()->heap()->undefined_value()); module->set_module_namespace(isolate()->heap()->undefined_value());
module->set_requested_modules(*requested_modules); module->set_requested_modules(*requested_modules);
......
...@@ -1865,26 +1865,11 @@ void BytecodeGenerator::BuildVariableLoad(Variable* variable, ...@@ -1865,26 +1865,11 @@ void BytecodeGenerator::BuildVariableLoad(Variable* variable,
break; break;
} }
case VariableLocation::MODULE: { case VariableLocation::MODULE: {
ModuleDescriptor* descriptor = scope()->GetModuleScope()->module(); Register index = register_allocator()->NewRegister();
if (variable->IsExport()) { builder()
auto it = descriptor->regular_exports().find(variable->raw_name()); ->LoadLiteral(Smi::FromInt(variable->index()))
DCHECK(it != descriptor->regular_exports().end()); .StoreAccumulatorInRegister(index)
Register export_name = register_allocator()->NewRegister(); .CallRuntime(Runtime::kLoadModuleVariable, index);
builder()
->LoadLiteral(it->second->export_name->string())
.StoreAccumulatorInRegister(export_name)
.CallRuntime(Runtime::kLoadModuleExport, export_name);
} else {
auto it = descriptor->regular_imports().find(variable->raw_name());
DCHECK(it != descriptor->regular_imports().end());
RegisterList args = register_allocator()->NewRegisterList(2);
builder()
->LoadLiteral(it->second->import_name->string())
.StoreAccumulatorInRegister(args[0])
.LoadLiteral(Smi::FromInt(it->second->module_request))
.StoreAccumulatorInRegister(args[1])
.CallRuntime(Runtime::kLoadModuleImport, args);
}
if (hole_check_mode == HoleCheckMode::kRequired) { if (hole_check_mode == HoleCheckMode::kRequired) {
BuildThrowIfHole(variable->name()); BuildThrowIfHole(variable->name());
} }
...@@ -2052,23 +2037,17 @@ void BytecodeGenerator::BuildVariableAssignment(Variable* variable, ...@@ -2052,23 +2037,17 @@ void BytecodeGenerator::BuildVariableAssignment(Variable* variable,
// assignments for them. // assignments for them.
DCHECK(variable->IsExport()); DCHECK(variable->IsExport());
ModuleDescriptor* mod = scope()->GetModuleScope()->module();
// There may be several export names for this local name, but it doesn't
// matter which one we pick, as they all map to the same cell.
auto it = mod->regular_exports().find(variable->raw_name());
DCHECK(it != mod->regular_exports().end());
RegisterList args = register_allocator()->NewRegisterList(2); RegisterList args = register_allocator()->NewRegisterList(2);
builder() builder()
->StoreAccumulatorInRegister(args[1]) ->StoreAccumulatorInRegister(args[1])
.LoadLiteral(it->second->export_name->string()) .LoadLiteral(Smi::FromInt(variable->index()))
.StoreAccumulatorInRegister(args[0]); .StoreAccumulatorInRegister(args[0]);
if (hole_check_mode == HoleCheckMode::kRequired) { if (hole_check_mode == HoleCheckMode::kRequired) {
builder()->CallRuntime(Runtime::kLoadModuleExport, args[0]); builder()->CallRuntime(Runtime::kLoadModuleVariable, args[0]);
BuildHoleCheckForVariableAssignment(variable, op); BuildHoleCheckForVariableAssignment(variable, op);
} }
builder() builder()
->CallRuntime(Runtime::kStoreModuleExport, args) ->CallRuntime(Runtime::kStoreModuleVariable, args)
.LoadAccumulatorWithRegister(args[1]); .LoadAccumulatorWithRegister(args[1]);
break; break;
} }
......
...@@ -5781,6 +5781,8 @@ ACCESSORS(JSFixedArrayIterator, initial_next, JSFunction, kNextOffset) ...@@ -5781,6 +5781,8 @@ ACCESSORS(JSFixedArrayIterator, initial_next, JSFunction, kNextOffset)
ACCESSORS(Module, code, Object, kCodeOffset) ACCESSORS(Module, code, Object, kCodeOffset)
ACCESSORS(Module, exports, ObjectHashTable, kExportsOffset) ACCESSORS(Module, exports, ObjectHashTable, kExportsOffset)
ACCESSORS(Module, regular_exports, FixedArray, kRegularExportsOffset)
ACCESSORS(Module, regular_imports, FixedArray, kRegularImportsOffset)
ACCESSORS(Module, module_namespace, HeapObject, kModuleNamespaceOffset) ACCESSORS(Module, module_namespace, HeapObject, kModuleNamespaceOffset)
ACCESSORS(Module, requested_modules, FixedArray, kRequestedModulesOffset) ACCESSORS(Module, requested_modules, FixedArray, kRequestedModulesOffset)
SMI_ACCESSORS(Module, hash, kHashOffset) SMI_ACCESSORS(Module, hash, kHashOffset)
......
...@@ -19826,6 +19826,22 @@ class Module::ResolveSet ...@@ -19826,6 +19826,22 @@ class Module::ResolveSet
Zone* zone_; Zone* zone_;
}; };
namespace {
int ExportIndex(int cell_index) {
DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
ModuleDescriptor::kExport);
return cell_index - 1;
}
int ImportIndex(int cell_index) {
DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
ModuleDescriptor::kImport);
return -cell_index - 1;
}
} // anonymous namespace
void Module::CreateIndirectExport(Handle<Module> module, Handle<String> name, void Module::CreateIndirectExport(Handle<Module> module, Handle<String> name,
Handle<ModuleInfoEntry> entry) { Handle<ModuleInfoEntry> entry) {
Isolate* isolate = module->GetIsolate(); Isolate* isolate = module->GetIsolate();
...@@ -19835,11 +19851,15 @@ void Module::CreateIndirectExport(Handle<Module> module, Handle<String> name, ...@@ -19835,11 +19851,15 @@ void Module::CreateIndirectExport(Handle<Module> module, Handle<String> name,
module->set_exports(*exports); module->set_exports(*exports);
} }
void Module::CreateExport(Handle<Module> module, Handle<FixedArray> names) { void Module::CreateExport(Handle<Module> module, int cell_index,
Handle<FixedArray> names) {
DCHECK_LT(0, names->length()); DCHECK_LT(0, names->length());
Isolate* isolate = module->GetIsolate(); Isolate* isolate = module->GetIsolate();
Handle<Cell> cell = Handle<Cell> cell =
isolate->factory()->NewCell(isolate->factory()->undefined_value()); isolate->factory()->NewCell(isolate->factory()->undefined_value());
module->regular_exports()->set(ExportIndex(cell_index), *cell);
Handle<ObjectHashTable> exports(module->exports(), isolate); Handle<ObjectHashTable> exports(module->exports(), isolate);
for (int i = 0, n = names->length(); i < n; ++i) { for (int i = 0, n = names->length(); i < n; ++i) {
Handle<String> name(String::cast(names->get(i)), isolate); Handle<String> name(String::cast(names->get(i)), isolate);
...@@ -19849,24 +19869,33 @@ void Module::CreateExport(Handle<Module> module, Handle<FixedArray> names) { ...@@ -19849,24 +19869,33 @@ void Module::CreateExport(Handle<Module> module, Handle<FixedArray> names) {
module->set_exports(*exports); module->set_exports(*exports);
} }
void Module::StoreExport(Handle<Module> module, Handle<String> name, Handle<Object> Module::LoadVariable(Handle<Module> module, int cell_index) {
Handle<Object> value) {
Handle<Cell> cell(Cell::cast(module->exports()->Lookup(name)));
cell->set_value(*value);
}
Handle<Object> Module::LoadExport(Handle<Module> module, Handle<String> name) {
Isolate* isolate = module->GetIsolate(); Isolate* isolate = module->GetIsolate();
Handle<Object> object(module->exports()->Lookup(name), isolate); Handle<Object> object;
switch (ModuleDescriptor::GetCellIndexKind(cell_index)) {
case ModuleDescriptor::kImport:
object = handle(module->regular_imports()->get(ImportIndex(cell_index)),
isolate);
break;
case ModuleDescriptor::kExport:
object = handle(module->regular_exports()->get(ExportIndex(cell_index)),
isolate);
break;
case ModuleDescriptor::kInvalid:
UNREACHABLE();
break;
}
return handle(Handle<Cell>::cast(object)->value(), isolate); return handle(Handle<Cell>::cast(object)->value(), isolate);
} }
Handle<Object> Module::LoadImport(Handle<Module> module, Handle<String> name, void Module::StoreVariable(Handle<Module> module, int cell_index,
int module_request) { Handle<Object> value) {
Isolate* isolate = module->GetIsolate(); Isolate* isolate = module->GetIsolate();
Handle<Module> requested_module( DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
Module::cast(module->requested_modules()->get(module_request)), isolate); ModuleDescriptor::kExport);
return Module::LoadExport(requested_module, name); Handle<Object> object(module->regular_exports()->get(ExportIndex(cell_index)),
isolate);
Handle<Cell>::cast(object)->set_value(*value);
} }
MaybeHandle<Cell> Module::ResolveImport(Handle<Module> module, MaybeHandle<Cell> Module::ResolveImport(Handle<Module> module,
...@@ -20021,10 +20050,12 @@ bool Module::Instantiate(Handle<Module> module, v8::Local<v8::Context> context, ...@@ -20021,10 +20050,12 @@ bool Module::Instantiate(Handle<Module> module, v8::Local<v8::Context> context,
isolate); isolate);
// Set up local exports. // Set up local exports.
// TODO(neis): Create regular_exports array here instead of in factory method?
for (int i = 0, n = module_info->RegularExportCount(); i < n; ++i) { for (int i = 0, n = module_info->RegularExportCount(); i < n; ++i) {
int cell_index = module_info->RegularExportCellIndex(i);
Handle<FixedArray> export_names(module_info->RegularExportExportNames(i), Handle<FixedArray> export_names(module_info->RegularExportExportNames(i),
isolate); isolate);
CreateExport(module, export_names); CreateExport(module, cell_index, export_names);
} }
// Partially set up indirect exports. // Partially set up indirect exports.
...@@ -20076,11 +20107,13 @@ bool Module::Instantiate(Handle<Module> module, v8::Local<v8::Context> context, ...@@ -20076,11 +20107,13 @@ bool Module::Instantiate(Handle<Module> module, v8::Local<v8::Context> context,
isolate); isolate);
MessageLocation loc(script, entry->beg_pos(), entry->end_pos()); MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
ResolveSet resolve_set(&zone); ResolveSet resolve_set(&zone);
if (ResolveImport(module, name, entry->module_request(), loc, true, Handle<Cell> cell;
&resolve_set) if (!ResolveImport(module, name, entry->module_request(), loc, true,
.is_null()) { &resolve_set)
.ToHandle(&cell)) {
return false; return false;
} }
module->regular_imports()->set(ImportIndex(entry->cell_index()), *cell);
} }
// Resolve indirect exports. // Resolve indirect exports.
......
...@@ -8179,7 +8179,15 @@ class Module : public Struct { ...@@ -8179,7 +8179,15 @@ class Module : public Struct {
// Module::ModuleVerify() for the precise invariant. // Module::ModuleVerify() for the precise invariant.
DECL_ACCESSORS(code, Object) DECL_ACCESSORS(code, Object)
// The export table. // Arrays of cells corresponding to regular exports and regular imports.
// A cell's position in the array is determined by the cell index of the
// associated module entry (which coincides with the variable index of the
// associated variable).
DECL_ACCESSORS(regular_exports, FixedArray)
DECL_ACCESSORS(regular_imports, FixedArray)
// The complete export table, mapping an export name to its cell.
// TODO(neis): We may want to remove the regular exports from the table.
DECL_ACCESSORS(exports, ObjectHashTable) DECL_ACCESSORS(exports, ObjectHashTable)
// Hash for this object (a random non-zero Smi). // Hash for this object (a random non-zero Smi).
...@@ -8210,12 +8218,9 @@ class Module : public Struct { ...@@ -8210,12 +8218,9 @@ class Module : public Struct {
// Implementation of spec operation ModuleEvaluation. // Implementation of spec operation ModuleEvaluation.
static MUST_USE_RESULT MaybeHandle<Object> Evaluate(Handle<Module> module); static MUST_USE_RESULT MaybeHandle<Object> Evaluate(Handle<Module> module);
static Handle<Object> LoadExport(Handle<Module> module, Handle<String> name); static Handle<Object> LoadVariable(Handle<Module> module, int cell_index);
static void StoreExport(Handle<Module> module, Handle<String> name, static void StoreVariable(Handle<Module> module, int cell_index,
Handle<Object> value); Handle<Object> value);
static Handle<Object> LoadImport(Handle<Module> module, Handle<String> name,
int module_request);
// Get the namespace object for [module_request] of [module]. If it doesn't // Get the namespace object for [module_request] of [module]. If it doesn't
// exist yet, it is created. // exist yet, it is created.
...@@ -8224,7 +8229,9 @@ class Module : public Struct { ...@@ -8224,7 +8229,9 @@ class Module : public Struct {
static const int kCodeOffset = HeapObject::kHeaderSize; static const int kCodeOffset = HeapObject::kHeaderSize;
static const int kExportsOffset = kCodeOffset + kPointerSize; static const int kExportsOffset = kCodeOffset + kPointerSize;
static const int kHashOffset = kExportsOffset + kPointerSize; static const int kRegularExportsOffset = kExportsOffset + kPointerSize;
static const int kRegularImportsOffset = kRegularExportsOffset + kPointerSize;
static const int kHashOffset = kRegularImportsOffset + kPointerSize;
static const int kModuleNamespaceOffset = kHashOffset + kPointerSize; static const int kModuleNamespaceOffset = kHashOffset + kPointerSize;
static const int kRequestedModulesOffset = static const int kRequestedModulesOffset =
kModuleNamespaceOffset + kPointerSize; kModuleNamespaceOffset + kPointerSize;
...@@ -8233,7 +8240,8 @@ class Module : public Struct { ...@@ -8233,7 +8240,8 @@ class Module : public Struct {
private: private:
enum { kEvaluatedBit }; enum { kEvaluatedBit };
static void CreateExport(Handle<Module> module, Handle<FixedArray> names); static void CreateExport(Handle<Module> module, int cell_index,
Handle<FixedArray> names);
static void CreateIndirectExport(Handle<Module> module, Handle<String> name, static void CreateIndirectExport(Handle<Module> module, Handle<String> name,
Handle<ModuleInfoEntry> entry); Handle<ModuleInfoEntry> entry);
......
...@@ -17,30 +17,21 @@ RUNTIME_FUNCTION(Runtime_GetModuleNamespace) { ...@@ -17,30 +17,21 @@ RUNTIME_FUNCTION(Runtime_GetModuleNamespace) {
return *Module::GetModuleNamespace(module, module_request); return *Module::GetModuleNamespace(module, module_request);
} }
RUNTIME_FUNCTION(Runtime_LoadModuleExport) { RUNTIME_FUNCTION(Runtime_LoadModuleVariable) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0); CONVERT_SMI_ARG_CHECKED(index, 0);
Handle<Module> module(isolate->context()->module()); Handle<Module> module(isolate->context()->module());
return *Module::LoadExport(module, name); return *Module::LoadVariable(module, index);
} }
RUNTIME_FUNCTION(Runtime_LoadModuleImport) { RUNTIME_FUNCTION(Runtime_StoreModuleVariable) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 2); DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0); CONVERT_SMI_ARG_CHECKED(index, 0);
CONVERT_SMI_ARG_CHECKED(module_request, 1);
Handle<Module> module(isolate->context()->module());
return *Module::LoadImport(module, name, module_request);
}
RUNTIME_FUNCTION(Runtime_StoreModuleExport) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
Handle<Module> module(isolate->context()->module()); Handle<Module> module(isolate->context()->module());
Module::StoreExport(module, name, value); Module::StoreVariable(module, index, value);
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
} }
......
...@@ -359,9 +359,8 @@ namespace internal { ...@@ -359,9 +359,8 @@ namespace internal {
#define FOR_EACH_INTRINSIC_MODULE(F) \ #define FOR_EACH_INTRINSIC_MODULE(F) \
F(GetModuleNamespace, 1, 1) \ F(GetModuleNamespace, 1, 1) \
F(LoadModuleExport, 1, 1) \ F(LoadModuleVariable, 1, 1) \
F(LoadModuleImport, 2, 1) \ F(StoreModuleVariable, 2, 1)
F(StoreModuleExport, 2, 1)
#define FOR_EACH_INTRINSIC_NUMBERS(F) \ #define FOR_EACH_INTRINSIC_NUMBERS(F) \
F(IsValidSmi, 1, 1) \ F(IsValidSmi, 1, 1) \
......
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