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

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: Move allocation 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 10175 matching lines...) Expand 10 before | Expand all | Expand 10 after
14405 return this->raw(); 14503 return this->raw();
14406 } 14504 }
14407 if (!CheckAndCanonicalizeFields(error_str)) { 14505 if (!CheckAndCanonicalizeFields(error_str)) {
14408 return Instance::null(); 14506 return Instance::null();
14409 } 14507 }
14410 Thread* thread = Thread::Current(); 14508 Thread* thread = Thread::Current();
14411 Zone* zone = thread->zone(); 14509 Zone* zone = thread->zone();
14412 Isolate* isolate = thread->isolate(); 14510 Isolate* isolate = thread->isolate();
14413 Instance& result = Instance::Handle(zone); 14511 Instance& result = Instance::Handle(zone);
14414 const Class& cls = Class::Handle(zone, this->clazz()); 14512 const Class& cls = Class::Handle(zone, this->clazz());
14415 Array& constants = Array::Handle(zone, cls.constants());
14416 const intptr_t constants_len = constants.Length();
14417 // Linear search to see whether this value is already present in the
14418 // list of canonicalized constants.
14419 intptr_t index = 0; 14513 intptr_t index = 0;
14420 while (index < constants_len) { 14514 result ^= cls.LookupCanonicalInstance(zone, *this, &index);
14421 result ^= constants.At(index); 14515 if (!result.IsNull()) {
14422 if (result.IsNull()) { 14516 return result.raw();
14423 break; 14517 }
14518 {
14519 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
14520 // Retry lookup.
14521 {
14522 Instance& temp_result = Instance::Handle(zone,
14523 cls.LookupCanonicalInstance(zone, *this, &index));
14524 if (!temp_result.IsNull()) {
14525 return temp_result.raw();
14526 }
14424 } 14527 }
14425 if (this->CanonicalizeEquals(result)) { 14528
14426 ASSERT(result.IsCanonical()); 14529 // The value needs to be added to the list. Grow the list if
14427 return result.raw(); 14530 // it is full.
14531 result ^= this->raw();
14532 if (result.IsNew() ||
14533 (result.InVMHeap() && (isolate != Dart::vm_isolate()))) {
14534 /**
14535 * When a snapshot is generated on a 64 bit architecture and then read
14536 * into a 32 bit architecture, values which are Smi on the 64 bit
14537 * architecture could potentially be converted to Mint objects, however
14538 * since Smi values do not have any notion of canonical bits we lose
14539 * that information when the object becomes a Mint.
14540 * Some of these values could be literal values and end up in the
14541 * VM isolate heap. Later when these values are referenced in a
14542 * constant list we try to ensure that all the objects in the list
14543 * are canonical and try to canonicalize them. When these Mint objects
14544 * are encountered they do not have the canonical bit set and
14545 * canonicalizing them won't work as the VM heap is read only now.
14546 * In these cases we clone the object into the isolate and then
14547 * canonicalize it.
14548 */
14549 // Create a canonical object in old space.
14550 result ^= Object::Clone(result, Heap::kOld);
14428 } 14551 }
14429 index++; 14552 ASSERT(result.IsOld());
14553
14554 result.SetCanonical();
14555 cls.InsertCanonicalConstant(index, result);
14556 return result.raw();
14430 } 14557 }
14431 // The value needs to be added to the list. Grow the list if
14432 // it is full.
14433 result ^= this->raw();
14434 if (result.IsNew() ||
14435 (result.InVMHeap() && (isolate != Dart::vm_isolate()))) {
14436 /**
14437 * When a snapshot is generated on a 64 bit architecture and then read
14438 * into a 32 bit architecture, values which are Smi on the 64 bit
14439 * architecture could potentially be converted to Mint objects, however
14440 * since Smi values do not have any notion of canonical bits we lose
14441 * that information when the object becomes a Mint.
14442 * Some of these values could be literal values and end up in the
14443 * VM isolate heap. Later when these values are referenced in a
14444 * constant list we try to ensure that all the objects in the list
14445 * are canonical and try to canonicalize them. When these Mint objects
14446 * are encountered they do not have the canonical bit set and
14447 * canonicalizing them won't work as the VM heap is read only now.
14448 * In these cases we clone the object into the isolate and then
14449 * canonicalize it.
14450 */
14451 // Create a canonical object in old space.
14452 result ^= Object::Clone(result, Heap::kOld);
14453 }
14454 ASSERT(result.IsOld());
14455 cls.InsertCanonicalConstant(index, result);
14456 result.SetCanonical();
14457 return result.raw();
14458 } 14558 }
14459 14559
14460 14560
14461 RawAbstractType* Instance::GetType() const { 14561 RawAbstractType* Instance::GetType() const {
14462 if (IsNull()) { 14562 if (IsNull()) {
14463 return Type::NullType(); 14563 return Type::NullType();
14464 } 14564 }
14465 const Class& cls = Class::Handle(clazz()); 14565 const Class& cls = Class::Handle(clazz());
14466 if (cls.IsClosureClass()) { 14566 if (cls.IsClosureClass()) {
14467 const Function& signature = 14567 const Function& signature =
(...skipping 3184 matching lines...) Expand 10 before | Expand all | Expand 10 after
17652 result ^= raw; 17752 result ^= raw;
17653 } 17753 }
17654 result.set_value(val); 17754 result.set_value(val);
17655 return result.raw(); 17755 return result.raw();
17656 } 17756 }
17657 17757
17658 17758
17659 RawMint* Mint::NewCanonical(int64_t value) { 17759 RawMint* Mint::NewCanonical(int64_t value) {
17660 // Do not allocate a Mint if Smi would do. 17760 // Do not allocate a Mint if Smi would do.
17661 ASSERT(!Smi::IsValid(value)); 17761 ASSERT(!Smi::IsValid(value));
17662 const Class& cls = 17762 Thread* thread = Thread::Current();
17663 Class::Handle(Isolate::Current()->object_store()->mint_class()); 17763 Zone* zone = thread->zone();
17664 const Array& constants = Array::Handle(cls.constants()); 17764 Isolate* isolate = thread->isolate();
17665 const intptr_t constants_len = constants.Length(); 17765 const Class& cls = Class::Handle(zone, isolate->object_store()->mint_class());
17666 // Linear search to see whether this value is already present in the 17766 Mint& canonical_value = Mint::Handle(zone);
17667 // list of canonicalized constants.
17668 Mint& canonical_value = Mint::Handle();
17669 intptr_t index = 0; 17767 intptr_t index = 0;
17670 while (index < constants_len) { 17768 canonical_value ^= cls.LookupCanonicalMint(zone, value, &index);
17671 canonical_value ^= constants.At(index); 17769 if (!canonical_value.IsNull()) {
17672 if (canonical_value.IsNull()) { 17770 return canonical_value.raw();
17673 break; 17771 }
17772 {
17773 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
17774 // Retry lookup.
17775 {
17776 const Mint& result =
17777 Mint::Handle(zone, cls.LookupCanonicalMint(zone, value, &index));
17778 if (!result.IsNull()) {
17779 return result.raw();
17780 }
17674 } 17781 }
17675 if (canonical_value.value() == value) { 17782 canonical_value = Mint::New(value, Heap::kOld);
17676 ASSERT(canonical_value.IsCanonical()); 17783 canonical_value.SetCanonical();
17677 return canonical_value.raw(); 17784 // The value needs to be added to the constants list. Grow the list if
17678 } 17785 // it is full.
17679 index++; 17786 cls.InsertCanonicalConstant(index, canonical_value);
17787 return canonical_value.raw();
17680 } 17788 }
17681 // The value needs to be added to the constants list. Grow the list if
17682 // it is full.
17683 canonical_value = Mint::New(value, Heap::kOld);
17684 cls.InsertCanonicalConstant(index, canonical_value);
17685 canonical_value.SetCanonical();
17686 return canonical_value.raw();
17687 } 17789 }
17688 17790
17689 17791
17690 bool Mint::Equals(const Instance& other) const { 17792 bool Mint::Equals(const Instance& other) const {
17691 if (this->raw() == other.raw()) { 17793 if (this->raw() == other.raw()) {
17692 // Both handles point to the same raw instance. 17794 // Both handles point to the same raw instance.
17693 return true; 17795 return true;
17694 } 17796 }
17695 if (!other.IsMint() || other.IsNull()) { 17797 if (!other.IsMint() || other.IsNull()) {
17696 return false; 17798 return false;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
17800 RawDouble* Double::New(const String& str, Heap::Space space) { 17902 RawDouble* Double::New(const String& str, Heap::Space space) {
17801 double double_value; 17903 double double_value;
17802 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) { 17904 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) {
17803 return Double::Handle().raw(); 17905 return Double::Handle().raw();
17804 } 17906 }
17805 return New(double_value, space); 17907 return New(double_value, space);
17806 } 17908 }
17807 17909
17808 17910
17809 RawDouble* Double::NewCanonical(double value) { 17911 RawDouble* Double::NewCanonical(double value) {
17810 const Class& cls = 17912 Thread* thread = Thread::Current();
17811 Class::Handle(Isolate::Current()->object_store()->double_class()); 17913 Zone* zone = thread->zone();
17812 const Array& constants = Array::Handle(cls.constants()); 17914 Isolate* isolate = thread->isolate();
17813 const intptr_t constants_len = constants.Length(); 17915 const Class& cls = Class::Handle(isolate->object_store()->double_class());
17814 // Linear search to see whether this value is already present in the 17916 // Linear search to see whether this value is already present in the
17815 // list of canonicalized constants. 17917 // list of canonicalized constants.
17816 Double& canonical_value = Double::Handle(); 17918 Double& canonical_value = Double::Handle(zone);
17817 intptr_t index = 0; 17919 intptr_t index = 0;
17818 while (index < constants_len) { 17920
17819 canonical_value ^= constants.At(index); 17921 canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index);
17820 if (canonical_value.IsNull()) { 17922 if (!canonical_value.IsNull()) {
17821 break; 17923 return canonical_value.raw();
17924 }
17925 {
17926 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
17927 // Retry lookup.
17928 {
17929 const Double& result =
17930 Double::Handle(zone, cls.LookupCanonicalDouble(zone, value, &index));
17931 if (!result.IsNull()) {
17932 return result.raw();
17933 }
17822 } 17934 }
17823 if (canonical_value.BitwiseEqualsToDouble(value)) { 17935 canonical_value = Double::New(value, Heap::kOld);
17824 return canonical_value.raw(); 17936 canonical_value.SetCanonical();
17825 } 17937 // The value needs to be added to the constants list. Grow the list if
17826 index++; 17938 // it is full.
17939 cls.InsertCanonicalConstant(index, canonical_value);
17940 return canonical_value.raw();
17827 } 17941 }
17828 // The value needs to be added to the constants list. Grow the list if
17829 // it is full.
17830 canonical_value = Double::New(value, Heap::kOld);
17831 cls.InsertCanonicalConstant(index, canonical_value);
17832 canonical_value.SetCanonical();
17833 return canonical_value.raw();
17834 } 17942 }
17835 17943
17836 17944
17837 RawDouble* Double::NewCanonical(const String& str) { 17945 RawDouble* Double::NewCanonical(const String& str) {
17838 double double_value; 17946 double double_value;
17839 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) { 17947 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) {
17840 return Double::Handle().raw(); 17948 return Double::Handle().raw();
17841 } 17949 }
17842 return NewCanonical(double_value); 17950 return NewCanonical(double_value);
17843 } 17951 }
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
18104 ((str[1] == 'x') || (str[1] == 'X'))) { 18212 ((str[1] == 'x') || (str[1] == 'X'))) {
18105 digits = NewDigitsFromHexCString(&str[2], &used, space); 18213 digits = NewDigitsFromHexCString(&str[2], &used, space);
18106 } else { 18214 } else {
18107 digits = NewDigitsFromDecCString(str, &used, space); 18215 digits = NewDigitsFromDecCString(str, &used, space);
18108 } 18216 }
18109 return New(neg, used, digits, space); 18217 return New(neg, used, digits, space);
18110 } 18218 }
18111 18219
18112 18220
18113 RawBigint* Bigint::NewCanonical(const String& str) { 18221 RawBigint* Bigint::NewCanonical(const String& str) {
18222 Thread* thread = Thread::Current();
18223 Zone* zone = thread->zone();
18224 Isolate* isolate = thread->isolate();
18114 const Bigint& value = Bigint::Handle( 18225 const Bigint& value = Bigint::Handle(
18115 Bigint::NewFromCString(str.ToCString(), Heap::kOld)); 18226 zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld));
18116 const Class& cls = 18227 const Class& cls =
18117 Class::Handle(Isolate::Current()->object_store()->bigint_class()); 18228 Class::Handle(zone, isolate->object_store()->bigint_class());
18118 const Array& constants = Array::Handle(cls.constants());
18119 const intptr_t constants_len = constants.Length();
18120 // Linear search to see whether this value is already present in the
18121 // list of canonicalized constants.
18122 Bigint& canonical_value = Bigint::Handle();
18123 intptr_t index = 0; 18229 intptr_t index = 0;
18124 while (index < constants_len) { 18230 const Bigint& canonical_value =
18125 canonical_value ^= constants.At(index); 18231 Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index));
18126 if (canonical_value.IsNull()) { 18232 if (!canonical_value.IsNull()) {
18127 break; 18233 return canonical_value.raw();
18234 }
18235 {
18236 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
18237 // Retry lookup.
18238 {
18239 const Bigint& result =
18240 Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index));
18241 if (!result.IsNull()) {
18242 return result.raw();
18243 }
18128 } 18244 }
18129 if (canonical_value.Equals(value)) { 18245 value.SetCanonical();
18130 return canonical_value.raw(); 18246 // The value needs to be added to the constants list. Grow the list if
18131 } 18247 // it is full.
18132 index++; 18248 cls.InsertCanonicalConstant(index, value);
18249 return value.raw();
18133 } 18250 }
18134 // The value needs to be added to the constants list. Grow the list if
18135 // it is full.
18136 cls.InsertCanonicalConstant(index, value);
18137 value.SetCanonical();
18138 return value.raw();
18139 } 18251 }
18140 18252
18141 18253
18142 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used, 18254 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used,
18143 Heap::Space space) { 18255 Heap::Space space) {
18144 const int kBitsPerHexDigit = 4; 18256 const int kBitsPerHexDigit = 4;
18145 const int kHexDigitsPerDigit = 8; 18257 const int kHexDigitsPerDigit = 8;
18146 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit; 18258 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
18147 intptr_t hex_i = strlen(str); // Terminating byte excluded. 18259 intptr_t hex_i = strlen(str); // Terminating byte excluded.
18148 if ((hex_i <= 0) || (hex_i >= kMaxInt32)) { 18260 if ((hex_i <= 0) || (hex_i >= kMaxInt32)) {
(...skipping 3608 matching lines...) Expand 10 before | Expand all | Expand 10 after
21757 return UserTag::null(); 21869 return UserTag::null();
21758 } 21870 }
21759 21871
21760 21872
21761 const char* UserTag::ToCString() const { 21873 const char* UserTag::ToCString() const {
21762 const String& tag_label = String::Handle(label()); 21874 const String& tag_label = String::Handle(label());
21763 return tag_label.ToCString(); 21875 return tag_label.ToCString();
21764 } 21876 }
21765 21877
21766 } // namespace dart 21878 } // 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