OLD | NEW |
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/become.h" | 10 #include "vm/become.h" |
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 cls = Class::NewStringClass(kOneByteStringCid); | 696 cls = Class::NewStringClass(kOneByteStringCid); |
697 isolate->object_store()->set_one_byte_string_class(cls); | 697 isolate->object_store()->set_one_byte_string_class(cls); |
698 cls = Class::NewStringClass(kTwoByteStringCid); | 698 cls = Class::NewStringClass(kTwoByteStringCid); |
699 isolate->object_store()->set_two_byte_string_class(cls); | 699 isolate->object_store()->set_two_byte_string_class(cls); |
700 cls = Class::New<Mint>(); | 700 cls = Class::New<Mint>(); |
701 isolate->object_store()->set_mint_class(cls); | 701 isolate->object_store()->set_mint_class(cls); |
702 cls = Class::New<Bigint>(); | 702 cls = Class::New<Bigint>(); |
703 isolate->object_store()->set_bigint_class(cls); | 703 isolate->object_store()->set_bigint_class(cls); |
704 cls = Class::New<Double>(); | 704 cls = Class::New<Double>(); |
705 isolate->object_store()->set_double_class(cls); | 705 isolate->object_store()->set_double_class(cls); |
| 706 cls = Class::New<Fraction>(); |
| 707 // TODO(regis): Remove once native getters are implemented for _Fraction. |
| 708 cls.SetRefinalizeAfterPatch(); // Fields are defined both in C++ and in Dart. |
| 709 isolate->object_store()->set_fraction_class(cls); |
706 | 710 |
707 // Ensure that class kExternalTypedDataUint8ArrayCid is registered as we | 711 // Ensure that class kExternalTypedDataUint8ArrayCid is registered as we |
708 // need it when reading in the token stream of bootstrap classes in the VM | 712 // need it when reading in the token stream of bootstrap classes in the VM |
709 // isolate. | 713 // isolate. |
710 Class::NewExternalTypedDataClass(kExternalTypedDataUint8ArrayCid); | 714 Class::NewExternalTypedDataClass(kExternalTypedDataUint8ArrayCid); |
711 | 715 |
712 // Needed for object pools of VM isolate stubs. | 716 // Needed for object pools of VM isolate stubs. |
713 Class::NewTypedDataClass(kTypedDataInt8ArrayCid); | 717 Class::NewTypedDataClass(kTypedDataInt8ArrayCid); |
714 | 718 |
715 // Allocate and initialize the empty_array instance. | 719 // Allocate and initialize the empty_array instance. |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 cls = Class::New<Bigint>(); | 1375 cls = Class::New<Bigint>(); |
1372 object_store->set_bigint_class(cls); | 1376 object_store->set_bigint_class(cls); |
1373 RegisterPrivateClass(cls, Symbols::_Bigint(), core_lib); | 1377 RegisterPrivateClass(cls, Symbols::_Bigint(), core_lib); |
1374 pending_classes.Add(cls); | 1378 pending_classes.Add(cls); |
1375 | 1379 |
1376 cls = Class::New<Double>(); | 1380 cls = Class::New<Double>(); |
1377 object_store->set_double_class(cls); | 1381 object_store->set_double_class(cls); |
1378 RegisterPrivateClass(cls, Symbols::_Double(), core_lib); | 1382 RegisterPrivateClass(cls, Symbols::_Double(), core_lib); |
1379 pending_classes.Add(cls); | 1383 pending_classes.Add(cls); |
1380 | 1384 |
| 1385 cls = Class::New<Fraction>(); |
| 1386 object_store->set_fraction_class(cls); |
| 1387 // TODO(regis): Remove once native getters are implemented for _Fraction. |
| 1388 cls.SetRefinalizeAfterPatch(); // Fields are defined both in C++ and in Dart. |
| 1389 RegisterPrivateClass(cls, Symbols::_Fraction(), core_lib); |
| 1390 pending_classes.Add(cls); |
| 1391 |
1381 // Class that represents the Dart class _Closure and C++ class Closure. | 1392 // Class that represents the Dart class _Closure and C++ class Closure. |
1382 cls = Class::New<Closure>(); | 1393 cls = Class::New<Closure>(); |
1383 cls.set_type_arguments_field_offset(Closure::type_arguments_offset()); | 1394 cls.set_type_arguments_field_offset(Closure::type_arguments_offset()); |
1384 cls.set_num_type_arguments(0); // Although a closure has type_arguments_. | 1395 cls.set_num_type_arguments(0); // Although a closure has type_arguments_. |
1385 cls.set_num_own_type_arguments(0); | 1396 cls.set_num_own_type_arguments(0); |
1386 RegisterPrivateClass(cls, Symbols::_Closure(), core_lib); | 1397 RegisterPrivateClass(cls, Symbols::_Closure(), core_lib); |
1387 pending_classes.Add(cls); | 1398 pending_classes.Add(cls); |
1388 object_store->set_closure_class(cls); | 1399 object_store->set_closure_class(cls); |
1389 | 1400 |
1390 cls = Class::New<WeakProperty>(); | 1401 cls = Class::New<WeakProperty>(); |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1691 cls = Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid); | 1702 cls = Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid); |
1692 CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS); | 1703 CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS); |
1693 #undef REGISTER_TYPED_DATA_VIEW_CLASS | 1704 #undef REGISTER_TYPED_DATA_VIEW_CLASS |
1694 cls = Class::NewTypedDataViewClass(kByteDataViewCid); | 1705 cls = Class::NewTypedDataViewClass(kByteDataViewCid); |
1695 #define REGISTER_EXT_TYPED_DATA_CLASS(clazz) \ | 1706 #define REGISTER_EXT_TYPED_DATA_CLASS(clazz) \ |
1696 cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid); | 1707 cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid); |
1697 CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS); | 1708 CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS); |
1698 #undef REGISTER_EXT_TYPED_DATA_CLASS | 1709 #undef REGISTER_EXT_TYPED_DATA_CLASS |
1699 | 1710 |
1700 cls = Class::New<Instance>(kByteBufferCid); | 1711 cls = Class::New<Instance>(kByteBufferCid); |
| 1712 object_store->set_byte_buffer_class(cls); |
1701 | 1713 |
1702 cls = Class::New<Integer>(); | 1714 cls = Class::New<Integer>(); |
1703 object_store->set_integer_implementation_class(cls); | 1715 object_store->set_integer_implementation_class(cls); |
1704 | 1716 |
1705 cls = Class::New<Smi>(); | 1717 cls = Class::New<Smi>(); |
1706 object_store->set_smi_class(cls); | 1718 object_store->set_smi_class(cls); |
1707 | 1719 |
1708 cls = Class::New<Mint>(); | 1720 cls = Class::New<Mint>(); |
1709 object_store->set_mint_class(cls); | 1721 object_store->set_mint_class(cls); |
1710 | 1722 |
1711 cls = Class::New<Double>(); | 1723 cls = Class::New<Double>(); |
1712 object_store->set_double_class(cls); | 1724 object_store->set_double_class(cls); |
1713 | 1725 |
| 1726 cls = Class::New<Fraction>(); |
| 1727 // TODO(regis): Remove once native getters are implemented for _Fraction. |
| 1728 cls.SetRefinalizeAfterPatch(); // Fields are defined both in C++ and in Dart. |
| 1729 object_store->set_fraction_class(cls); |
| 1730 |
1714 cls = Class::New<Closure>(); | 1731 cls = Class::New<Closure>(); |
1715 object_store->set_closure_class(cls); | 1732 object_store->set_closure_class(cls); |
1716 | 1733 |
1717 cls = Class::New<Bigint>(); | 1734 cls = Class::New<Bigint>(); |
1718 object_store->set_bigint_class(cls); | 1735 object_store->set_bigint_class(cls); |
1719 | 1736 |
1720 cls = Class::NewStringClass(kOneByteStringCid); | 1737 cls = Class::NewStringClass(kOneByteStringCid); |
1721 object_store->set_one_byte_string_class(cls); | 1738 object_store->set_one_byte_string_class(cls); |
1722 | 1739 |
1723 cls = Class::NewStringClass(kTwoByteStringCid); | 1740 cls = Class::NewStringClass(kTwoByteStringCid); |
(...skipping 1841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3565 | 3582 |
3566 | 3583 |
3567 void Class::set_is_finalized() const { | 3584 void Class::set_is_finalized() const { |
3568 ASSERT(!is_finalized()); | 3585 ASSERT(!is_finalized()); |
3569 set_state_bits(ClassFinalizedBits::update(RawClass::kFinalized, | 3586 set_state_bits(ClassFinalizedBits::update(RawClass::kFinalized, |
3570 raw_ptr()->state_bits_)); | 3587 raw_ptr()->state_bits_)); |
3571 } | 3588 } |
3572 | 3589 |
3573 | 3590 |
3574 void Class::SetRefinalizeAfterPatch() const { | 3591 void Class::SetRefinalizeAfterPatch() const { |
3575 ASSERT(!IsTopLevel()); | 3592 ASSERT((raw_ptr()->name_ == String::null()) || !IsTopLevel()); |
3576 set_state_bits(ClassFinalizedBits::update(RawClass::kRefinalizeAfterPatch, | 3593 set_state_bits(ClassFinalizedBits::update(RawClass::kRefinalizeAfterPatch, |
3577 raw_ptr()->state_bits_)); | 3594 raw_ptr()->state_bits_)); |
3578 set_state_bits(TypeFinalizedBit::update(false, raw_ptr()->state_bits_)); | 3595 set_state_bits(TypeFinalizedBit::update(false, raw_ptr()->state_bits_)); |
3579 } | 3596 } |
3580 | 3597 |
3581 | 3598 |
3582 void Class::ResetFinalization() const { | 3599 void Class::ResetFinalization() const { |
3583 ASSERT(IsTopLevel()); | 3600 ASSERT(IsTopLevel()); |
3584 set_state_bits(ClassFinalizedBits::update(RawClass::kAllocated, | 3601 set_state_bits(ClassFinalizedBits::update(RawClass::kAllocated, |
3585 raw_ptr()->state_bits_)); | 3602 raw_ptr()->state_bits_)); |
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4331 if (canonical_value.Equals(value)) { | 4348 if (canonical_value.Equals(value)) { |
4332 ASSERT(canonical_value.IsCanonical()); | 4349 ASSERT(canonical_value.IsCanonical()); |
4333 return canonical_value.raw(); | 4350 return canonical_value.raw(); |
4334 } | 4351 } |
4335 *index = *index + 1; | 4352 *index = *index + 1; |
4336 } | 4353 } |
4337 return Bigint::null(); | 4354 return Bigint::null(); |
4338 } | 4355 } |
4339 | 4356 |
4340 | 4357 |
| 4358 RawFraction* Class::LookupCanonicalFraction(Zone* zone, |
| 4359 const Fraction& value, |
| 4360 intptr_t* index) const { |
| 4361 ASSERT(this->raw() == Isolate::Current()->object_store()->fraction_class()); |
| 4362 const Array& constants = Array::Handle(zone, this->constants()); |
| 4363 const intptr_t constants_len = constants.Length(); |
| 4364 // Linear search to see whether this value is already present in the |
| 4365 // list of canonicalized constants. |
| 4366 Fraction& canonical_value = Fraction::Handle(zone); |
| 4367 while (*index < constants_len) { |
| 4368 canonical_value ^= constants.At(*index); |
| 4369 if (canonical_value.IsNull()) { |
| 4370 break; |
| 4371 } |
| 4372 if (canonical_value.CanonicalizeEquals(value)) { |
| 4373 ASSERT(canonical_value.IsCanonical()); |
| 4374 return canonical_value.raw(); |
| 4375 } |
| 4376 *index = *index + 1; |
| 4377 } |
| 4378 return Fraction::null(); |
| 4379 } |
| 4380 |
| 4381 |
4341 class CanonicalInstanceKey { | 4382 class CanonicalInstanceKey { |
4342 public: | 4383 public: |
4343 explicit CanonicalInstanceKey(const Instance& key) : key_(key) { | 4384 explicit CanonicalInstanceKey(const Instance& key) : key_(key) { |
4344 ASSERT(!(key.IsString() || key.IsInteger() || key.IsAbstractType())); | 4385 ASSERT(!(key.IsString() || key.IsInteger() || key.IsAbstractType())); |
4345 } | 4386 } |
4346 bool Matches(const Instance& obj) const { | 4387 bool Matches(const Instance& obj) const { |
4347 ASSERT(!(obj.IsString() || obj.IsInteger() || obj.IsAbstractType())); | 4388 ASSERT(!(obj.IsString() || obj.IsInteger() || obj.IsAbstractType())); |
4348 if (key_.CanonicalizeEquals(obj)) { | 4389 if (key_.CanonicalizeEquals(obj)) { |
4349 ASSERT(obj.IsCanonical()); | 4390 ASSERT(obj.IsCanonical()); |
4350 return true; | 4391 return true; |
(...skipping 3659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8010 | 8051 |
8011 | 8052 |
8012 RawLiteralToken* LiteralToken::New(Token::Kind kind, const String& literal) { | 8053 RawLiteralToken* LiteralToken::New(Token::Kind kind, const String& literal) { |
8013 const LiteralToken& result = LiteralToken::Handle(LiteralToken::New()); | 8054 const LiteralToken& result = LiteralToken::Handle(LiteralToken::New()); |
8014 result.set_kind(kind); | 8055 result.set_kind(kind); |
8015 result.set_literal(literal); | 8056 result.set_literal(literal); |
8016 if (kind == Token::kINTEGER) { | 8057 if (kind == Token::kINTEGER) { |
8017 const Integer& value = Integer::Handle(Integer::NewCanonical(literal)); | 8058 const Integer& value = Integer::Handle(Integer::NewCanonical(literal)); |
8018 ASSERT(value.IsSmi() || value.IsOld()); | 8059 ASSERT(value.IsSmi() || value.IsOld()); |
8019 result.set_value(value); | 8060 result.set_value(value); |
| 8061 } else if (kind == Token::kRATIONAL) { |
| 8062 const Fraction& value = Fraction::Handle(Fraction::NewCanonical(literal)); |
| 8063 result.set_value(value); |
8020 } else if (kind == Token::kDOUBLE) { | 8064 } else if (kind == Token::kDOUBLE) { |
8021 const Double& value = Double::Handle(Double::NewCanonical(literal)); | 8065 const Double& value = Double::Handle(Double::NewCanonical(literal)); |
8022 result.set_value(value); | 8066 result.set_value(value); |
8023 } else { | 8067 } else { |
8024 ASSERT(Token::NeedsLiteralToken(kind)); | 8068 ASSERT(Token::NeedsLiteralToken(kind)); |
8025 result.set_value(literal); | 8069 result.set_value(literal); |
8026 } | 8070 } |
8027 return result.raw(); | 8071 return result.raw(); |
8028 } | 8072 } |
8029 | 8073 |
(...skipping 10024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18054 if (result.IsNew()) { | 18098 if (result.IsNew()) { |
18055 // Create a canonical object in old space. | 18099 // Create a canonical object in old space. |
18056 result ^= Object::Clone(result, Heap::kOld); | 18100 result ^= Object::Clone(result, Heap::kOld); |
18057 } | 18101 } |
18058 ASSERT(result.IsOld()); | 18102 ASSERT(result.IsOld()); |
18059 result.SetCanonical(); | 18103 result.SetCanonical(); |
18060 cls.InsertCanonicalNumber(zone, index, result); | 18104 cls.InsertCanonicalNumber(zone, index, result); |
18061 return result.raw(); | 18105 return result.raw(); |
18062 } | 18106 } |
18063 } | 18107 } |
| 18108 case kFractionCid: { |
| 18109 return Fraction::NewCanonical(Fraction::Cast(*this)); |
| 18110 } |
18064 default: | 18111 default: |
18065 UNREACHABLE(); | 18112 UNREACHABLE(); |
18066 } | 18113 } |
18067 return Instance::null(); | 18114 return Instance::null(); |
18068 } | 18115 } |
18069 | 18116 |
18070 | 18117 |
18071 const char* Number::ToCString() const { | 18118 const char* Number::ToCString() const { |
18072 // Number is an interface. No instances of Number should exist. | 18119 // Number is an interface. No instances of Number should exist. |
18073 UNREACHABLE(); | 18120 UNREACHABLE(); |
(...skipping 878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18952 } | 18999 } |
18953 { | 19000 { |
18954 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | 19001 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
18955 // Retry lookup. | 19002 // Retry lookup. |
18956 { | 19003 { |
18957 canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index); | 19004 canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index); |
18958 if (!canonical_value.IsNull()) { | 19005 if (!canonical_value.IsNull()) { |
18959 return canonical_value.raw(); | 19006 return canonical_value.raw(); |
18960 } | 19007 } |
18961 } | 19008 } |
| 19009 ASSERT(value.IsOld()); |
18962 value.SetCanonical(); | 19010 value.SetCanonical(); |
18963 // The value needs to be added to the constants list. Grow the list if | 19011 // The value needs to be added to the constants list. Grow the list if |
18964 // it is full. | 19012 // it is full. |
18965 cls.InsertCanonicalNumber(zone, index, value); | 19013 cls.InsertCanonicalNumber(zone, index, value); |
18966 return value.raw(); | 19014 return value.raw(); |
18967 } | 19015 } |
18968 } | 19016 } |
18969 | 19017 |
18970 | 19018 |
18971 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used, | 19019 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used, |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19444 Zone* zone = Thread::Current()->zone(); | 19492 Zone* zone = Thread::Current()->zone(); |
19445 return zone->AllocUnsafe(size); | 19493 return zone->AllocUnsafe(size); |
19446 } | 19494 } |
19447 | 19495 |
19448 | 19496 |
19449 const char* Bigint::ToCString() const { | 19497 const char* Bigint::ToCString() const { |
19450 return ToDecCString(&BigintAllocator); | 19498 return ToDecCString(&BigintAllocator); |
19451 } | 19499 } |
19452 | 19500 |
19453 | 19501 |
| 19502 bool Fraction::CanonicalizeEquals(const Instance& other) const { |
| 19503 if (this->raw() == other.raw()) { |
| 19504 return true; // "===". |
| 19505 } |
| 19506 if (other.IsNull() || !other.IsFraction()) { |
| 19507 return false; |
| 19508 } |
| 19509 return (numerator() == Fraction::Cast(other).numerator()) && |
| 19510 (denominator() == Fraction::Cast(other).denominator()); |
| 19511 } |
| 19512 |
| 19513 |
| 19514 RawFraction* Fraction::New(Heap::Space space) { |
| 19515 return Fraction::New(0, 0, space); |
| 19516 } |
| 19517 |
| 19518 |
| 19519 RawFraction* Fraction::New(uint64_t numerator, |
| 19520 uint64_t denominator, |
| 19521 Heap::Space space) { |
| 19522 Thread* thread = Thread::Current(); |
| 19523 Zone* zone = thread->zone(); |
| 19524 Isolate* isolate = thread->isolate(); |
| 19525 ASSERT(isolate->object_store()->fraction_class() != Class::null()); |
| 19526 Fraction& result = Fraction::Handle(zone); |
| 19527 { |
| 19528 RawObject* raw = Object::Allocate(Fraction::kClassId, |
| 19529 Fraction::InstanceSize(), |
| 19530 space); |
| 19531 NoSafepointScope no_safepoint; |
| 19532 result ^= raw; |
| 19533 } |
| 19534 result.set_numerator(Integer::Handle( |
| 19535 Integer::NewFromUint64(numerator, space))); |
| 19536 result.set_denominator(Integer::Handle( |
| 19537 Integer::NewFromUint64(denominator, space))); |
| 19538 return result.raw(); |
| 19539 } |
| 19540 |
| 19541 |
| 19542 void Fraction::set_numerator(const Integer& value) const { |
| 19543 StorePointer(&raw_ptr()->numerator_, value.raw()); |
| 19544 } |
| 19545 |
| 19546 |
| 19547 static bool CStringToFraction(const char* str, |
| 19548 intptr_t length, |
| 19549 uint64_t* numerator, |
| 19550 uint64_t* denominator) { |
| 19551 ASSERT(str != NULL); |
| 19552 ASSERT(length > 0); |
| 19553 const uint64_t max_accum = (1ULL << 63) / 10; |
| 19554 uint64_t num = 0ULL; |
| 19555 uint64_t denom = 1ULL; |
| 19556 bool seen_decimal_point = false; |
| 19557 for (intptr_t i = 0; i < length; i++) { |
| 19558 char c = str[i]; |
| 19559 if (!seen_decimal_point && (c == '.')) { |
| 19560 seen_decimal_point = true; |
| 19561 } else if (('0' <= c) && (c <= '9')) { |
| 19562 // Bail if numerator or denominator get close to Bigint. |
| 19563 if ((num > max_accum) || (denom > max_accum)) { |
| 19564 return false; |
| 19565 } |
| 19566 num = num*10 + (c - '0'); |
| 19567 if (seen_decimal_point) denom *= 10; |
| 19568 } else { |
| 19569 if ((str[i] != 'r') && (str[i] != 'R')) { |
| 19570 return false; |
| 19571 } |
| 19572 break; |
| 19573 } |
| 19574 } |
| 19575 // Reduce somewhat. Do not reduce if denominator is 100. |
| 19576 while ((denom != 100ULL) && ((num & 1) == 0) && ((denom & 1) == 0)) { |
| 19577 num >>= 1; |
| 19578 denom >>= 1; |
| 19579 } |
| 19580 // TODO(regis): Reduce further using gcd. |
| 19581 *numerator = num; |
| 19582 *denominator = denom; |
| 19583 return true; |
| 19584 } |
| 19585 |
| 19586 |
| 19587 RawFraction* Fraction::NewCanonical(const String& str) { |
| 19588 uint64_t nominator; |
| 19589 uint64_t denominator; |
| 19590 if (!CStringToFraction(str.ToCString(), str.Length(), |
| 19591 &nominator, &denominator)) { |
| 19592 // Call the Dart version, which supports Bigint. |
| 19593 // Not supported when called early from core lib itself. |
| 19594 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 19595 ASSERT(!core_lib.IsNull()); |
| 19596 const String& fraction_class_name = Symbols::_Fraction(); |
| 19597 const String& constructor_name = Symbols::DotFromRationalLiteral(); |
| 19598 const Array& constructor_args = Array::Handle(Array::New(1)); |
| 19599 constructor_args.SetAt(0, str); |
| 19600 Object& value = Object::Handle( |
| 19601 DartLibraryCalls::InstanceCreate(core_lib, |
| 19602 fraction_class_name, |
| 19603 constructor_name, |
| 19604 true, // A factory. |
| 19605 constructor_args)); |
| 19606 ASSERT(!value.IsError()); |
| 19607 return Fraction::NewCanonical(Fraction::Cast(value)); |
| 19608 } |
| 19609 return Fraction::NewCanonical(Fraction::Handle( |
| 19610 Fraction::New(nominator, denominator, Heap::kOld))); |
| 19611 } |
| 19612 |
| 19613 |
| 19614 RawFraction* Fraction::NewCanonical(const Fraction& value) { |
| 19615 // TODO(regis): Canonicalize fields. |
| 19616 Thread* thread = Thread::Current(); |
| 19617 Zone* zone = thread->zone(); |
| 19618 Isolate* isolate = thread->isolate(); |
| 19619 const Class& cls = |
| 19620 Class::Handle(zone, isolate->object_store()->fraction_class()); |
| 19621 intptr_t index = 0; |
| 19622 Fraction& canonical_value = Fraction::Handle(zone); |
| 19623 canonical_value ^= cls.LookupCanonicalFraction(zone, value, &index); |
| 19624 if (!canonical_value.IsNull()) { |
| 19625 return canonical_value.raw(); |
| 19626 } |
| 19627 { |
| 19628 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
| 19629 // Retry lookup. |
| 19630 { |
| 19631 canonical_value ^= cls.LookupCanonicalFraction(zone, value, &index); |
| 19632 if (!canonical_value.IsNull()) { |
| 19633 return canonical_value.raw(); |
| 19634 } |
| 19635 } |
| 19636 Fraction& result = Fraction::Handle(zone, value.raw()); |
| 19637 if (result.IsNew()) { |
| 19638 // Create a canonical object in old space. |
| 19639 result ^= Object::Clone(result, Heap::kOld); |
| 19640 } |
| 19641 ASSERT(result.IsOld()); |
| 19642 result.SetCanonical(); |
| 19643 // The value needs to be added to the constants list. Grow the list if |
| 19644 // it is full. |
| 19645 cls.InsertCanonicalNumber(zone, index, result); |
| 19646 return result.raw(); |
| 19647 } |
| 19648 } |
| 19649 |
| 19650 |
| 19651 void Fraction::set_denominator(const Integer& value) const { |
| 19652 StorePointer(&raw_ptr()->denominator_, value.raw()); |
| 19653 } |
| 19654 |
| 19655 |
| 19656 const char* Fraction::ToCString() const { |
| 19657 if (IsNull()) { |
| 19658 return "_Fraction NULL"; |
| 19659 } |
| 19660 return OS::SCreate(Thread::Current()->zone(), "_Fraction %s/%s", |
| 19661 Integer::Handle(numerator()).ToCString(), |
| 19662 Integer::Handle(denominator()).ToCString()); |
| 19663 } |
| 19664 |
| 19665 |
19454 // Synchronize with implementation in compiler (intrinsifier). | 19666 // Synchronize with implementation in compiler (intrinsifier). |
19455 class StringHasher : ValueObject { | 19667 class StringHasher : ValueObject { |
19456 public: | 19668 public: |
19457 StringHasher() : hash_(0) {} | 19669 StringHasher() : hash_(0) {} |
19458 void Add(int32_t ch) { | 19670 void Add(int32_t ch) { |
19459 hash_ = CombineHashes(hash_, ch); | 19671 hash_ = CombineHashes(hash_, ch); |
19460 } | 19672 } |
19461 void Add(const String& str, intptr_t begin_index, intptr_t len); | 19673 void Add(const String& str, intptr_t begin_index, intptr_t len); |
19462 | 19674 |
19463 // Return a non-zero hash of at most 'bits' bits. | 19675 // Return a non-zero hash of at most 'bits' bits. |
(...skipping 3131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
22595 return UserTag::null(); | 22807 return UserTag::null(); |
22596 } | 22808 } |
22597 | 22809 |
22598 | 22810 |
22599 const char* UserTag::ToCString() const { | 22811 const char* UserTag::ToCString() const { |
22600 const String& tag_label = String::Handle(label()); | 22812 const String& tag_label = String::Handle(label()); |
22601 return tag_label.ToCString(); | 22813 return tag_label.ToCString(); |
22602 } | 22814 } |
22603 | 22815 |
22604 } // namespace dart | 22816 } // namespace dart |
OLD | NEW |