| 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 | 
|---|