Commit 1179c6b0 authored by Jakob Gruber's avatar Jakob Gruber Committed by V8 LUCI CQ

[compiler] Don't serialize object_create_map

.. when concurrent-inlining, use direct reads instead.

Two fields were changed to have a non-atomic getter and acq-rel
accessors:

- Map::prototype_info
- PrototypeInfo::object_create_map

Bug: v8:7790
Change-Id: I05e888240d73ab6e961b1048a25713ec45fb0305
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2876852Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74777}
parent f15a656d
......@@ -439,8 +439,8 @@ class JSObjectData : public JSReceiverData {
void SerializeObjectCreateMap(JSHeapBroker* broker);
ObjectData* object_create_map(
JSHeapBroker* broker) const { // Can be nullptr.
// Can be nullptr.
ObjectData* object_create_map(JSHeapBroker* broker) const {
if (!serialized_object_create_map_) {
DCHECK_NULL(object_create_map_);
TRACE_MISSING(broker, "object_create_map on " << this);
......@@ -2892,24 +2892,6 @@ int ObjectRef::AsSmi() const {
return Handle<Smi>::cast(object())->value();
}
base::Optional<MapRef> JSObjectRef::GetObjectCreateMap() const {
if (data_->should_access_heap()) {
Handle<Map> instance_map;
if (Map::TryGetObjectCreateMap(broker()->isolate(), object())
.ToHandle(&instance_map)) {
return MakeRef(broker(), instance_map);
} else {
return base::Optional<MapRef>();
}
}
ObjectData* map_data = data()->AsJSObject()->object_create_map(broker());
if (map_data == nullptr) return base::Optional<MapRef>();
if (map_data->should_access_heap()) {
return MakeRef(broker(), Handle<Map>::cast(map_data->object()));
}
return MapRef(broker(), map_data->AsMap());
}
#define DEF_TESTER(Type, ...) \
bool MapRef::Is##Type##Map() const { \
return InstanceTypeChecker::Is##Type(instance_type()); \
......@@ -4425,12 +4407,42 @@ ScopeInfoRef SharedFunctionInfoRef::scope_info() const {
}
void JSObjectRef::SerializeObjectCreateMap() {
if (data_->should_access_heap()) return;
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) {
return;
}
CHECK_IMPLIES(!FLAG_turbo_concurrent_get_property_access_info,
broker()->mode() == JSHeapBroker::kSerializing);
data()->AsJSObject()->SerializeObjectCreateMap(broker());
}
base::Optional<MapRef> JSObjectRef::GetObjectCreateMap() const {
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) {
Handle<Map> map_handle = Handle<Map>::cast(map().object());
// Note: implemented as an acquire-load.
if (!map_handle->is_prototype_map()) return {};
Handle<Object> maybe_proto_info = broker()->CanonicalPersistentHandle(
map_handle->prototype_info(kAcquireLoad));
if (!maybe_proto_info->IsPrototypeInfo()) return {};
MaybeObject maybe_object_create_map =
Handle<PrototypeInfo>::cast(maybe_proto_info)
->object_create_map(kAcquireLoad);
if (!maybe_object_create_map->IsWeak()) return {};
return MapRef(broker(),
broker()->GetOrCreateData(
maybe_object_create_map->GetHeapObjectAssumeWeak(),
kAssumeMemoryFence));
}
ObjectData* map_data = data()->AsJSObject()->object_create_map(broker());
if (map_data == nullptr) return base::Optional<MapRef>();
if (map_data->should_access_heap()) {
return TryMakeRef(broker(), Handle<Map>::cast(map_data->object()));
}
return MapRef(broker(), map_data->AsMap());
}
bool MapRef::TrySerializeOwnDescriptor(InternalIndex descriptor_index) {
CHECK_LT(descriptor_index.as_int(), NumberOfOwnDescriptors());
if (data_->should_access_heap()) return true;
......
......@@ -2707,8 +2707,8 @@ void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
DCHECK(old_map->is_prototype_map());
DCHECK(new_map->is_prototype_map());
bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
new_map->set_prototype_info(old_map->prototype_info());
old_map->set_prototype_info(Smi::zero());
new_map->set_prototype_info(old_map->prototype_info(), kReleaseStore);
old_map->set_prototype_info(Smi::zero(), kReleaseStore);
if (FLAG_trace_prototype_users) {
PrintF("Moving prototype_info %p from map %p to map %p.\n",
reinterpret_cast<void*>(new_map->prototype_info().ptr()),
......
......@@ -54,8 +54,14 @@ RELEASE_ACQUIRE_WEAK_ACCESSORS(Map, raw_transitions,
ACCESSORS_CHECKED2(Map, prototype, HeapObject, kPrototypeOffset, true,
value.IsNull() || value.IsJSReceiver())
ACCESSORS_CHECKED(Map, prototype_info, Object,
kTransitionsOrPrototypeInfoOffset, this->is_prototype_map())
DEF_GETTER(Map, prototype_info, Object) {
Object value = TaggedField<Object, kTransitionsOrPrototypeInfoOffset>::load(
cage_base, *this);
DCHECK(this->is_prototype_map());
return value;
}
RELEASE_ACQUIRE_ACCESSORS(Map, prototype_info, Object,
kTransitionsOrPrototypeInfoOffset)
// |bit_field| fields.
// Concurrent access to |has_prototype_slot| and |has_non_instance_prototype|
......
......@@ -934,24 +934,6 @@ Handle<Map> Map::GetObjectCreateMap(Isolate* isolate,
return Map::TransitionToPrototype(isolate, map, prototype);
}
// static
MaybeHandle<Map> Map::TryGetObjectCreateMap(Isolate* isolate,
Handle<HeapObject> prototype) {
Handle<Map> map(isolate->native_context()->object_function().initial_map(),
isolate);
if (map->prototype() == *prototype) return map;
if (prototype->IsNull(isolate)) {
return isolate->slow_object_with_null_prototype_map();
}
if (!prototype->IsJSObject()) return MaybeHandle<Map>();
Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
if (!js_prototype->map().is_prototype_map()) return MaybeHandle<Map>();
Handle<PrototypeInfo> info =
Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
if (!info->HasObjectCreateMap()) return MaybeHandle<Map>();
return handle(info->ObjectCreateMap(), isolate);
}
static bool ContainsMap(MapHandles const& maps, Map map) {
DCHECK(!map.is_null());
for (Handle<Map> current : maps) {
......@@ -2256,7 +2238,7 @@ Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
}
Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
prototype->map().set_prototype_info(*proto_info);
prototype->map().set_prototype_info(*proto_info, kReleaseStore);
return proto_info;
}
......@@ -2268,7 +2250,7 @@ Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map,
return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
}
Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
prototype_map->set_prototype_info(*proto_info);
prototype_map->set_prototype_info(*proto_info, kReleaseStore);
return proto_info;
}
......
......@@ -446,7 +446,8 @@ class Map : public HeapObject {
DECL_RELEASE_ACQUIRE_WEAK_ACCESSORS(raw_transitions)
// [prototype_info]: Per-prototype metadata. Aliased with transitions
// (which prototype maps don't have).
DECL_ACCESSORS(prototype_info, Object)
DECL_GETTER(prototype_info, Object)
DECL_RELEASE_ACQUIRE_ACCESSORS(prototype_info, Object)
// PrototypeInfo is created lazily using this helper (which installs it on
// the given prototype's map).
static Handle<PrototypeInfo> GetOrCreatePrototypeInfo(
......@@ -761,11 +762,6 @@ class Map : public HeapObject {
static Handle<Map> GetObjectCreateMap(Isolate* isolate,
Handle<HeapObject> prototype);
// Similar to {GetObjectCreateMap} but does not transition {prototype} and
// fails gracefully by returning an empty handle instead.
static MaybeHandle<Map> TryGetObjectCreateMap(Isolate* isolate,
Handle<HeapObject> prototype);
// Computes a hash value for this map, to be used in HashTables and such.
int Hash();
......
......@@ -24,6 +24,13 @@ namespace internal {
TQ_OBJECT_CONSTRUCTORS_IMPL(PrototypeInfo)
DEF_GETTER(PrototypeInfo, object_create_map, MaybeObject) {
return TaggedField<MaybeObject, kObjectCreateMapOffset>::load(cage_base,
*this);
}
RELEASE_ACQUIRE_WEAK_ACCESSORS(PrototypeInfo, object_create_map,
kObjectCreateMapOffset)
Map PrototypeInfo::ObjectCreateMap() {
return Map::cast(object_create_map()->GetHeapObjectAssumeWeak());
}
......@@ -31,7 +38,7 @@ Map PrototypeInfo::ObjectCreateMap() {
// static
void PrototypeInfo::SetObjectCreateMap(Handle<PrototypeInfo> info,
Handle<Map> map) {
info->set_object_create_map(HeapObjectReference::Weak(*map));
info->set_object_create_map(HeapObjectReference::Weak(*map), kReleaseStore);
}
bool PrototypeInfo::HasObjectCreateMap() {
......
......@@ -25,6 +25,9 @@ class PrototypeInfo
static const int UNREGISTERED = -1;
// [object_create_map]: A field caching the map for Object.create(prototype).
DECL_GETTER(object_create_map, MaybeObject)
DECL_RELEASE_ACQUIRE_WEAK_ACCESSORS(object_create_map)
static inline void SetObjectCreateMap(Handle<PrototypeInfo> info,
Handle<Map> map);
inline Map ObjectCreateMap();
......
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