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

Unified Diff: runtime/vm/object.cc

Issue 1754813004: Add thread safe constant canonicalization. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: c Created 4 years, 10 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 0c959cd387390bde40cf85246db640950a0f51b3..28c9aaf91a141b60bdc2e5144e81734108c996f0 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4217,6 +4217,104 @@ const char* Class::ToCString() const {
}
+// Returns an instance of Double or Double::null().
+// 'index' points to either:
+// - constants_list_ position of found element, or
+// - constants_list_ position where new canonical can be inserted.
+RawDouble* Class::LookupCanonicalDouble(
+ Zone* zone, double value, intptr_t* index) const {
+ ASSERT(this->raw() == Isolate::Current()->object_store()->double_class());
+ const Array& constants = Array::Handle(zone, this->constants());
+ const intptr_t constants_len = constants.Length();
+ // Linear search to see whether this value is already present in the
+ // list of canonicalized constants.
+ Double& canonical_value = Double::Handle(zone);
+ while (*index < constants_len) {
+ canonical_value ^= constants.At(*index);
+ if (canonical_value.IsNull()) {
+ break;
+ }
+ if (canonical_value.BitwiseEqualsToDouble(value)) {
+ ASSERT(canonical_value.IsCanonical());
+ return canonical_value.raw();
+ }
+ *index = *index + 1;
+ }
+ return Double::null();
+}
+
+
+RawMint* Class::LookupCanonicalMint(
+ Zone* zone, int64_t value, intptr_t* index) const {
+ ASSERT(this->raw() == Isolate::Current()->object_store()->mint_class());
+ const Array& constants = Array::Handle(zone, this->constants());
+ const intptr_t constants_len = constants.Length();
+ // Linear search to see whether this value is already present in the
+ // list of canonicalized constants.
+ Mint& canonical_value = Mint::Handle(zone);
+ while (*index < constants_len) {
+ canonical_value ^= constants.At(*index);
+ if (canonical_value.IsNull()) {
+ break;
+ }
+ if (canonical_value.value() == value) {
+ ASSERT(canonical_value.IsCanonical());
+ return canonical_value.raw();
+ }
+ *index = *index + 1;
+ }
+ return Mint::null();
+}
+
+
+RawBigint* Class::LookupCanonicalBigint(Zone* zone,
+ const Bigint& value,
+ intptr_t* index) const {
+ ASSERT(this->raw() == Isolate::Current()->object_store()->bigint_class());
+ const Array& constants = Array::Handle(zone, this->constants());
+ const intptr_t constants_len = constants.Length();
+ // Linear search to see whether this value is already present in the
+ // list of canonicalized constants.
+ Bigint& canonical_value = Bigint::Handle(zone);
+ while (*index < constants_len) {
+ canonical_value ^= constants.At(*index);
+ if (canonical_value.IsNull()) {
+ break;
+ }
+ if (canonical_value.Equals(value)) {
+ ASSERT(canonical_value.IsCanonical());
+ return canonical_value.raw();
+ }
+ *index = *index + 1;
+ }
+ return Bigint::null();
+}
+
+
+RawInstance* Class::LookupCanonicalInstance(Zone* zone,
+ const Instance& value,
+ intptr_t* index) const {
+ ASSERT(this->raw() == value.clazz());
+ const Array& constants = Array::Handle(zone, this->constants());
+ const intptr_t constants_len = constants.Length();
+ // Linear search to see whether this value is already present in the
+ // list of canonicalized constants.
+ Instance& canonical_value = Instance::Handle(zone);
+ while (*index < constants_len) {
+ canonical_value ^= constants.At(*index);
+ if (canonical_value.IsNull()) {
+ break;
+ }
+ if (value.CanonicalizeEquals(canonical_value)) {
+ ASSERT(canonical_value.IsCanonical());
+ return canonical_value.raw();
+ }
+ *index = *index + 1;
+ }
+ return Instance::null();
+}
+
+
void Class::InsertCanonicalConstant(intptr_t index,
const Instance& constant) const {
// The constant needs to be added to the list. Grow the list if it is full.
@@ -14356,21 +14454,10 @@ RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const {
Isolate* isolate = thread->isolate();
Instance& result = Instance::Handle(zone);
const Class& cls = Class::Handle(zone, this->clazz());
- Array& constants = Array::Handle(zone, cls.constants());
- const intptr_t constants_len = constants.Length();
- // Linear search to see whether this value is already present in the
- // list of canonicalized constants.
intptr_t index = 0;
- while (index < constants_len) {
- result ^= constants.At(index);
- if (result.IsNull()) {
- break;
- }
- if (this->CanonicalizeEquals(result)) {
- ASSERT(result.IsCanonical());
- return result.raw();
- }
- index++;
+ 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.
@@ -14396,9 +14483,20 @@ RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const {
result ^= Object::Clone(result, Heap::kOld);
}
siva 2016/03/02 19:12:07 As discussed offline this piece of code could move
ASSERT(result.IsOld());
- cls.InsertCanonicalConstant(index, result);
- result.SetCanonical();
- return result.raw();
+ {
+ 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.SetCanonical();
+ cls.InsertCanonicalConstant(index, result);
+ return result.raw();
+ }
}
@@ -17603,31 +17701,33 @@ RawMint* Mint::New(int64_t val, Heap::Space space) {
RawMint* Mint::NewCanonical(int64_t value) {
// Do not allocate a Mint if Smi would do.
ASSERT(!Smi::IsValid(value));
- const Class& cls =
- Class::Handle(Isolate::Current()->object_store()->mint_class());
- const Array& constants = Array::Handle(cls.constants());
- const intptr_t constants_len = constants.Length();
- // Linear search to see whether this value is already present in the
- // list of canonicalized constants.
- Mint& canonical_value = Mint::Handle();
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ Isolate* isolate = thread->isolate();
+ const Class& cls = Class::Handle(zone, isolate->object_store()->mint_class());
+ Mint& canonical_value = Mint::Handle(zone);
intptr_t index = 0;
- while (index < constants_len) {
- canonical_value ^= constants.At(index);
- if (canonical_value.IsNull()) {
- break;
- }
- if (canonical_value.value() == value) {
- ASSERT(canonical_value.IsCanonical());
- return canonical_value.raw();
- }
- index++;
+ canonical_value ^= cls.LookupCanonicalMint(zone, value, &index);
+ if (!canonical_value.IsNull()) {
+ return canonical_value.raw();
}
- // The value needs to be added to the constants list. Grow the list if
- // it is full.
canonical_value = Mint::New(value, Heap::kOld);
- cls.InsertCanonicalConstant(index, canonical_value);
- canonical_value.SetCanonical();
- return canonical_value.raw();
+ {
+ 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.SetCanonical();
+ // The value needs to be added to the constants list. Grow the list if
+ // it is full.
+ cls.InsertCanonicalConstant(index, canonical_value);
+ return canonical_value.raw();
+ }
}
@@ -17751,30 +17851,36 @@ RawDouble* Double::New(const String& str, Heap::Space space) {
RawDouble* Double::NewCanonical(double value) {
- const Class& cls =
- Class::Handle(Isolate::Current()->object_store()->double_class());
- const Array& constants = Array::Handle(cls.constants());
- const intptr_t constants_len = constants.Length();
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ Isolate* isolate = thread->isolate();
+ const Class& cls = Class::Handle(isolate->object_store()->double_class());
// Linear search to see whether this value is already present in the
// list of canonicalized constants.
- Double& canonical_value = Double::Handle();
+ Double& canonical_value = Double::Handle(zone);
intptr_t index = 0;
- while (index < constants_len) {
- canonical_value ^= constants.At(index);
- if (canonical_value.IsNull()) {
- break;
- }
- if (canonical_value.BitwiseEqualsToDouble(value)) {
- return canonical_value.raw();
- }
- index++;
+
+ canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index);
+ if (!canonical_value.IsNull()) {
+ return canonical_value.raw();
}
- // The value needs to be added to the constants list. Grow the list if
- // it is full.
canonical_value = Double::New(value, Heap::kOld);
- cls.InsertCanonicalConstant(index, canonical_value);
- canonical_value.SetCanonical();
- return canonical_value.raw();
+ {
+ 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.SetCanonical();
+ // The value needs to be added to the constants list. Grow the list if
+ // it is full.
+ cls.InsertCanonicalConstant(index, canonical_value);
+ return canonical_value.raw();
+ }
}
@@ -18055,31 +18161,35 @@ RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) {
RawBigint* Bigint::NewCanonical(const String& str) {
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ Isolate* isolate = thread->isolate();
const Bigint& value = Bigint::Handle(
- Bigint::NewFromCString(str.ToCString(), Heap::kOld));
+ zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld));
const Class& cls =
- Class::Handle(Isolate::Current()->object_store()->bigint_class());
- const Array& constants = Array::Handle(cls.constants());
- const intptr_t constants_len = constants.Length();
- // Linear search to see whether this value is already present in the
- // list of canonicalized constants.
- Bigint& canonical_value = Bigint::Handle();
+ Class::Handle(zone, isolate->object_store()->bigint_class());
intptr_t index = 0;
- while (index < constants_len) {
- canonical_value ^= constants.At(index);
- if (canonical_value.IsNull()) {
- break;
- }
- if (canonical_value.Equals(value)) {
- return canonical_value.raw();
+ const Bigint& canonical_value =
+ Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index));
+ if (!canonical_value.IsNull()) {
+ return canonical_value.raw();
+ }
+ {
+ 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();
+ }
}
- index++;
+ value.SetCanonical();
+ // The value needs to be added to the constants list. Grow the list if
+ // it is full.
+ cls.InsertCanonicalConstant(index, value);
+ return value.raw();
}
- // The value needs to be added to the constants list. Grow the list if
- // it is full.
- cls.InsertCanonicalConstant(index, value);
- value.SetCanonical();
- return value.raw();
}
« 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