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

[compiler] Make JSObjectRef and others background-serialized

.. now that all JSObjectRef methods can run in concurrent settings.

Also change a few subtypes to bg-serialized:

 - JSArray
 - JSGlobalProxy
 - JSTypedArray

Bug: v8:7790
Change-Id: I406b0a8eacb4e5bd2c3a24eb106b29df2cf55421
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2966377Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75452}
parent cd658fd2
...@@ -92,11 +92,14 @@ class PrototypePropertyDependency final : public CompilationDependency { ...@@ -92,11 +92,14 @@ class PrototypePropertyDependency final : public CompilationDependency {
class StableMapDependency final : public CompilationDependency { class StableMapDependency final : public CompilationDependency {
public: public:
explicit StableMapDependency(const MapRef& map) : map_(map) { explicit StableMapDependency(const MapRef& map) : map_(map) {}
DCHECK(map_.is_stable());
}
bool IsValid() const override { return map_.object()->is_stable(); } bool IsValid() const override {
// TODO(v8:11670): Consider turn this back into a CHECK inside the
// constructor and DependOnStableMap, if possible in light of concurrent
// heap state modifications.
return !map_.object()->is_dictionary_map() && map_.object()->is_stable();
}
void Install(Handle<Code> code) const override { void Install(Handle<Code> code) const override {
SLOW_DCHECK(IsValid()); SLOW_DCHECK(IsValid());
...@@ -396,15 +399,19 @@ class FieldRepresentationDependency final : public CompilationDependency { ...@@ -396,15 +399,19 @@ class FieldRepresentationDependency final : public CompilationDependency {
: owner_(owner), : owner_(owner),
descriptor_(descriptor), descriptor_(descriptor),
representation_(representation) { representation_(representation) {
CHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
CHECK(representation_.Equals(
owner_.GetPropertyDetails(descriptor_).representation()));
} }
bool IsValid() const override { bool IsValid() const override {
DisallowGarbageCollection no_heap_allocation; DisallowGarbageCollection no_heap_allocation;
Handle<Map> owner = owner_.object(); Handle<Map> owner = owner_.object();
return representation_.Equals(owner->instance_descriptors(owner_.isolate()) Isolate* isolate = owner_.isolate();
// TODO(v8:11670): Consider turn this back into a CHECK inside the
// constructor, if possible in light of concurrent heap state
// modifications.
if (owner->FindFieldOwner(isolate, descriptor_) != *owner) return false;
return representation_.Equals(owner->instance_descriptors(isolate)
.GetDetails(descriptor_) .GetDetails(descriptor_)
.representation()); .representation());
} }
...@@ -434,17 +441,21 @@ class FieldTypeDependency final : public CompilationDependency { ...@@ -434,17 +441,21 @@ class FieldTypeDependency final : public CompilationDependency {
// longer need to explicitly store the type. // longer need to explicitly store the type.
FieldTypeDependency(const MapRef& owner, InternalIndex descriptor, FieldTypeDependency(const MapRef& owner, InternalIndex descriptor,
const ObjectRef& type) const ObjectRef& type)
: owner_(owner), descriptor_(descriptor), type_(type) { : owner_(owner), descriptor_(descriptor), type_(type) {}
CHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
CHECK(type_.equals(owner_.GetFieldType(descriptor_)));
}
bool IsValid() const override { bool IsValid() const override {
DisallowGarbageCollection no_heap_allocation; DisallowGarbageCollection no_heap_allocation;
Handle<Map> owner = owner_.object(); Handle<Map> owner = owner_.object();
Isolate* isolate = owner_.isolate();
// TODO(v8:11670): Consider turn this back into a CHECK inside the
// constructor, if possible in light of concurrent heap state
// modifications.
if (owner->FindFieldOwner(isolate, descriptor_) != *owner) return false;
Handle<Object> type = type_.object(); Handle<Object> type = type_.object();
return *type == owner->instance_descriptors(owner_.isolate()) return *type ==
.GetFieldType(descriptor_); owner->instance_descriptors(isolate).GetFieldType(descriptor_);
} }
void Install(Handle<Code> code) const override { void Install(Handle<Code> code) const override {
...@@ -462,19 +473,21 @@ class FieldTypeDependency final : public CompilationDependency { ...@@ -462,19 +473,21 @@ class FieldTypeDependency final : public CompilationDependency {
class FieldConstnessDependency final : public CompilationDependency { class FieldConstnessDependency final : public CompilationDependency {
public: public:
FieldConstnessDependency(const MapRef& owner, InternalIndex descriptor) FieldConstnessDependency(const MapRef& owner, InternalIndex descriptor)
: owner_(owner), descriptor_(descriptor) { : owner_(owner), descriptor_(descriptor) {}
CHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
CHECK_EQ(PropertyConstness::kConst,
owner_.GetPropertyDetails(descriptor_).constness());
}
bool IsValid() const override { bool IsValid() const override {
DisallowGarbageCollection no_heap_allocation; DisallowGarbageCollection no_heap_allocation;
Handle<Map> owner = owner_.object(); Handle<Map> owner = owner_.object();
return PropertyConstness::kConst == Isolate* isolate = owner_.isolate();
owner->instance_descriptors(owner_.isolate())
.GetDetails(descriptor_) // TODO(v8:11670): Consider turn this back into a CHECK inside the
.constness(); // constructor, if possible in light of concurrent heap state
// modifications.
if (owner->FindFieldOwner(isolate, descriptor_) != *owner) return false;
return PropertyConstness::kConst == owner->instance_descriptors(isolate)
.GetDetails(descriptor_)
.constness();
} }
void Install(Handle<Code> code) const override { void Install(Handle<Code> code) const override {
...@@ -658,12 +671,9 @@ ObjectRef CompilationDependencies::DependOnPrototypeProperty( ...@@ -658,12 +671,9 @@ ObjectRef CompilationDependencies::DependOnPrototypeProperty(
} }
void CompilationDependencies::DependOnStableMap(const MapRef& map) { void CompilationDependencies::DependOnStableMap(const MapRef& map) {
DCHECK(!map.is_dictionary_map());
DCHECK(!map.IsNeverSerializedHeapObject()); DCHECK(!map.IsNeverSerializedHeapObject());
if (map.CanTransition()) { if (map.CanTransition()) {
RecordDependency(zone_->New<StableMapDependency>(map)); RecordDependency(zone_->New<StableMapDependency>(map));
} else {
DCHECK(map.is_stable());
} }
} }
......
...@@ -431,7 +431,8 @@ class JSReceiverData : public HeapObjectData { ...@@ -431,7 +431,8 @@ class JSReceiverData : public HeapObjectData {
class JSObjectData : public JSReceiverData { class JSObjectData : public JSReceiverData {
public: public:
JSObjectData(JSHeapBroker* broker, ObjectData** storage, JSObjectData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSObject> object); Handle<JSObject> object,
ObjectDataKind kind = kSerializedHeapObject);
// Recursive serialization of all reachable JSObjects. // Recursive serialization of all reachable JSObjects.
void SerializeAsBoilerplate(JSHeapBroker* broker); void SerializeAsBoilerplate(JSHeapBroker* broker);
...@@ -692,12 +693,8 @@ ObjectData* JSObjectData::GetOwnDictionaryProperty(JSHeapBroker* broker, ...@@ -692,12 +693,8 @@ ObjectData* JSObjectData::GetOwnDictionaryProperty(JSHeapBroker* broker,
class JSTypedArrayData : public JSObjectData { class JSTypedArrayData : public JSObjectData {
public: public:
JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage, JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSTypedArray> object) Handle<JSTypedArray> object, ObjectDataKind kind)
: JSObjectData(broker, storage, object) {} : JSObjectData(broker, storage, object, kind) {}
// TODO(v8:7790): Once JSObject is no longer serialized, also make
// JSTypedArrayRef never-serialized.
STATIC_ASSERT(IsSerializedRef<JSObject>());
void Serialize(JSHeapBroker* broker); void Serialize(JSHeapBroker* broker);
bool serialized() const { return serialized_; } bool serialized() const { return serialized_; }
...@@ -1384,7 +1381,8 @@ HeapObjectData::HeapObjectData(JSHeapBroker* broker, ObjectData** storage, ...@@ -1384,7 +1381,8 @@ HeapObjectData::HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
// instance_type_ member. In the case of constructing the MapData for the // instance_type_ member. In the case of constructing the MapData for the
// meta map (whose map is itself), this member has not yet been // meta map (whose map is itself), this member has not yet been
// initialized. // initialized.
map_(broker->GetOrCreateData(object->map(kAcquireLoad))) { map_(broker->GetOrCreateData(object->map(kAcquireLoad),
kAssumeMemoryFence)) {
CHECK_IMPLIES(kind == kSerializedHeapObject, CHECK_IMPLIES(kind == kSerializedHeapObject,
broker->mode() == JSHeapBroker::kSerializing); broker->mode() == JSHeapBroker::kSerializing);
CHECK_IMPLIES(broker->mode() == JSHeapBroker::kSerialized, CHECK_IMPLIES(broker->mode() == JSHeapBroker::kSerialized,
...@@ -1873,9 +1871,8 @@ bool JSBoundFunctionData::Serialize(JSHeapBroker* broker) { ...@@ -1873,9 +1871,8 @@ bool JSBoundFunctionData::Serialize(JSHeapBroker* broker) {
} }
JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage, JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSObject> object) Handle<JSObject> object, ObjectDataKind kind)
: JSReceiverData(broker, storage, object, : JSReceiverData(broker, storage, object, kind),
ObjectDataKind::kSerializedHeapObject),
inobject_fields_(broker->zone()), inobject_fields_(broker->zone()),
own_constant_elements_(broker->zone()), own_constant_elements_(broker->zone()),
own_properties_(broker->zone()) {} own_properties_(broker->zone()) {}
...@@ -1907,7 +1904,10 @@ class BytecodeArrayData : public FixedArrayBaseData { ...@@ -1907,7 +1904,10 @@ class BytecodeArrayData : public FixedArrayBaseData {
class JSArrayData : public JSObjectData { class JSArrayData : public JSObjectData {
public: public:
JSArrayData(JSHeapBroker* broker, ObjectData** storage, JSArrayData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSArray> object); Handle<JSArray> object,
ObjectDataKind kind = kSerializedHeapObject)
: JSObjectData(broker, storage, object, kind),
own_elements_(broker->zone()) {}
void Serialize(JSHeapBroker* broker); void Serialize(JSHeapBroker* broker);
ObjectData* length() const { ObjectData* length() const {
...@@ -1930,10 +1930,6 @@ class JSArrayData : public JSObjectData { ...@@ -1930,10 +1930,6 @@ class JSArrayData : public JSObjectData {
ZoneVector<std::pair<uint32_t, ObjectData*>> own_elements_; ZoneVector<std::pair<uint32_t, ObjectData*>> own_elements_;
}; };
JSArrayData::JSArrayData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSArray> object)
: JSObjectData(broker, storage, object), own_elements_(broker->zone()) {}
void JSArrayData::Serialize(JSHeapBroker* broker) { void JSArrayData::Serialize(JSHeapBroker* broker) {
CHECK(!broker->is_concurrent_inlining()); CHECK(!broker->is_concurrent_inlining());
...@@ -2217,13 +2213,11 @@ JSGlobalObjectData::JSGlobalObjectData(JSHeapBroker* broker, ...@@ -2217,13 +2213,11 @@ JSGlobalObjectData::JSGlobalObjectData(JSHeapBroker* broker,
class JSGlobalProxyData : public JSObjectData { class JSGlobalProxyData : public JSObjectData {
public: public:
JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage, JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSGlobalProxy> object); Handle<JSGlobalProxy> object,
ObjectDataKind kind = kSerializedHeapObject)
: JSObjectData(broker, storage, object, kind) {}
}; };
JSGlobalProxyData::JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSGlobalProxy> object)
: JSObjectData(broker, storage, object) {}
namespace { namespace {
base::Optional<PropertyCellRef> GetPropertyCellFromHeap(JSHeapBroker* broker, base::Optional<PropertyCellRef> GetPropertyCellFromHeap(JSHeapBroker* broker,
...@@ -3640,7 +3634,8 @@ DescriptorArrayRef MapRef::instance_descriptors() const { ...@@ -3640,7 +3634,8 @@ DescriptorArrayRef MapRef::instance_descriptors() const {
base::Optional<HeapObjectRef> MapRef::prototype() const { base::Optional<HeapObjectRef> MapRef::prototype() const {
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) { if (data_->should_access_heap() || broker()->is_concurrent_inlining()) {
return TryMakeRef(broker(), HeapObject::cast(object()->prototype())); return MakeRefAssumeMemoryFence(broker(),
HeapObject::cast(object()->prototype()));
} }
ObjectData* prototype_data = data()->AsMap()->prototype(); ObjectData* prototype_data = data()->AsMap()->prototype();
if (prototype_data == nullptr) { if (prototype_data == nullptr) {
...@@ -4612,14 +4607,7 @@ void SourceTextModuleRef::Serialize() { ...@@ -4612,14 +4607,7 @@ void SourceTextModuleRef::Serialize() {
void JSTypedArrayRef::Serialize() { void JSTypedArrayRef::Serialize() {
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) { if (data_->should_access_heap() || broker()->is_concurrent_inlining()) {
// Even if the typed array object itself is no longer serialized (besides // Nothing to do.
// the JSObject parts), the `buffer` field still is and thus we need to
// make sure to visit it.
// TODO(jgruber,v8:7790): Remove once JSObject is no longer serialized.
static_assert(
std::is_base_of<JSObject, decltype(object()->buffer())>::value, "");
STATIC_ASSERT(IsSerializedRef<JSObject>());
MakeRef<JSObject>(broker(), object()->buffer());
} else { } else {
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing); CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsJSTypedArray()->Serialize(broker()); data()->AsJSTypedArray()->Serialize(broker());
......
...@@ -80,13 +80,13 @@ enum class RefSerializationKind { ...@@ -80,13 +80,13 @@ enum class RefSerializationKind {
// DO NOT VIOLATE THIS PROPERTY! // DO NOT VIOLATE THIS PROPERTY!
#define HEAP_BROKER_OBJECT_LIST(V) \ #define HEAP_BROKER_OBJECT_LIST(V) \
/* Subtypes of JSObject */ \ /* Subtypes of JSObject */ \
V(JSArray, RefSerializationKind::kSerialized) \ V(JSArray, RefSerializationKind::kBackgroundSerialized) \
V(JSBoundFunction, RefSerializationKind::kSerialized) \ V(JSBoundFunction, RefSerializationKind::kSerialized) \
V(JSDataView, RefSerializationKind::kSerialized) \ V(JSDataView, RefSerializationKind::kSerialized) \
V(JSFunction, RefSerializationKind::kSerialized) \ V(JSFunction, RefSerializationKind::kSerialized) \
V(JSGlobalObject, RefSerializationKind::kSerialized) \ V(JSGlobalObject, RefSerializationKind::kSerialized) \
V(JSGlobalProxy, RefSerializationKind::kSerialized) \ V(JSGlobalProxy, RefSerializationKind::kBackgroundSerialized) \
V(JSTypedArray, RefSerializationKind::kSerialized) \ V(JSTypedArray, RefSerializationKind::kBackgroundSerialized) \
/* Subtypes of Context */ \ /* Subtypes of Context */ \
V(NativeContext, RefSerializationKind::kNeverSerialized) \ V(NativeContext, RefSerializationKind::kNeverSerialized) \
/* Subtypes of FixedArray */ \ /* Subtypes of FixedArray */ \
...@@ -102,7 +102,7 @@ enum class RefSerializationKind { ...@@ -102,7 +102,7 @@ enum class RefSerializationKind {
V(String, RefSerializationKind::kNeverSerialized) \ V(String, RefSerializationKind::kNeverSerialized) \
V(Symbol, RefSerializationKind::kNeverSerialized) \ V(Symbol, RefSerializationKind::kNeverSerialized) \
/* Subtypes of JSReceiver */ \ /* Subtypes of JSReceiver */ \
V(JSObject, RefSerializationKind::kSerialized) \ V(JSObject, RefSerializationKind::kBackgroundSerialized) \
/* Subtypes of HeapObject */ \ /* Subtypes of HeapObject */ \
V(AccessorInfo, RefSerializationKind::kNeverSerialized) \ V(AccessorInfo, RefSerializationKind::kNeverSerialized) \
V(AllocationSite, RefSerializationKind::kSerialized) \ V(AllocationSite, RefSerializationKind::kSerialized) \
......
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