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

Unified Diff: runtime/vm/object.cc

Issue 1866713003: - Restructure the Canonicalization of instances in preparation for adding a (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code-review-comments Created 4 years, 8 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') | no next file » | 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 44e9d23312d593d64b356ef300bad1de9e43d571..63389b6a446460fbc94232abd70b83b507bb23a1 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4399,6 +4399,21 @@ void Class::InsertCanonicalConstant(intptr_t index,
}
+void Class::InsertCanonicalNumber(Zone* zone,
+ intptr_t index,
+ const Number& constant) const {
+ // The constant needs to be added to the list. Grow the list if it is full.
+ Array& canonical_list = Array::Handle(zone, constants());
+ const intptr_t list_len = canonical_list.Length();
+ if (index >= list_len) {
+ const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4;
+ canonical_list ^= Array::Grow(canonical_list, new_length, Heap::kOld);
+ set_constants(canonical_list);
+ }
+ canonical_list.SetAt(index, constant);
+}
+
+
RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix,
const String& ident,
TokenPosition token_pos) {
@@ -14654,12 +14669,13 @@ class CheckForPointers : public ObjectPointerVisitor {
#endif // DEBUG
-bool Instance::CheckAndCanonicalizeFields(const char** error_str) const {
- const Class& cls = Class::Handle(this->clazz());
+bool Instance::CheckAndCanonicalizeFields(Zone* zone,
+ const char** error_str) const {
+ const Class& cls = Class::Handle(zone, this->clazz());
if (cls.id() >= kNumPredefinedCids) {
// Iterate over all fields, canonicalize numbers and strings, expect all
// other instances to be canonical otherwise report error (return false).
- Object& obj = Object::Handle();
+ Object& obj = Object::Handle(zone);
intptr_t end_field_offset = cls.instance_size() - kWordSize;
for (intptr_t field_offset = 0;
field_offset <= end_field_offset;
@@ -14672,8 +14688,7 @@ bool Instance::CheckAndCanonicalizeFields(const char** error_str) const {
this->SetFieldAtOffset(field_offset, obj);
} else {
ASSERT(error_str != NULL);
- char* chars = OS::SCreate(Thread::Current()->zone(),
- "field: %s\n", obj.ToCString());
+ char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString());
*error_str = chars;
return false;
}
@@ -14696,11 +14711,11 @@ RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const {
if (this->IsCanonical()) {
return this->raw();
}
- if (!CheckAndCanonicalizeFields(error_str)) {
- return Instance::null();
- }
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
+ if (!CheckAndCanonicalizeFields(zone, error_str)) {
+ return Instance::null();
+ }
Isolate* isolate = thread->isolate();
Instance& result = Instance::Handle(zone);
const Class& cls = Class::Handle(zone, this->clazz());
@@ -14713,38 +14728,21 @@ RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const {
SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
// Retry lookup.
{
- Instance& temp_result = Instance::Handle(zone,
- cls.LookupCanonicalInstance(zone, *this, &index));
- if (!temp_result.IsNull()) {
- return temp_result.raw();
+ result ^= cls.LookupCanonicalInstance(zone, *this, &index);
+ if (!result.IsNull()) {
+ return result.raw();
}
}
// The value needs to be added to the list. Grow the list if
// it is full.
result ^= this->raw();
- if (result.IsNew() ||
- (result.InVMHeap() && (isolate != Dart::vm_isolate()))) {
- /**
- * When a snapshot is generated on a 64 bit architecture and then read
- * into a 32 bit architecture, values which are Smi on the 64 bit
- * architecture could potentially be converted to Mint objects, however
- * since Smi values do not have any notion of canonical bits we lose
- * that information when the object becomes a Mint.
- * Some of these values could be literal values and end up in the
- * VM isolate heap. Later when these values are referenced in a
- * constant list we try to ensure that all the objects in the list
- * are canonical and try to canonicalize them. When these Mint objects
- * are encountered they do not have the canonical bit set and
- * canonicalizing them won't work as the VM heap is read only now.
- * In these cases we clone the object into the isolate and then
- * canonicalize it.
- */
+ ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap());
+ if (result.IsNew()) {
// Create a canonical object in old space.
result ^= Object::Clone(result, Heap::kOld);
}
ASSERT(result.IsOld());
-
result.SetCanonical();
cls.InsertCanonicalConstant(index, result);
return result.raw();
@@ -14956,7 +14954,8 @@ bool Instance::IsIdenticalTo(const Instance& other) const {
return Integer::Cast(*this).Equals(other);
}
if (IsDouble() && other.IsDouble()) {
- return Double::Cast(*this).CanonicalizeEquals(other);
+ double other_value = Double::Cast(other).value();
+ return Double::Cast(*this).BitwiseEqualsToDouble(other_value);
}
return false;
}
@@ -17360,6 +17359,61 @@ RawMixinAppType* MixinAppType::New(const AbstractType& super_type,
}
+RawInstance* Number::CheckAndCanonicalize(const char** error_str) const {
+ intptr_t cid = GetClassId();
+ switch (cid) {
+ case kSmiCid:
+ return reinterpret_cast<RawSmi*>(raw_value());
+ case kMintCid:
+ return Mint::NewCanonical(Mint::Cast(*this).value());
+ case kDoubleCid:
+ return Double::NewCanonical(Double::Cast(*this).value());
+ case kBigintCid: {
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ Isolate* isolate = thread->isolate();
+ if (!CheckAndCanonicalizeFields(zone, error_str)) {
+ return Instance::null();
+ }
+ Bigint& result = Bigint::Handle(zone);
+ const Class& cls = Class::Handle(zone, this->clazz());
+ intptr_t index = 0;
+ result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index);
+ if (!result.IsNull()) {
+ return result.raw();
+ }
+ {
+ SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
+ // Retry lookup.
+ {
+ result ^= cls.LookupCanonicalBigint(
+ zone, Bigint::Cast(*this), &index);
+ if (!result.IsNull()) {
+ return result.raw();
+ }
+ }
+
+ // The value needs to be added to the list. Grow the list if
+ // it is full.
+ result ^= this->raw();
+ ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap());
+ if (result.IsNew()) {
+ // Create a canonical object in old space.
+ result ^= Object::Clone(result, Heap::kOld);
+ }
+ ASSERT(result.IsOld());
+ result.SetCanonical();
+ cls.InsertCanonicalNumber(zone, index, result);
+ return result.raw();
+ }
+ }
+ default:
+ UNREACHABLE();
+ }
+ return Instance::null();
+}
+
+
const char* Number::ToCString() const {
// Number is an interface. No instances of Number should exist.
UNREACHABLE();
@@ -17783,17 +17837,16 @@ RawMint* Mint::NewCanonical(int64_t value) {
SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
// Retry lookup.
{
- const Mint& result =
- Mint::Handle(zone, cls.LookupCanonicalMint(zone, value, &index));
- if (!result.IsNull()) {
- return result.raw();
+ canonical_value ^= cls.LookupCanonicalMint(zone, value, &index);
+ if (!canonical_value.IsNull()) {
+ return canonical_value.raw();
}
}
canonical_value = Mint::New(value, Heap::kOld);
canonical_value.SetCanonical();
// The value needs to be added to the constants list. Grow the list if
// it is full.
- cls.InsertCanonicalConstant(index, canonical_value);
+ cls.InsertCanonicalNumber(zone, index, canonical_value);
return canonical_value.raw();
}
}
@@ -17936,17 +17989,16 @@ RawDouble* Double::NewCanonical(double value) {
SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
// Retry lookup.
{
- const Double& result =
- Double::Handle(zone, cls.LookupCanonicalDouble(zone, value, &index));
- if (!result.IsNull()) {
- return result.raw();
+ canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index);
+ if (!canonical_value.IsNull()) {
+ return canonical_value.raw();
}
}
canonical_value = Double::New(value, Heap::kOld);
canonical_value.SetCanonical();
// The value needs to be added to the constants list. Grow the list if
// it is full.
- cls.InsertCanonicalConstant(index, canonical_value);
+ cls.InsertCanonicalNumber(zone, index, canonical_value);
return canonical_value.raw();
}
}
@@ -18073,13 +18125,14 @@ bool Bigint::Equals(const Instance& other) const {
}
-bool Bigint::CheckAndCanonicalizeFields(const char** error_str) const {
+bool Bigint::CheckAndCanonicalizeFields(Zone* zone,
+ const char** error_str) const {
// Bool field neg should always be canonical.
- ASSERT(Bool::Handle(neg()).IsCanonical());
+ ASSERT(Bool::Handle(zone, neg()).IsCanonical());
// Smi field used is canonical by definition.
if (Used() > 0) {
// Canonicalize TypedData field digits.
- TypedData& digits_ = TypedData::Handle(digits());
+ TypedData& digits_ = TypedData::Handle(zone, digits());
digits_ ^= digits_.CheckAndCanonicalize(NULL);
ASSERT(!digits_.IsNull());
set_digits(digits_);
@@ -18237,8 +18290,8 @@ RawBigint* Bigint::NewCanonical(const String& str) {
const Class& cls =
Class::Handle(zone, isolate->object_store()->bigint_class());
intptr_t index = 0;
- const Bigint& canonical_value =
- Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index));
+ Bigint& canonical_value = Bigint::Handle(zone);
+ canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index);
if (!canonical_value.IsNull()) {
return canonical_value.raw();
}
@@ -18246,16 +18299,15 @@ RawBigint* Bigint::NewCanonical(const String& str) {
SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
// Retry lookup.
{
- const Bigint& result =
- Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index));
- if (!result.IsNull()) {
- return result.raw();
+ canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index);
+ if (!canonical_value.IsNull()) {
+ return canonical_value.raw();
}
}
value.SetCanonical();
// The value needs to be added to the constants list. Grow the list if
// it is full.
- cls.InsertCanonicalConstant(index, value);
+ cls.InsertCanonicalNumber(zone, index, value);
return value.raw();
}
}
@@ -20494,14 +20546,7 @@ bool Array::CanonicalizeEquals(const Instance& other) const {
return false;
}
- // Both arrays must have the same type arguments.
- const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
- const TypeArguments& other_type_args = TypeArguments::Handle(
- other.GetTypeArguments());
- if (!type_args.Equals(other_type_args)) {
- return false;
- }
-
+ // First check if both arrays have the same length and elements.
const Array& other_arr = Array::Cast(other);
intptr_t len = this->Length();
@@ -20514,6 +20559,14 @@ bool Array::CanonicalizeEquals(const Instance& other) const {
return false;
}
}
+
+ // Now check if both arrays have the same type arguments.
+ const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
+ const TypeArguments& other_type_args = TypeArguments::Handle(
+ other.GetTypeArguments());
+ if (!type_args.Equals(other_type_args)) {
+ return false;
+ }
return true;
}
@@ -20659,8 +20712,9 @@ RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
}
-bool Array::CheckAndCanonicalizeFields(const char** error_str) const {
- Object& obj = Object::Handle();
+bool Array::CheckAndCanonicalizeFields(Zone* zone,
+ const char** error_str) const {
+ Object& obj = Object::Handle(zone);
// Iterate over all elements, canonicalize numbers and strings, expect all
// other instances to be canonical otherwise report error (return false).
for (intptr_t i = 0; i < Length(); i++) {
@@ -20730,44 +20784,6 @@ RawObject* GrowableObjectArray::RemoveLast() const {
}
-bool GrowableObjectArray::CanonicalizeEquals(const Instance& other) const {
- // If both handles point to the same raw instance they are equal.
- if (this->raw() == other.raw()) {
- return true;
- }
-
- // Other instance must be non null and a GrowableObjectArray.
- if (!other.IsGrowableObjectArray() || other.IsNull()) {
- return false;
- }
-
- const GrowableObjectArray& other_arr = GrowableObjectArray::Cast(other);
-
- // The capacity and length of both objects must be equal.
- if (Capacity() != other_arr.Capacity() || Length() != other_arr.Length()) {
- return false;
- }
-
- // Both arrays must have the same type arguments.
- const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
- const TypeArguments& other_type_args = TypeArguments::Handle(
- other.GetTypeArguments());
- if (!type_args.Equals(other_type_args)) {
- return false;
- }
-
- // The data part in both arrays must be identical.
- const Array& contents = Array::Handle(data());
- const Array& other_contents = Array::Handle(other_arr.data());
- for (intptr_t i = 0; i < Length(); i++) {
- if (contents.At(i) != other_contents.At(i)) {
- return false;
- }
- }
- return true;
-}
-
-
RawGrowableObjectArray* GrowableObjectArray::New(intptr_t capacity,
Heap::Space space) {
const Array& data = Array::Handle(Array::New(capacity, space));
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698