[modules] Turbofan inlining support for namespace accesses
Bug: v8:1569 Change-Id: I84317ce1ac145b69caa26452721f71aac88f219e Reviewed-on: https://chromium-review.googlesource.com/636699 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/master@{#47839}
This commit is contained in:
parent
b6bf9ad92d
commit
8d7379c066
@ -96,6 +96,13 @@ PropertyAccessInfo PropertyAccessInfo::AccessorConstant(
|
||||
return PropertyAccessInfo(kAccessorConstant, holder, constant, receiver_maps);
|
||||
}
|
||||
|
||||
// static
|
||||
PropertyAccessInfo PropertyAccessInfo::ModuleExport(
|
||||
MapHandles const& receiver_maps, Handle<Cell> cell) {
|
||||
return PropertyAccessInfo(kModuleExport, MaybeHandle<JSObject>(), cell,
|
||||
receiver_maps);
|
||||
}
|
||||
|
||||
PropertyAccessInfo::PropertyAccessInfo()
|
||||
: kind_(kInvalid),
|
||||
field_representation_(MachineRepresentation::kNone),
|
||||
@ -209,6 +216,9 @@ bool PropertyAccessInfo::Merge(PropertyAccessInfo const* that,
|
||||
that->receiver_maps_.end());
|
||||
return true;
|
||||
}
|
||||
case kModuleExport: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
@ -400,6 +410,26 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
|
||||
return true;
|
||||
} else {
|
||||
DCHECK_EQ(kAccessor, details.kind());
|
||||
if (map->instance_type() == JS_MODULE_NAMESPACE_TYPE) {
|
||||
DCHECK(map->is_prototype_map());
|
||||
Handle<PrototypeInfo> proto_info =
|
||||
Map::GetOrCreatePrototypeInfo(map, isolate());
|
||||
DCHECK(proto_info->weak_cell()->IsWeakCell());
|
||||
Object* obj = WeakCell::cast(proto_info->weak_cell())->value();
|
||||
DCHECK(obj->IsJSModuleNamespace());
|
||||
ObjectHashTable* exports =
|
||||
JSModuleNamespace::cast(obj)->module()->exports();
|
||||
Object* value =
|
||||
exports->Lookup(isolate(), name, Smi::ToInt(name->GetHash()));
|
||||
DCHECK(value->IsCell());
|
||||
if (Cell::cast(value)->value()->IsTheHole(isolate())) {
|
||||
// This module has not been fully initialized yet.
|
||||
return false;
|
||||
}
|
||||
*access_info = PropertyAccessInfo::ModuleExport(
|
||||
MapHandles{receiver_map}, handle(Cell::cast(value), isolate()));
|
||||
return true;
|
||||
}
|
||||
Handle<Object> accessors(descriptors->GetValue(number), isolate());
|
||||
if (!accessors->IsAccessorPair()) return false;
|
||||
Handle<Object> accessor(
|
||||
|
@ -63,7 +63,8 @@ class PropertyAccessInfo final {
|
||||
kDataConstant,
|
||||
kDataField,
|
||||
kDataConstantField,
|
||||
kAccessorConstant
|
||||
kAccessorConstant,
|
||||
kModuleExport
|
||||
};
|
||||
|
||||
static PropertyAccessInfo NotFound(MapHandles const& receiver_maps,
|
||||
@ -80,6 +81,8 @@ class PropertyAccessInfo final {
|
||||
static PropertyAccessInfo AccessorConstant(MapHandles const& receiver_maps,
|
||||
Handle<Object> constant,
|
||||
MaybeHandle<JSObject> holder);
|
||||
static PropertyAccessInfo ModuleExport(MapHandles const& receiver_maps,
|
||||
Handle<Cell> cell);
|
||||
|
||||
PropertyAccessInfo();
|
||||
|
||||
@ -93,6 +96,7 @@ class PropertyAccessInfo final {
|
||||
// is done.
|
||||
bool IsDataConstantField() const { return kind() == kDataConstantField; }
|
||||
bool IsAccessorConstant() const { return kind() == kAccessorConstant; }
|
||||
bool IsModuleExport() const { return kind() == kModuleExport; }
|
||||
|
||||
bool HasTransitionMap() const { return !transition_map().is_null(); }
|
||||
|
||||
@ -107,6 +111,10 @@ class PropertyAccessInfo final {
|
||||
}
|
||||
MaybeHandle<Map> field_map() const { return field_map_; }
|
||||
MapHandles const& receiver_maps() const { return receiver_maps_; }
|
||||
Handle<Cell> export_cell() const {
|
||||
DCHECK_EQ(kModuleExport, kind_);
|
||||
return Handle<Cell>::cast(constant_);
|
||||
}
|
||||
|
||||
private:
|
||||
PropertyAccessInfo(MaybeHandle<JSObject> holder,
|
||||
|
@ -1639,6 +1639,11 @@ JSNativeContextSpecialization::BuildPropertyLoad(
|
||||
} else if (access_info.IsAccessorConstant()) {
|
||||
value = InlinePropertyGetterCall(receiver, context, frame_state, &effect,
|
||||
&control, if_exceptions, access_info);
|
||||
} else if (access_info.IsModuleExport()) {
|
||||
Node* cell = jsgraph()->Constant(access_info.export_cell());
|
||||
value = effect =
|
||||
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForCellValue()),
|
||||
cell, effect, control);
|
||||
} else {
|
||||
DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
|
||||
value = access_builder.BuildLoadDataField(name, access_info, receiver,
|
||||
|
@ -840,15 +840,25 @@ Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module) {
|
||||
ns->set_module(*module);
|
||||
module->set_module_namespace(*ns);
|
||||
|
||||
// Create the properties in the namespace object.
|
||||
// Create the properties in the namespace object. Transition the object
|
||||
// to dictionary mode so that property addition is faster.
|
||||
PropertyAttributes attr = DONT_DELETE;
|
||||
JSObject::NormalizeProperties(ns, CLEAR_INOBJECT_PROPERTIES,
|
||||
static_cast<int>(names.size()),
|
||||
"JSModuleNamespace");
|
||||
for (const auto& name : names) {
|
||||
JSObject::SetAccessor(
|
||||
ns, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr))
|
||||
.Check();
|
||||
JSObject::SetNormalizedProperty(
|
||||
ns, name, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr),
|
||||
PropertyDetails(kAccessor, attr, PropertyCellType::kMutable));
|
||||
}
|
||||
JSObject::PreventExtensions(ns, THROW_ON_ERROR).ToChecked();
|
||||
|
||||
// Optimize the namespace object as a prototype, for two reasons:
|
||||
// - The object's map is guaranteed not to be shared. ICs rely on this.
|
||||
// - We can store a pointer from the map back to the namespace object.
|
||||
// Turbofan can use this for inlining the access.
|
||||
JSObject::OptimizeAsPrototype(ns);
|
||||
Map::GetOrCreatePrototypeWeakCell(ns, isolate);
|
||||
return ns;
|
||||
}
|
||||
|
||||
|
1120
test/mjsunit/harmony/modules-import-large.js
Normal file
1120
test/mjsunit/harmony/modules-import-large.js
Normal file
File diff suppressed because it is too large
Load Diff
2204
test/mjsunit/harmony/modules-skip-large1.js
Normal file
2204
test/mjsunit/harmony/modules-skip-large1.js
Normal file
File diff suppressed because it is too large
Load Diff
1104
test/mjsunit/harmony/modules-skip-large2.js
Normal file
1104
test/mjsunit/harmony/modules-skip-large2.js
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user