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

Side by Side 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, 9 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 unified diff | Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 4199 matching lines...) Expand 10 before | Expand all | Expand 10 after
4210 const char* Class::ToCString() const { 4210 const char* Class::ToCString() const {
4211 const Library& lib = Library::Handle(library()); 4211 const Library& lib = Library::Handle(library());
4212 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); 4212 const char* library_name = lib.IsNull() ? "" : lib.ToCString();
4213 const char* patch_prefix = is_patch() ? "Patch " : ""; 4213 const char* patch_prefix = is_patch() ? "Patch " : "";
4214 const char* class_name = String::Handle(Name()).ToCString(); 4214 const char* class_name = String::Handle(Name()).ToCString();
4215 return OS::SCreate(Thread::Current()->zone(), 4215 return OS::SCreate(Thread::Current()->zone(),
4216 "%s %sClass: %s", library_name, patch_prefix, class_name); 4216 "%s %sClass: %s", library_name, patch_prefix, class_name);
4217 } 4217 }
4218 4218
4219 4219
4220 // Returns an instance of Double or Double::null().
4221 // 'index' points to either:
4222 // - constants_list_ position of found element, or
4223 // - constants_list_ position where new canonical can be inserted.
4224 RawDouble* Class::LookupCanonicalDouble(
4225 Zone* zone, double value, intptr_t* index) const {
4226 ASSERT(this->raw() == Isolate::Current()->object_store()->double_class());
4227 const Array& constants = Array::Handle(zone, this->constants());
4228 const intptr_t constants_len = constants.Length();
4229 // Linear search to see whether this value is already present in the
4230 // list of canonicalized constants.
4231 Double& canonical_value = Double::Handle(zone);
4232 while (*index < constants_len) {
4233 canonical_value ^= constants.At(*index);
4234 if (canonical_value.IsNull()) {
4235 break;
4236 }
4237 if (canonical_value.BitwiseEqualsToDouble(value)) {
4238 ASSERT(canonical_value.IsCanonical());
4239 return canonical_value.raw();
4240 }
4241 *index = *index + 1;
4242 }
4243 return Double::null();
4244 }
4245
4246
4247 RawMint* Class::LookupCanonicalMint(
4248 Zone* zone, int64_t value, intptr_t* index) const {
4249 ASSERT(this->raw() == Isolate::Current()->object_store()->mint_class());
4250 const Array& constants = Array::Handle(zone, this->constants());
4251 const intptr_t constants_len = constants.Length();
4252 // Linear search to see whether this value is already present in the
4253 // list of canonicalized constants.
4254 Mint& canonical_value = Mint::Handle(zone);
4255 while (*index < constants_len) {
4256 canonical_value ^= constants.At(*index);
4257 if (canonical_value.IsNull()) {
4258 break;
4259 }
4260 if (canonical_value.value() == value) {
4261 ASSERT(canonical_value.IsCanonical());
4262 return canonical_value.raw();
4263 }
4264 *index = *index + 1;
4265 }
4266 return Mint::null();
4267 }
4268
4269
4270 RawBigint* Class::LookupCanonicalBigint(Zone* zone,
4271 const Bigint& value,
4272 intptr_t* index) const {
4273 ASSERT(this->raw() == Isolate::Current()->object_store()->bigint_class());
4274 const Array& constants = Array::Handle(zone, this->constants());
4275 const intptr_t constants_len = constants.Length();
4276 // Linear search to see whether this value is already present in the
4277 // list of canonicalized constants.
4278 Bigint& canonical_value = Bigint::Handle(zone);
4279 while (*index < constants_len) {
4280 canonical_value ^= constants.At(*index);
4281 if (canonical_value.IsNull()) {
4282 break;
4283 }
4284 if (canonical_value.Equals(value)) {
4285 ASSERT(canonical_value.IsCanonical());
4286 return canonical_value.raw();
4287 }
4288 *index = *index + 1;
4289 }
4290 return Bigint::null();
4291 }
4292
4293
4294 RawInstance* Class::LookupCanonicalInstance(Zone* zone,
4295 const Instance& value,
4296 intptr_t* index) const {
4297 ASSERT(this->raw() == value.clazz());
4298 const Array& constants = Array::Handle(zone, this->constants());
4299 const intptr_t constants_len = constants.Length();
4300 // Linear search to see whether this value is already present in the
4301 // list of canonicalized constants.
4302 Instance& canonical_value = Instance::Handle(zone);
4303 while (*index < constants_len) {
4304 canonical_value ^= constants.At(*index);
4305 if (canonical_value.IsNull()) {
4306 break;
4307 }
4308 if (value.CanonicalizeEquals(canonical_value)) {
4309 ASSERT(canonical_value.IsCanonical());
4310 return canonical_value.raw();
4311 }
4312 *index = *index + 1;
4313 }
4314 return Instance::null();
4315 }
4316
4317
4220 void Class::InsertCanonicalConstant(intptr_t index, 4318 void Class::InsertCanonicalConstant(intptr_t index,
4221 const Instance& constant) const { 4319 const Instance& constant) const {
4222 // The constant needs to be added to the list. Grow the list if it is full. 4320 // The constant needs to be added to the list. Grow the list if it is full.
4223 Array& canonical_list = Array::Handle(constants()); 4321 Array& canonical_list = Array::Handle(constants());
4224 const intptr_t list_len = canonical_list.Length(); 4322 const intptr_t list_len = canonical_list.Length();
4225 if (index >= list_len) { 4323 if (index >= list_len) {
4226 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; 4324 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4;
4227 const Array& new_canonical_list = 4325 const Array& new_canonical_list =
4228 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld)); 4326 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld));
4229 set_constants(new_canonical_list); 4327 set_constants(new_canonical_list);
(...skipping 10119 matching lines...) Expand 10 before | Expand all | Expand 10 after
14349 return this->raw(); 14447 return this->raw();
14350 } 14448 }
14351 if (!CheckAndCanonicalizeFields(error_str)) { 14449 if (!CheckAndCanonicalizeFields(error_str)) {
14352 return Instance::null(); 14450 return Instance::null();
14353 } 14451 }
14354 Thread* thread = Thread::Current(); 14452 Thread* thread = Thread::Current();
14355 Zone* zone = thread->zone(); 14453 Zone* zone = thread->zone();
14356 Isolate* isolate = thread->isolate(); 14454 Isolate* isolate = thread->isolate();
14357 Instance& result = Instance::Handle(zone); 14455 Instance& result = Instance::Handle(zone);
14358 const Class& cls = Class::Handle(zone, this->clazz()); 14456 const Class& cls = Class::Handle(zone, this->clazz());
14359 Array& constants = Array::Handle(zone, cls.constants());
14360 const intptr_t constants_len = constants.Length();
14361 // Linear search to see whether this value is already present in the
14362 // list of canonicalized constants.
14363 intptr_t index = 0; 14457 intptr_t index = 0;
14364 while (index < constants_len) { 14458 result ^= cls.LookupCanonicalInstance(zone, *this, &index);
14365 result ^= constants.At(index); 14459 if (!result.IsNull()) {
14366 if (result.IsNull()) { 14460 return result.raw();
14367 break;
14368 }
14369 if (this->CanonicalizeEquals(result)) {
14370 ASSERT(result.IsCanonical());
14371 return result.raw();
14372 }
14373 index++;
14374 } 14461 }
14375 // The value needs to be added to the list. Grow the list if 14462 // The value needs to be added to the list. Grow the list if
14376 // it is full. 14463 // it is full.
14377 result ^= this->raw(); 14464 result ^= this->raw();
14378 if (result.IsNew() || 14465 if (result.IsNew() ||
14379 (result.InVMHeap() && (isolate != Dart::vm_isolate()))) { 14466 (result.InVMHeap() && (isolate != Dart::vm_isolate()))) {
14380 /** 14467 /**
14381 * When a snapshot is generated on a 64 bit architecture and then read 14468 * When a snapshot is generated on a 64 bit architecture and then read
14382 * into a 32 bit architecture, values which are Smi on the 64 bit 14469 * into a 32 bit architecture, values which are Smi on the 64 bit
14383 * architecture could potentially be converted to Mint objects, however 14470 * architecture could potentially be converted to Mint objects, however
14384 * since Smi values do not have any notion of canonical bits we lose 14471 * since Smi values do not have any notion of canonical bits we lose
14385 * that information when the object becomes a Mint. 14472 * that information when the object becomes a Mint.
14386 * Some of these values could be literal values and end up in the 14473 * Some of these values could be literal values and end up in the
14387 * VM isolate heap. Later when these values are referenced in a 14474 * VM isolate heap. Later when these values are referenced in a
14388 * constant list we try to ensure that all the objects in the list 14475 * constant list we try to ensure that all the objects in the list
14389 * are canonical and try to canonicalize them. When these Mint objects 14476 * are canonical and try to canonicalize them. When these Mint objects
14390 * are encountered they do not have the canonical bit set and 14477 * are encountered they do not have the canonical bit set and
14391 * canonicalizing them won't work as the VM heap is read only now. 14478 * canonicalizing them won't work as the VM heap is read only now.
14392 * In these cases we clone the object into the isolate and then 14479 * In these cases we clone the object into the isolate and then
14393 * canonicalize it. 14480 * canonicalize it.
14394 */ 14481 */
14395 // Create a canonical object in old space. 14482 // Create a canonical object in old space.
14396 result ^= Object::Clone(result, Heap::kOld); 14483 result ^= Object::Clone(result, Heap::kOld);
14397 } 14484 }
siva 2016/03/02 19:12:07 As discussed offline this piece of code could move
14398 ASSERT(result.IsOld()); 14485 ASSERT(result.IsOld());
14399 cls.InsertCanonicalConstant(index, result); 14486 {
14400 result.SetCanonical(); 14487 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
14401 return result.raw(); 14488 // Retry lookup.
14489 {
14490 Instance& temp_result = Instance::Handle(zone,
14491 cls.LookupCanonicalInstance(zone, *this, &index));
14492 if (!temp_result.IsNull()) {
14493 return temp_result.raw();
14494 }
14495 }
14496 result.SetCanonical();
14497 cls.InsertCanonicalConstant(index, result);
14498 return result.raw();
14499 }
14402 } 14500 }
14403 14501
14404 14502
14405 RawAbstractType* Instance::GetType() const { 14503 RawAbstractType* Instance::GetType() const {
14406 if (IsNull()) { 14504 if (IsNull()) {
14407 return Type::NullType(); 14505 return Type::NullType();
14408 } 14506 }
14409 const Class& cls = Class::Handle(clazz()); 14507 const Class& cls = Class::Handle(clazz());
14410 if (cls.IsClosureClass()) { 14508 if (cls.IsClosureClass()) {
14411 const Function& signature = 14509 const Function& signature =
(...skipping 3184 matching lines...) Expand 10 before | Expand all | Expand 10 after
17596 result ^= raw; 17694 result ^= raw;
17597 } 17695 }
17598 result.set_value(val); 17696 result.set_value(val);
17599 return result.raw(); 17697 return result.raw();
17600 } 17698 }
17601 17699
17602 17700
17603 RawMint* Mint::NewCanonical(int64_t value) { 17701 RawMint* Mint::NewCanonical(int64_t value) {
17604 // Do not allocate a Mint if Smi would do. 17702 // Do not allocate a Mint if Smi would do.
17605 ASSERT(!Smi::IsValid(value)); 17703 ASSERT(!Smi::IsValid(value));
17606 const Class& cls = 17704 Thread* thread = Thread::Current();
17607 Class::Handle(Isolate::Current()->object_store()->mint_class()); 17705 Zone* zone = thread->zone();
17608 const Array& constants = Array::Handle(cls.constants()); 17706 Isolate* isolate = thread->isolate();
17609 const intptr_t constants_len = constants.Length(); 17707 const Class& cls = Class::Handle(zone, isolate->object_store()->mint_class());
17610 // Linear search to see whether this value is already present in the 17708 Mint& canonical_value = Mint::Handle(zone);
17611 // list of canonicalized constants.
17612 Mint& canonical_value = Mint::Handle();
17613 intptr_t index = 0; 17709 intptr_t index = 0;
17614 while (index < constants_len) { 17710 canonical_value ^= cls.LookupCanonicalMint(zone, value, &index);
17615 canonical_value ^= constants.At(index); 17711 if (!canonical_value.IsNull()) {
17616 if (canonical_value.IsNull()) { 17712 return canonical_value.raw();
17617 break; 17713 }
17714 canonical_value = Mint::New(value, Heap::kOld);
17715 {
17716 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
17717 // Retry lookup.
17718 {
17719 const Mint& result =
17720 Mint::Handle(zone, cls.LookupCanonicalMint(zone, value, &index));
17721 if (!result.IsNull()) {
17722 return result.raw();
17723 }
17618 } 17724 }
17619 if (canonical_value.value() == value) { 17725 canonical_value.SetCanonical();
17620 ASSERT(canonical_value.IsCanonical()); 17726 // The value needs to be added to the constants list. Grow the list if
17621 return canonical_value.raw(); 17727 // it is full.
17622 } 17728 cls.InsertCanonicalConstant(index, canonical_value);
17623 index++; 17729 return canonical_value.raw();
17624 } 17730 }
17625 // The value needs to be added to the constants list. Grow the list if
17626 // it is full.
17627 canonical_value = Mint::New(value, Heap::kOld);
17628 cls.InsertCanonicalConstant(index, canonical_value);
17629 canonical_value.SetCanonical();
17630 return canonical_value.raw();
17631 } 17731 }
17632 17732
17633 17733
17634 bool Mint::Equals(const Instance& other) const { 17734 bool Mint::Equals(const Instance& other) const {
17635 if (this->raw() == other.raw()) { 17735 if (this->raw() == other.raw()) {
17636 // Both handles point to the same raw instance. 17736 // Both handles point to the same raw instance.
17637 return true; 17737 return true;
17638 } 17738 }
17639 if (!other.IsMint() || other.IsNull()) { 17739 if (!other.IsMint() || other.IsNull()) {
17640 return false; 17740 return false;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
17744 RawDouble* Double::New(const String& str, Heap::Space space) { 17844 RawDouble* Double::New(const String& str, Heap::Space space) {
17745 double double_value; 17845 double double_value;
17746 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) { 17846 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) {
17747 return Double::Handle().raw(); 17847 return Double::Handle().raw();
17748 } 17848 }
17749 return New(double_value, space); 17849 return New(double_value, space);
17750 } 17850 }
17751 17851
17752 17852
17753 RawDouble* Double::NewCanonical(double value) { 17853 RawDouble* Double::NewCanonical(double value) {
17754 const Class& cls = 17854 Thread* thread = Thread::Current();
17755 Class::Handle(Isolate::Current()->object_store()->double_class()); 17855 Zone* zone = thread->zone();
17756 const Array& constants = Array::Handle(cls.constants()); 17856 Isolate* isolate = thread->isolate();
17757 const intptr_t constants_len = constants.Length(); 17857 const Class& cls = Class::Handle(isolate->object_store()->double_class());
17758 // Linear search to see whether this value is already present in the 17858 // Linear search to see whether this value is already present in the
17759 // list of canonicalized constants. 17859 // list of canonicalized constants.
17760 Double& canonical_value = Double::Handle(); 17860 Double& canonical_value = Double::Handle(zone);
17761 intptr_t index = 0; 17861 intptr_t index = 0;
17762 while (index < constants_len) { 17862
17763 canonical_value ^= constants.At(index); 17863 canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index);
17764 if (canonical_value.IsNull()) { 17864 if (!canonical_value.IsNull()) {
17765 break; 17865 return canonical_value.raw();
17866 }
17867 canonical_value = Double::New(value, Heap::kOld);
17868 {
17869 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
17870 // Retry lookup.
17871 {
17872 const Double& result =
17873 Double::Handle(zone, cls.LookupCanonicalDouble(zone, value, &index));
17874 if (!result.IsNull()) {
17875 return result.raw();
17876 }
17766 } 17877 }
17767 if (canonical_value.BitwiseEqualsToDouble(value)) { 17878 canonical_value.SetCanonical();
17768 return canonical_value.raw(); 17879 // The value needs to be added to the constants list. Grow the list if
17769 } 17880 // it is full.
17770 index++; 17881 cls.InsertCanonicalConstant(index, canonical_value);
17882 return canonical_value.raw();
17771 } 17883 }
17772 // The value needs to be added to the constants list. Grow the list if
17773 // it is full.
17774 canonical_value = Double::New(value, Heap::kOld);
17775 cls.InsertCanonicalConstant(index, canonical_value);
17776 canonical_value.SetCanonical();
17777 return canonical_value.raw();
17778 } 17884 }
17779 17885
17780 17886
17781 RawDouble* Double::NewCanonical(const String& str) { 17887 RawDouble* Double::NewCanonical(const String& str) {
17782 double double_value; 17888 double double_value;
17783 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) { 17889 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) {
17784 return Double::Handle().raw(); 17890 return Double::Handle().raw();
17785 } 17891 }
17786 return NewCanonical(double_value); 17892 return NewCanonical(double_value);
17787 } 17893 }
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
18048 ((str[1] == 'x') || (str[1] == 'X'))) { 18154 ((str[1] == 'x') || (str[1] == 'X'))) {
18049 digits = NewDigitsFromHexCString(&str[2], &used, space); 18155 digits = NewDigitsFromHexCString(&str[2], &used, space);
18050 } else { 18156 } else {
18051 digits = NewDigitsFromDecCString(str, &used, space); 18157 digits = NewDigitsFromDecCString(str, &used, space);
18052 } 18158 }
18053 return New(neg, used, digits, space); 18159 return New(neg, used, digits, space);
18054 } 18160 }
18055 18161
18056 18162
18057 RawBigint* Bigint::NewCanonical(const String& str) { 18163 RawBigint* Bigint::NewCanonical(const String& str) {
18164 Thread* thread = Thread::Current();
18165 Zone* zone = thread->zone();
18166 Isolate* isolate = thread->isolate();
18058 const Bigint& value = Bigint::Handle( 18167 const Bigint& value = Bigint::Handle(
18059 Bigint::NewFromCString(str.ToCString(), Heap::kOld)); 18168 zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld));
18060 const Class& cls = 18169 const Class& cls =
18061 Class::Handle(Isolate::Current()->object_store()->bigint_class()); 18170 Class::Handle(zone, isolate->object_store()->bigint_class());
18062 const Array& constants = Array::Handle(cls.constants());
18063 const intptr_t constants_len = constants.Length();
18064 // Linear search to see whether this value is already present in the
18065 // list of canonicalized constants.
18066 Bigint& canonical_value = Bigint::Handle();
18067 intptr_t index = 0; 18171 intptr_t index = 0;
18068 while (index < constants_len) { 18172 const Bigint& canonical_value =
18069 canonical_value ^= constants.At(index); 18173 Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index));
18070 if (canonical_value.IsNull()) { 18174 if (!canonical_value.IsNull()) {
18071 break; 18175 return canonical_value.raw();
18176 }
18177 {
18178 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
18179 // Retry lookup.
18180 {
18181 const Bigint& result =
18182 Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index));
18183 if (!result.IsNull()) {
18184 return result.raw();
18185 }
18072 } 18186 }
18073 if (canonical_value.Equals(value)) { 18187 value.SetCanonical();
18074 return canonical_value.raw(); 18188 // The value needs to be added to the constants list. Grow the list if
18075 } 18189 // it is full.
18076 index++; 18190 cls.InsertCanonicalConstant(index, value);
18191 return value.raw();
18077 } 18192 }
18078 // The value needs to be added to the constants list. Grow the list if
18079 // it is full.
18080 cls.InsertCanonicalConstant(index, value);
18081 value.SetCanonical();
18082 return value.raw();
18083 } 18193 }
18084 18194
18085 18195
18086 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used, 18196 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used,
18087 Heap::Space space) { 18197 Heap::Space space) {
18088 const int kBitsPerHexDigit = 4; 18198 const int kBitsPerHexDigit = 4;
18089 const int kHexDigitsPerDigit = 8; 18199 const int kHexDigitsPerDigit = 8;
18090 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit; 18200 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
18091 intptr_t hex_i = strlen(str); // Terminating byte excluded. 18201 intptr_t hex_i = strlen(str); // Terminating byte excluded.
18092 if ((hex_i <= 0) || (hex_i >= kMaxInt32)) { 18202 if ((hex_i <= 0) || (hex_i >= kMaxInt32)) {
(...skipping 3608 matching lines...) Expand 10 before | Expand all | Expand 10 after
21701 return UserTag::null(); 21811 return UserTag::null();
21702 } 21812 }
21703 21813
21704 21814
21705 const char* UserTag::ToCString() const { 21815 const char* UserTag::ToCString() const {
21706 const String& tag_label = String::Handle(label()); 21816 const String& tag_label = String::Handle(label());
21707 return tag_label.ToCString(); 21817 return tag_label.ToCString();
21708 } 21818 }
21709 21819
21710 } // namespace dart 21820 } // namespace dart
OLDNEW
« 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