Commit 967f24b4 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Serialize map for Object.create lowering.

The refactoring also requires serialization of Map::prototype.

Bug: v8:7790
Change-Id: I240254d0a1f1beaf03b13d20cc7cc02c96f08069
Reviewed-on: https://chromium-review.googlesource.com/1219328
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55853}
parent 750ce1e7
......@@ -1344,6 +1344,24 @@ Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) {
return NoChange();
}
namespace {
base::Optional<MapRef> GetObjectCreateMap(JSHeapBroker* broker,
HeapObjectRef prototype) {
MapRef standard_map =
broker->native_context().object_function().initial_map();
if (prototype.equals(standard_map.prototype())) {
return standard_map;
}
if (prototype.oddball_type() == OddballType::kNull) {
return broker->native_context().slow_object_with_null_prototype_map();
}
if (prototype.IsJSObject()) {
return prototype.AsJSObject().GetObjectCreateMap();
}
return base::Optional<MapRef>();
}
} // namespace
Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateObject, node->opcode());
Node* effect = NodeProperties::GetEffectInput(node);
......@@ -1353,7 +1371,8 @@ Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
if (!prototype_type.IsHeapConstant()) return NoChange();
HeapObjectRef prototype_const = prototype_type.AsHeapConstant()->Ref();
auto maybe_instance_map = prototype_const.TryGetObjectCreateMap();
auto maybe_instance_map =
GetObjectCreateMap(js_heap_broker(), prototype_const);
if (!maybe_instance_map) return NoChange();
MapRef instance_map = maybe_instance_map.value();
......
......@@ -111,6 +111,12 @@ class JSObjectData : public HeapObjectData {
// This method is only used to assert our invariants.
bool cow_or_empty_elements_tenured() const;
void SerializeObjectCreateMap();
MapData* object_create_map() const { // Can be nullptr.
CHECK(serialized_object_create_map_);
return object_create_map_;
}
private:
void SerializeRecursive(int max_depths);
......@@ -122,8 +128,31 @@ class JSObjectData : public HeapObjectData {
bool serialized_elements_ = false;
ZoneVector<JSObjectField> inobject_fields_;
bool serialized_object_create_map_ = false;
MapData* object_create_map_ = nullptr;
};
void JSObjectData::SerializeObjectCreateMap() {
if (serialized_object_create_map_) return;
serialized_object_create_map_ = true;
Handle<JSObject> jsobject = Handle<JSObject>::cast(object());
if (jsobject->map()->is_prototype_map()) {
Handle<Object> maybe_proto_info(jsobject->map()->prototype_info(),
broker()->isolate());
if (maybe_proto_info->IsPrototypeInfo()) {
auto proto_info = Handle<PrototypeInfo>::cast(maybe_proto_info);
if (proto_info->HasObjectCreateMap()) {
DCHECK_NULL(object_create_map_);
object_create_map_ =
broker()->GetOrCreateData(proto_info->ObjectCreateMap())->AsMap();
}
}
}
}
class JSFunctionData : public JSObjectData {
public:
bool has_initial_map() const { return has_initial_map_; }
......@@ -424,6 +453,12 @@ class MapData : public HeapObjectData {
return descriptors_;
}
void SerializePrototype();
ObjectData* prototype() const {
CHECK(serialized_prototype_);
return prototype_;
}
private:
InstanceType const instance_type_;
int const instance_size_;
......@@ -436,6 +471,9 @@ class MapData : public HeapObjectData {
bool serialized_descriptors_ = false;
ZoneVector<PropertyDescriptor> descriptors_;
bool serialized_prototype_ = false;
ObjectData* prototype_ = nullptr;
};
AllocationSiteData::AllocationSiteData(JSHeapBroker* broker,
......@@ -521,9 +559,14 @@ void JSFunctionData::Serialize() {
? broker()->GetOrCreateData(function->prototype())
: nullptr;
if (initial_map_ != nullptr &&
initial_map_->instance_type() == JS_ARRAY_TYPE) {
initial_map_->SerializeElementsKindGeneralizations();
if (initial_map_ != nullptr) {
if (initial_map_->instance_type() == JS_ARRAY_TYPE) {
initial_map_->SerializeElementsKindGeneralizations();
}
// TODO(neis): This is currently only needed for native_context's
// object_function, as used by GetObjectCreateMap. If no further use sites
// show up, we should move this into NativeContextData::Serialize.
initial_map_->SerializePrototype();
}
}
......@@ -883,6 +926,15 @@ void JSObjectData::SerializeElements() {
elements_ = broker()->GetOrCreateData(elements_object)->AsFixedArrayBase();
}
void MapData::SerializePrototype() {
if (serialized_prototype_) return;
serialized_prototype_ = true;
Handle<Map> map = Handle<Map>::cast(object());
DCHECK_NULL(prototype_);
prototype_ = broker()->GetOrCreateData(map->prototype());
}
void MapData::SerializeDescriptors() {
if (serialized_descriptors_) return;
serialized_descriptors_ = true;
......@@ -1292,16 +1344,26 @@ HeapObjectType HeapObjectRef::type() const {
}
}
base::Optional<MapRef> HeapObjectRef::TryGetObjectCreateMap() const {
NativeContextRef JSHeapBroker::native_context() {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
Handle<Map> instance_map;
if (Map::TryGetObjectCreateMap(broker()->isolate(), object<HeapObject>())
.ToHandle(&instance_map)) {
return MapRef(broker(), instance_map);
} else {
return base::Optional<MapRef>();
return NativeContextRef(this, isolate()->native_context());
}
base::Optional<MapRef> JSObjectRef::GetObjectCreateMap() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
AllowHeapAllocation heap_allocation;
Handle<Map> instance_map;
if (Map::TryGetObjectCreateMap(broker()->isolate(), object<HeapObject>())
.ToHandle(&instance_map)) {
return MapRef(broker(), instance_map);
} else {
return base::Optional<MapRef>();
}
}
MapData* map_data = data()->AsJSObject()->object_create_map();
return map_data != nullptr ? MapRef(map_data) : base::Optional<MapRef>();
}
base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const {
......@@ -1639,6 +1701,7 @@ BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit)
BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit)
BIMODAL_ACCESSOR_C(Map, int, instance_size)
BIMODAL_ACCESSOR(Map, Object, prototype)
HANDLE_ACCESSOR_C(Map, bool, CanBeDeprecated)
HANDLE_ACCESSOR_C(Map, bool, CanTransition)
HANDLE_ACCESSOR_C(Map, bool, IsInobjectSlackTrackingInProgress)
......@@ -1896,6 +1959,12 @@ void JSFunctionRef::Serialize() {
data()->AsJSFunction()->Serialize();
}
void JSObjectRef::SerializeObjectCreateMap() {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsJSObject()->SerializeObjectCreateMap();
}
void MapRef::SerializeDescriptors() {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
......
......@@ -146,7 +146,6 @@ class HeapObjectRef : public ObjectRef {
HeapObjectType type() const;
MapRef map() const;
base::Optional<MapRef> TryGetObjectCreateMap() const;
bool IsSeqString() const;
bool IsExternalString() const;
};
......@@ -169,6 +168,9 @@ class JSObjectRef : public HeapObjectRef {
FixedArrayBaseRef elements() const;
void EnsureElementsTenured();
ElementsKind GetElementsKind() const;
void SerializeObjectCreateMap();
base::Optional<MapRef> GetObjectCreateMap() const;
};
class JSFunctionRef : public JSObjectRef {
......@@ -242,6 +244,7 @@ class ContextRef : public HeapObjectRef {
V(Map, set_key_value_iterator_map) \
V(Map, set_value_iterator_map) \
V(Map, sloppy_arguments_map) \
V(Map, slow_object_with_null_prototype_map) \
V(Map, strict_arguments_map) \
V(Map, string_iterator_map) \
V(ScriptContextTable, script_context_table)
......@@ -328,6 +331,7 @@ class MapRef : public HeapObjectRef {
bool IsFixedCowArrayMap() const;
ObjectRef constructor_or_backpointer() const;
ObjectRef prototype() const;
base::Optional<MapRef> AsElementsKind(ElementsKind kind) const;
......@@ -460,6 +464,8 @@ class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
Isolate* isolate() const { return isolate_; }
Zone* zone() const { return zone_; }
NativeContextRef native_context();
enum BrokerMode { kDisabled, kSerializing, kSerialized };
BrokerMode mode() const { return mode_; }
void StopSerializing() {
......
......@@ -28,6 +28,7 @@ Reduction JSHeapCopyReducer::Reduce(Node* node) {
case IrOpcode::kHeapConstant: {
ObjectRef object(broker(), HeapConstantOf(node->op()));
if (object.IsJSFunction()) object.AsJSFunction().Serialize();
if (object.IsJSObject()) object.AsJSObject().SerializeObjectCreateMap();
if (object.IsModule()) object.AsModule().Serialize();
break;
}
......@@ -44,16 +45,18 @@ Reduction JSHeapCopyReducer::Reduce(Node* node) {
state_info.shared_info().ToHandleChecked());
break;
}
case IrOpcode::kJSCreateBlockContext:
case IrOpcode::kJSCreateCatchContext:
case IrOpcode::kJSCreateWithContext: {
case IrOpcode::kJSCreateBlockContext: {
ScopeInfoRef(broker(), ScopeInfoOf(node->op()));
break;
}
case IrOpcode::kJSCreateBoundFunction: {
CreateBoundFunctionParameters const& p =
CreateBoundFunctionParametersOf(node->op());
MapRef map(broker(), p.map());
MapRef(broker(), p.map());
break;
}
case IrOpcode::kJSCreateCatchContext: {
ScopeInfoRef(broker(), ScopeInfoOf(node->op()));
break;
}
case IrOpcode::kJSCreateClosure: {
......@@ -85,6 +88,10 @@ Reduction JSHeapCopyReducer::Reduce(Node* node) {
FeedbackVectorRef(broker(), p.feedback().vector()).SerializeSlots();
break;
}
case IrOpcode::kJSCreateWithContext: {
ScopeInfoRef(broker(), ScopeInfoOf(node->op()));
break;
}
case IrOpcode::kJSLoadNamed:
case IrOpcode::kJSStoreNamed: {
NamedAccess const& p = NamedAccessOf(node->op());
......
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