Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1166)

Unified Diff: runtime/vm/object.cc

Issue 2912863006: Inline instance object hash code into object header on 64 bit. (Closed)
Patch Set: Add assembler tests and other feedback from Ryan Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/profiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2c6422e7d0e5d68d8799ed3ba5034b6b3bc99174..073514a4b1362b3220da0381e63129c4a86aa9b1 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -992,10 +992,12 @@ void Object::InitOnce(Isolate* isolate) {
// An object visitor which will mark all visited objects. This is used to
-// premark all objects in the vm_isolate_ heap.
-class PremarkingVisitor : public ObjectVisitor {
+// premark all objects in the vm_isolate_ heap. Also precalculates hash
+// codes so that we can get the identity hash code of objects in the read-
+// only VM isolate.
+class FinalizeVMIsolateVisitor : public ObjectVisitor {
public:
- PremarkingVisitor() {}
+ FinalizeVMIsolateVisitor() : counter_(1337) {}
void VisitObject(RawObject* obj) {
// Free list elements should never be marked.
@@ -1005,8 +1007,33 @@ class PremarkingVisitor : 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);
+ }
+#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
+ // codes, since we can't add hash codes later.
+ if (Object::GetCachedHash(obj) == 0) {
+ // Some classes have identity hash codes that depend on their contents,
+ // not per object.
+ ASSERT(!obj->IsStringInstance());
+ if (!obj->IsMint() && !obj->IsDouble() && !obj->IsBigint() &&
+ !obj->IsRawNull() && !obj->IsBool()) {
+ counter_ += 2011; // The year Dart was announced and a prime.
+ counter_ &= 0x3fffffff;
+ if (counter_ == 0) counter_++;
+ Object::SetCachedHash(obj, counter_);
+ }
+ }
+#endif
}
}
+
+ private:
+ int counter_;
};
@@ -1086,7 +1113,7 @@ void Object::FinalizeVMIsolate(Isolate* isolate) {
{
ASSERT(isolate == Dart::vm_isolate());
WritableVMIsolateScope scope(Thread::Current());
- PremarkingVisitor premarker;
+ FinalizeVMIsolateVisitor premarker;
ASSERT(isolate->heap()->UsedInWords(Heap::kNew) == 0);
isolate->heap()->IterateOldObjectsNoImagePages(&premarker);
// Make the VM isolate read-only again after setting all objects as marked.
@@ -1121,13 +1148,15 @@ void Object::MakeUnusedSpaceTraversable(const Object& obj,
reinterpret_cast<RawTypedData*>(RawObject::FromAddr(addr));
uword new_tags = RawObject::ClassIdTag::update(kTypedDataInt8ArrayCid, 0);
new_tags = RawObject::SizeTag::update(leftover_size, new_tags);
- uword tags = raw->ptr()->tags_;
- uword old_tags;
+ uint32_t tags = raw->ptr()->tags_;
+ uint32_t old_tags;
// TODO(iposva): Investigate whether CompareAndSwapWord is necessary.
do {
old_tags = tags;
- tags = AtomicOperations::CompareAndSwapWord(&raw->ptr()->tags_,
- old_tags, new_tags);
+ // We can't use obj.CompareAndSwapTags here because we don't have a
+ // handle for the new object.
+ tags = AtomicOperations::CompareAndSwapUint32(&raw->ptr()->tags_,
+ old_tags, new_tags);
} while (tags != old_tags);
intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0));
@@ -1139,13 +1168,12 @@ void Object::MakeUnusedSpaceTraversable(const Object& obj,
RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
uword new_tags = RawObject::ClassIdTag::update(kInstanceCid, 0);
new_tags = RawObject::SizeTag::update(leftover_size, new_tags);
- uword tags = raw->ptr()->tags_;
- uword old_tags;
+ uint32_t tags = raw->ptr()->tags_;
+ uint32_t old_tags;
// TODO(iposva): Investigate whether CompareAndSwapWord is necessary.
do {
old_tags = tags;
- tags = AtomicOperations::CompareAndSwapWord(&raw->ptr()->tags_,
- old_tags, new_tags);
+ tags = obj.CompareAndSwapTags(old_tags, new_tags);
} while (tags != old_tags);
}
}
@@ -1867,12 +1895,15 @@ void Object::InitializeObject(uword address,
*reinterpret_cast<uword*>(cur) = initial_value;
cur += kWordSize;
}
- uword tags = 0;
+ uint32_t tags = 0;
ASSERT(class_id != kIllegalCid);
tags = RawObject::ClassIdTag::update(class_id, tags);
tags = RawObject::SizeTag::update(size, tags);
tags = RawObject::VMHeapObjectTag::update(is_vm_object, tags);
reinterpret_cast<RawObject*>(address)->tags_ = tags;
+#if defined(HASH_IN_OBJECT_HEADER)
+ reinterpret_cast<RawObject*>(address)->hash_ = 0;
+#endif
ASSERT(is_vm_object == RawObject::IsVMHeapObject(tags));
}
@@ -20207,6 +20238,35 @@ static intptr_t HashImpl(const T* characters, intptr_t len) {
}
+intptr_t String::Hash(RawString* raw) {
+ StringHasher hasher;
+ uword length = Smi::Value(raw->ptr()->length_);
+ if (raw->IsOneByteString() || raw->IsExternalOneByteString()) {
+ const uint8_t* data;
+ if (raw->IsOneByteString()) {
+ data = reinterpret_cast<RawOneByteString*>(raw)->ptr()->data();
+ } else {
+ ASSERT(raw->IsExternalOneByteString());
+ RawExternalOneByteString* str =
+ reinterpret_cast<RawExternalOneByteString*>(raw);
+ data = str->ptr()->external_data_->data();
+ }
+ return String::Hash(data, length);
+ } else {
+ const uint16_t* data;
+ if (raw->IsTwoByteString()) {
+ data = reinterpret_cast<RawTwoByteString*>(raw)->ptr()->data();
+ } else {
+ ASSERT(raw->IsExternalTwoByteString());
+ RawExternalTwoByteString* str =
+ reinterpret_cast<RawExternalTwoByteString*>(raw);
+ data = str->ptr()->external_data_->data();
+ }
+ return String::Hash(data, length);
+ }
+}
+
+
intptr_t String::Hash(const char* characters, intptr_t len) {
return HashImpl(characters, len);
}
@@ -21027,11 +21087,11 @@ RawString* String::MakeExternal(void* array,
// Update the class information of the object.
const intptr_t class_id = kExternalOneByteStringCid;
- uword tags = raw_ptr()->tags_;
- uword old_tags;
+ uint32_t tags = raw_ptr()->tags_;
+ uint32_t old_tags;
do {
old_tags = tags;
- uword new_tags = RawObject::SizeTag::update(used_size, old_tags);
+ uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags);
new_tags = RawObject::ClassIdTag::update(class_id, new_tags);
tags = CompareAndSwapTags(old_tags, new_tags);
} while (tags != old_tags);
@@ -21064,11 +21124,11 @@ RawString* String::MakeExternal(void* array,
// Update the class information of the object.
const intptr_t class_id = kExternalTwoByteStringCid;
- uword tags = raw_ptr()->tags_;
- uword old_tags;
+ uint32_t tags = raw_ptr()->tags_;
+ uint32_t old_tags;
do {
old_tags = tags;
- uword new_tags = RawObject::SizeTag::update(used_size, old_tags);
+ uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags);
new_tags = RawObject::ClassIdTag::update(class_id, new_tags);
tags = CompareAndSwapTags(old_tags, new_tags);
} while (tags != old_tags);
@@ -21956,11 +22016,11 @@ void Array::MakeImmutable() const {
if (IsImmutable()) return;
ASSERT(!IsCanonical());
NoSafepointScope no_safepoint;
- uword tags = raw_ptr()->tags_;
- uword old_tags;
+ uint32_t tags = raw_ptr()->tags_;
+ uint32_t old_tags;
do {
old_tags = tags;
- uword new_tags =
+ uint32_t new_tags =
RawObject::ClassIdTag::update(kImmutableArrayCid, old_tags);
tags = CompareAndSwapTags(old_tags, new_tags);
} while (tags != old_tags);
@@ -22002,6 +22062,7 @@ RawArray* Array::Grow(const Array& source,
RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
ASSERT(!growable_array.IsNull());
+ ASSERT(growable_array.IsGrowableObjectArray());
intptr_t used_len = growable_array.Length();
// Get the type arguments and prepare to copy them.
const TypeArguments& type_arguments =
@@ -22014,6 +22075,7 @@ RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
intptr_t capacity_len = growable_array.Capacity();
Zone* zone = Thread::Current()->zone();
const Array& array = Array::Handle(zone, growable_array.data());
+ ASSERT(array.IsArray());
array.SetTypeArguments(type_arguments);
intptr_t capacity_size = Array::InstanceSize(capacity_len);
intptr_t used_size = Array::InstanceSize(used_len);
@@ -22027,10 +22089,10 @@ RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
// Update the size in the header field and length of the array object.
uword tags = array.raw_ptr()->tags_;
ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags));
- uword old_tags;
+ uint32_t old_tags;
do {
old_tags = tags;
- uword new_tags = RawObject::SizeTag::update(used_size, old_tags);
+ uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags);
tags = array.CompareAndSwapTags(old_tags, new_tags);
} while (tags != old_tags);
// TODO(22501): For the heap to remain walkable by the sweeper, it must
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698