mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 21:11:19 +00:00
[vm] Clear trailing bytes of objects that end up in snapshot images.
Previously, these bytes contained (parts of) the address of null, which is not deterministic. Bug: https://github.com/dart-lang/sdk/issues/31427 Change-Id: Id3eb16b32d15ff5e0648571a1168dc6f9e3fcbe5 Reviewed-on: https://dart-review.googlesource.com/51181 Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
parent
3a5fcf5a87
commit
c32e0e4bf3
|
@ -1996,23 +1996,13 @@ class RODataSerializationCluster : public SerializationCluster {
|
|||
objects_.Add(object);
|
||||
|
||||
// A string's hash must already be computed when we write it because it
|
||||
// will be loaded into read-only memory.
|
||||
if (cid_ == kOneByteStringCid) {
|
||||
RawOneByteString* str = static_cast<RawOneByteString*>(object);
|
||||
if (String::GetCachedHash(str) == 0) {
|
||||
intptr_t hash =
|
||||
String::Hash(str->ptr()->data(), Smi::Value(str->ptr()->length_));
|
||||
String::SetCachedHash(str, hash);
|
||||
}
|
||||
ASSERT(String::GetCachedHash(str) != 0);
|
||||
} else if (cid_ == kTwoByteStringCid) {
|
||||
RawTwoByteString* str = static_cast<RawTwoByteString*>(object);
|
||||
if (String::GetCachedHash(str) == 0) {
|
||||
intptr_t hash = String::Hash(str->ptr()->data(),
|
||||
Smi::Value(str->ptr()->length_) * 2);
|
||||
String::SetCachedHash(str, hash);
|
||||
}
|
||||
ASSERT(String::GetCachedHash(str) != 0);
|
||||
// will be loaded into read-only memory. Extra bytes due to allocation
|
||||
// rounding need to be deterministically set for reliable deduplication in
|
||||
// shared images.
|
||||
if (object->IsVMHeapObject()) {
|
||||
// This object is already read-only.
|
||||
} else {
|
||||
Object::FinalizeReadOnlyObject(object);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1038,11 +1038,7 @@ class FinalizeVMIsolateVisitor : public ObjectVisitor {
|
|||
if (!obj->IsFreeListElement()) {
|
||||
ASSERT(obj->IsVMHeapObject());
|
||||
obj->SetMarkBitUnsynchronized();
|
||||
if (obj->IsStringInstance()) {
|
||||
RawString* str = reinterpret_cast<RawString*>(obj);
|
||||
intptr_t hash = String::Hash(str);
|
||||
String::SetCachedHash(str, hash);
|
||||
}
|
||||
Object::FinalizeReadOnlyObject(obj);
|
||||
#if defined(HASH_IN_OBJECT_HEADER)
|
||||
// These objects end up in the read-only VM isolate which is shared
|
||||
// between isolates, so we have to prepopulate them with identity hash
|
||||
|
@ -1148,6 +1144,65 @@ void Object::FinalizeVMIsolate(Isolate* isolate) {
|
|||
}
|
||||
}
|
||||
|
||||
void Object::FinalizeReadOnlyObject(RawObject* object) {
|
||||
NoSafepointScope no_safepoint;
|
||||
intptr_t cid = object->GetClassId();
|
||||
if (cid == kOneByteStringCid) {
|
||||
RawOneByteString* str = static_cast<RawOneByteString*>(object);
|
||||
if (String::GetCachedHash(str) == 0) {
|
||||
intptr_t hash = String::Hash(str);
|
||||
String::SetCachedHash(str, hash);
|
||||
}
|
||||
intptr_t size = OneByteString::UnroundedSize(str);
|
||||
ASSERT(size <= str->Size());
|
||||
memset(reinterpret_cast<void*>(RawObject::ToAddr(str) + size), 0,
|
||||
str->Size() - size);
|
||||
} else if (cid == kTwoByteStringCid) {
|
||||
RawTwoByteString* str = static_cast<RawTwoByteString*>(object);
|
||||
if (String::GetCachedHash(str) == 0) {
|
||||
intptr_t hash = String::Hash(str);
|
||||
String::SetCachedHash(str, hash);
|
||||
}
|
||||
ASSERT(String::GetCachedHash(str) != 0);
|
||||
intptr_t size = TwoByteString::UnroundedSize(str);
|
||||
ASSERT(size <= str->Size());
|
||||
memset(reinterpret_cast<void*>(RawObject::ToAddr(str) + size), 0,
|
||||
str->Size() - size);
|
||||
} else if (cid == kExternalOneByteStringCid) {
|
||||
RawExternalOneByteString* str =
|
||||
static_cast<RawExternalOneByteString*>(object);
|
||||
if (String::GetCachedHash(str) == 0) {
|
||||
intptr_t hash = String::Hash(str);
|
||||
String::SetCachedHash(str, hash);
|
||||
}
|
||||
} else if (cid == kExternalTwoByteStringCid) {
|
||||
RawExternalTwoByteString* str =
|
||||
static_cast<RawExternalTwoByteString*>(object);
|
||||
if (String::GetCachedHash(str) == 0) {
|
||||
intptr_t hash = String::Hash(str);
|
||||
String::SetCachedHash(str, hash);
|
||||
}
|
||||
} else if (cid == kCodeSourceMapCid) {
|
||||
RawCodeSourceMap* map = CodeSourceMap::RawCast(object);
|
||||
intptr_t size = CodeSourceMap::UnroundedSize(map);
|
||||
ASSERT(size <= map->Size());
|
||||
memset(reinterpret_cast<void*>(RawObject::ToAddr(map) + size), 0,
|
||||
map->Size() - size);
|
||||
} else if (cid == kStackMapCid) {
|
||||
RawStackMap* map = StackMap::RawCast(object);
|
||||
intptr_t size = StackMap::UnroundedSize(map);
|
||||
ASSERT(size <= map->Size());
|
||||
memset(reinterpret_cast<void*>(RawObject::ToAddr(map) + size), 0,
|
||||
map->Size() - size);
|
||||
} else if (cid == kPcDescriptorsCid) {
|
||||
RawPcDescriptors* desc = PcDescriptors::RawCast(object);
|
||||
intptr_t size = PcDescriptors::UnroundedSize(desc);
|
||||
ASSERT(size <= desc->Size());
|
||||
memset(reinterpret_cast<void*>(RawObject::ToAddr(desc) + size), 0,
|
||||
desc->Size() - size);
|
||||
}
|
||||
}
|
||||
|
||||
void Object::set_vm_isolate_snapshot_object_table(const Array& table) {
|
||||
ASSERT(Isolate::Current() == Dart::vm_isolate());
|
||||
*vm_isolate_snapshot_object_table_ = table.raw();
|
||||
|
|
|
@ -559,6 +559,7 @@ class Object {
|
|||
static void InitOnce(Isolate* isolate);
|
||||
static void FinishInitOnce(Isolate* isolate);
|
||||
static void FinalizeVMIsolate(Isolate* isolate);
|
||||
static void FinalizeReadOnlyObject(RawObject* object);
|
||||
|
||||
// Initialize a new isolate either from a Kernel IR, from source, or from a
|
||||
// snapshot.
|
||||
|
@ -4356,6 +4357,12 @@ class PcDescriptors : public Object {
|
|||
static const intptr_t kBytesPerElement = 1;
|
||||
static const intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
|
||||
|
||||
static intptr_t UnroundedSize(RawPcDescriptors* desc) {
|
||||
return UnroundedSize(desc->ptr()->length_);
|
||||
}
|
||||
static intptr_t UnroundedSize(intptr_t len) {
|
||||
return sizeof(RawPcDescriptors) + len;
|
||||
}
|
||||
static intptr_t InstanceSize() {
|
||||
ASSERT(sizeof(RawPcDescriptors) ==
|
||||
OFFSET_OF_RETURNED_VALUE(RawPcDescriptors, data));
|
||||
|
@ -4363,7 +4370,7 @@ class PcDescriptors : public Object {
|
|||
}
|
||||
static intptr_t InstanceSize(intptr_t len) {
|
||||
ASSERT(0 <= len && len <= kMaxElements);
|
||||
return RoundedAllocationSize(sizeof(RawPcDescriptors) + len);
|
||||
return RoundedAllocationSize(UnroundedSize(len));
|
||||
}
|
||||
|
||||
static RawPcDescriptors* New(GrowableArray<uint8_t>* delta_encoded_data);
|
||||
|
@ -4478,6 +4485,12 @@ class CodeSourceMap : public Object {
|
|||
static const intptr_t kBytesPerElement = 1;
|
||||
static const intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
|
||||
|
||||
static intptr_t UnroundedSize(RawCodeSourceMap* map) {
|
||||
return UnroundedSize(map->ptr()->length_);
|
||||
}
|
||||
static intptr_t UnroundedSize(intptr_t len) {
|
||||
return sizeof(RawCodeSourceMap) + len;
|
||||
}
|
||||
static intptr_t InstanceSize() {
|
||||
ASSERT(sizeof(RawCodeSourceMap) ==
|
||||
OFFSET_OF_RETURNED_VALUE(RawCodeSourceMap, data));
|
||||
|
@ -4485,7 +4498,7 @@ class CodeSourceMap : public Object {
|
|||
}
|
||||
static intptr_t InstanceSize(intptr_t len) {
|
||||
ASSERT(0 <= len && len <= kMaxElements);
|
||||
return RoundedAllocationSize(sizeof(RawCodeSourceMap) + len);
|
||||
return RoundedAllocationSize(UnroundedSize(len));
|
||||
}
|
||||
|
||||
static RawCodeSourceMap* New(intptr_t length);
|
||||
|
@ -4544,15 +4557,20 @@ class StackMap : public Object {
|
|||
|
||||
static const intptr_t kMaxLengthInBytes = kSmiMax;
|
||||
|
||||
static intptr_t UnroundedSize(RawStackMap* map) {
|
||||
return UnroundedSize(map->ptr()->length_);
|
||||
}
|
||||
static intptr_t UnroundedSize(intptr_t len) {
|
||||
// The stackmap payload is in an array of bytes.
|
||||
intptr_t payload_size = Utils::RoundUp(len, kBitsPerByte) / kBitsPerByte;
|
||||
return sizeof(RawStackMap) + payload_size;
|
||||
}
|
||||
static intptr_t InstanceSize() {
|
||||
ASSERT(sizeof(RawStackMap) == OFFSET_OF_RETURNED_VALUE(RawStackMap, data));
|
||||
return 0;
|
||||
}
|
||||
static intptr_t InstanceSize(intptr_t length) {
|
||||
ASSERT(length >= 0);
|
||||
// The stackmap payload is in an array of bytes.
|
||||
intptr_t payload_size = Utils::RoundUp(length, kBitsPerByte) / kBitsPerByte;
|
||||
return RoundedAllocationSize(sizeof(RawStackMap) + payload_size);
|
||||
return RoundedAllocationSize(UnroundedSize(length));
|
||||
}
|
||||
static RawStackMap* New(intptr_t pc_offset,
|
||||
BitmapBuilder* bmap,
|
||||
|
@ -7377,12 +7395,17 @@ class OneByteString : public AllStatic {
|
|||
return OFFSET_OF_RETURNED_VALUE(RawOneByteString, data);
|
||||
}
|
||||
|
||||
static intptr_t UnroundedSize(RawOneByteString* str) {
|
||||
return UnroundedSize(Smi::Value(str->ptr()->length_));
|
||||
}
|
||||
static intptr_t UnroundedSize(intptr_t len) {
|
||||
return sizeof(RawOneByteString) + (len * kBytesPerElement);
|
||||
}
|
||||
static intptr_t InstanceSize() {
|
||||
ASSERT(sizeof(RawOneByteString) ==
|
||||
OFFSET_OF_RETURNED_VALUE(RawOneByteString, data));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static intptr_t InstanceSize(intptr_t len) {
|
||||
ASSERT(sizeof(RawOneByteString) == String::kSizeofRawString);
|
||||
ASSERT(0 <= len && len <= kMaxElements);
|
||||
|
@ -7392,8 +7415,7 @@ class OneByteString : public AllStatic {
|
|||
// memory allocated for the raw string.
|
||||
if (len == 0) return InstanceSize(1);
|
||||
#endif
|
||||
return String::RoundedAllocationSize(sizeof(RawOneByteString) +
|
||||
(len * kBytesPerElement));
|
||||
return String::RoundedAllocationSize(UnroundedSize(len));
|
||||
}
|
||||
|
||||
static RawOneByteString* New(intptr_t len, Heap::Space space);
|
||||
|
@ -7521,12 +7543,17 @@ class TwoByteString : public AllStatic {
|
|||
return OFFSET_OF_RETURNED_VALUE(RawTwoByteString, data);
|
||||
}
|
||||
|
||||
static intptr_t UnroundedSize(RawTwoByteString* str) {
|
||||
return UnroundedSize(Smi::Value(str->ptr()->length_));
|
||||
}
|
||||
static intptr_t UnroundedSize(intptr_t len) {
|
||||
return sizeof(RawTwoByteString) + (len * kBytesPerElement);
|
||||
}
|
||||
static intptr_t InstanceSize() {
|
||||
ASSERT(sizeof(RawTwoByteString) ==
|
||||
OFFSET_OF_RETURNED_VALUE(RawTwoByteString, data));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static intptr_t InstanceSize(intptr_t len) {
|
||||
ASSERT(sizeof(RawTwoByteString) == String::kSizeofRawString);
|
||||
ASSERT(0 <= len && len <= kMaxElements);
|
||||
|
@ -7534,8 +7561,7 @@ class TwoByteString : public AllStatic {
|
|||
// If we don't pad, then the external string object does not fit in the
|
||||
// memory allocated for the raw string.
|
||||
if (len == 0) return InstanceSize(1);
|
||||
return String::RoundedAllocationSize(sizeof(RawTwoByteString) +
|
||||
(len * kBytesPerElement));
|
||||
return String::RoundedAllocationSize(UnroundedSize(len));
|
||||
}
|
||||
|
||||
static RawTwoByteString* New(intptr_t len, Heap::Space space);
|
||||
|
|
Loading…
Reference in a new issue