mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:45:06 +00:00
[vm] Simplify is-deeply-immutable check in transitive object copy
Now that we have an immutability bit, we can set the bit in object header of newly allocated objects if those objects are always deeply immutable. That allows only checking for the immutable bit instead of checking against a whole range of cids when sending objects via `SendPort.send()` / `Isolate.exit()`. TEST=ci Change-Id: I4451a9fe11f68c7dd874d49ab632daa3102be19e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/281842 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
ebdb53fe85
commit
7db7bd0573
|
@ -214,32 +214,11 @@ static ObjectPtr ValidateMessageObject(Zone* zone,
|
|||
thread->CheckForSafepoint();
|
||||
|
||||
ObjectPtr raw = working_set->RemoveLast();
|
||||
|
||||
if (CanShareObjectAcrossIsolates(raw)) {
|
||||
continue;
|
||||
}
|
||||
const intptr_t cid = raw->GetClassId();
|
||||
// Keep the list in sync with the one in runtime/vm/object_graph_copy.cc
|
||||
switch (cid) {
|
||||
// Can be shared.
|
||||
case kOneByteStringCid:
|
||||
case kTwoByteStringCid:
|
||||
case kExternalOneByteStringCid:
|
||||
case kExternalTwoByteStringCid:
|
||||
case kMintCid:
|
||||
case kImmutableArrayCid:
|
||||
case kNeverCid:
|
||||
case kSentinelCid:
|
||||
case kInt32x4Cid:
|
||||
case kSendPortCid:
|
||||
case kCapabilityCid:
|
||||
case kRegExpCid:
|
||||
case kStackTraceCid:
|
||||
continue;
|
||||
// Cannot be shared due to possibly being mutable boxes for unboxed
|
||||
// fields in JIT, but can be transferred via Isolate.exit()
|
||||
case kDoubleCid:
|
||||
case kFloat32x4Cid:
|
||||
case kFloat64x2Cid:
|
||||
continue;
|
||||
|
||||
case kArrayCid: {
|
||||
array ^= Array::RawCast(raw);
|
||||
visitor.VisitObject(array.GetTypeArguments());
|
||||
|
|
|
@ -419,6 +419,16 @@ inline bool IsUnmodifiableTypedDataViewClassId(intptr_t index) {
|
|||
kTypedDataCidRemainderUnmodifiable);
|
||||
}
|
||||
|
||||
inline bool ShouldHaveImmutabilityBitSet(intptr_t index) {
|
||||
return IsUnmodifiableTypedDataViewClassId(index) || IsStringClassId(index) ||
|
||||
index == kMintCid || index == kNeverCid || index == kSentinelCid ||
|
||||
index == kStackTraceCid || index == kDoubleCid ||
|
||||
index == kFloat32x4Cid || index == kFloat64x2Cid ||
|
||||
index == kInt32x4Cid || index == kSendPortCid ||
|
||||
index == kCapabilityCid || index == kRegExpCid || index == kBoolCid ||
|
||||
index == kNullCid;
|
||||
}
|
||||
|
||||
inline bool IsFfiTypeClassId(intptr_t index) {
|
||||
switch (index) {
|
||||
case kPointerCid:
|
||||
|
|
|
@ -349,7 +349,7 @@ uword MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size) {
|
|||
dart::UntaggedObject::ClassIdTag::encode(cid) |
|
||||
dart::UntaggedObject::NewBit::encode(true) |
|
||||
dart::UntaggedObject::ImmutableBit::encode(
|
||||
IsUnmodifiableTypedDataViewClassId(cid));
|
||||
ShouldHaveImmutabilityBitSet(cid));
|
||||
}
|
||||
|
||||
word Object::tags_offset() {
|
||||
|
|
|
@ -2766,7 +2766,7 @@ void Object::InitializeObject(uword address,
|
|||
tags = UntaggedObject::OldAndNotRememberedBit::update(is_old, tags);
|
||||
tags = UntaggedObject::NewBit::update(!is_old, tags);
|
||||
tags = UntaggedObject::ImmutableBit::update(
|
||||
IsUnmodifiableTypedDataViewClassId(class_id), tags);
|
||||
ShouldHaveImmutabilityBitSet(class_id), tags);
|
||||
#if defined(HASH_IN_OBJECT_HEADER)
|
||||
tags = UntaggedObject::HashTag::update(0, tags);
|
||||
#endif
|
||||
|
|
|
@ -144,47 +144,30 @@ static ObjectPtr Marker() {
|
|||
return Object::unknown_constant().ptr();
|
||||
}
|
||||
|
||||
// Keep in sync with runtime/lib/isolate.cc:ValidateMessageObject
|
||||
DART_FORCE_INLINE
|
||||
static bool CanShareObject(ObjectPtr obj, uword tags) {
|
||||
if ((tags & UntaggedObject::CanonicalBit::mask_in_place()) != 0) {
|
||||
return true;
|
||||
}
|
||||
const auto cid = UntaggedObject::ClassIdTag::decode(tags);
|
||||
if (cid == kOneByteStringCid) return true;
|
||||
if (cid == kTwoByteStringCid) return true;
|
||||
if (cid == kExternalOneByteStringCid) return true;
|
||||
if (cid == kExternalTwoByteStringCid) return true;
|
||||
if (cid == kMintCid) return true;
|
||||
if (cid == kNeverCid) return true;
|
||||
if (cid == kSentinelCid) return true;
|
||||
if (cid == kStackTraceCid) return true;
|
||||
if (cid == kDoubleCid || cid == kFloat32x4Cid || cid == kFloat64x2Cid ||
|
||||
cid == kInt32x4Cid) {
|
||||
if ((tags & UntaggedObject::ImmutableBit::mask_in_place()) != 0) {
|
||||
if (IsUnmodifiableTypedDataViewClassId(cid)) {
|
||||
// Unmodifiable typed data views may have mutable backing stores.
|
||||
return TypedDataView::RawCast(obj)
|
||||
->untag()
|
||||
->typed_data()
|
||||
->untag()
|
||||
->IsImmutable();
|
||||
}
|
||||
// All other objects that have immutability bit set are deeply immutable.
|
||||
return true;
|
||||
}
|
||||
if (cid == kSendPortCid) return true;
|
||||
if (cid == kCapabilityCid) return true;
|
||||
if (cid == kRegExpCid) return true;
|
||||
|
||||
if (cid == kClosureCid) {
|
||||
// We can share a closure iff it doesn't close over any state.
|
||||
return Closure::RawCast(obj)->untag()->context() == Object::null();
|
||||
}
|
||||
|
||||
if (IsUnmodifiableTypedDataViewClassId(cid)) {
|
||||
// Unmodifiable typed data views may have mutable backing stores.
|
||||
return TypedDataView::RawCast(obj)
|
||||
->untag()
|
||||
->typed_data()
|
||||
->untag()
|
||||
->IsImmutable();
|
||||
} else {
|
||||
if ((tags & UntaggedObject::ImmutableBit::mask_in_place()) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -253,6 +253,9 @@ class UntaggedObject {
|
|||
class OldAndNotRememberedBit
|
||||
: public BitField<uword, bool, kOldAndNotRememberedBit, 1> {};
|
||||
|
||||
// Will be set to 1 iff
|
||||
// - is unmodifiable typed data view (backing store may be mutable)
|
||||
// - is transitively immutable
|
||||
class ImmutableBit : public BitField<uword, bool, kImmutableBit, 1> {};
|
||||
|
||||
class ReservedBit : public BitField<uword, intptr_t, kReservedBit, 1> {};
|
||||
|
|
Loading…
Reference in a new issue