| 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 #ifndef RUNTIME_VM_OBJECT_H_ | 5 #ifndef RUNTIME_VM_OBJECT_H_ |
| 6 #define RUNTIME_VM_OBJECT_H_ | 6 #define RUNTIME_VM_OBJECT_H_ |
| 7 | 7 |
| 8 #include "include/dart_api.h" | 8 #include "include/dart_api.h" |
| 9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
| 10 #include "platform/utils.h" | 10 #include "platform/utils.h" |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 ASSERT(sentinel_ != NULL); | 425 ASSERT(sentinel_ != NULL); |
| 426 return *sentinel_; | 426 return *sentinel_; |
| 427 } | 427 } |
| 428 // Value marking that we are transitioning from sentinel, e.g., computing | 428 // Value marking that we are transitioning from sentinel, e.g., computing |
| 429 // a field value. Used to detect circular initialization. | 429 // a field value. Used to detect circular initialization. |
| 430 static const Instance& transition_sentinel() { | 430 static const Instance& transition_sentinel() { |
| 431 ASSERT(transition_sentinel_ != NULL); | 431 ASSERT(transition_sentinel_ != NULL); |
| 432 return *transition_sentinel_; | 432 return *transition_sentinel_; |
| 433 } | 433 } |
| 434 | 434 |
| 435 #if defined(HASH_IN_OBJECT_HEADER) |
| 436 static uint32_t GetCachedHash(const RawObject* obj) { |
| 437 uword tags = obj->ptr()->tags_; |
| 438 return tags >> 32; |
| 439 } |
| 440 |
| 441 static void SetCachedHash(RawObject* obj, uintptr_t hash) { |
| 442 ASSERT(hash >> 32 == 0); |
| 443 obj->ptr()->tags_ |= hash << 32; |
| 444 } |
| 445 #endif |
| 446 |
| 435 // Compiler's constant propagation constants. | 447 // Compiler's constant propagation constants. |
| 436 static const Instance& unknown_constant() { | 448 static const Instance& unknown_constant() { |
| 437 ASSERT(unknown_constant_ != NULL); | 449 ASSERT(unknown_constant_ != NULL); |
| 438 return *unknown_constant_; | 450 return *unknown_constant_; |
| 439 } | 451 } |
| 440 static const Instance& non_constant() { | 452 static const Instance& non_constant() { |
| 441 ASSERT(non_constant_ != NULL); | 453 ASSERT(non_constant_ != NULL); |
| 442 return *non_constant_; | 454 return *non_constant_; |
| 443 } | 455 } |
| 444 | 456 |
| (...skipping 6302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6747 // 64-bit architecture stay in Smi range when loaded on a 32-bit | 6759 // 64-bit architecture stay in Smi range when loaded on a 32-bit |
| 6748 // architecture. | 6760 // architecture. |
| 6749 static const intptr_t kHashBits = 30; | 6761 static const intptr_t kHashBits = 30; |
| 6750 | 6762 |
| 6751 static const intptr_t kOneByteChar = 1; | 6763 static const intptr_t kOneByteChar = 1; |
| 6752 static const intptr_t kTwoByteChar = 2; | 6764 static const intptr_t kTwoByteChar = 2; |
| 6753 | 6765 |
| 6754 // All strings share the same maximum element count to keep things | 6766 // All strings share the same maximum element count to keep things |
| 6755 // simple. We choose a value that will prevent integer overflow for | 6767 // simple. We choose a value that will prevent integer overflow for |
| 6756 // 2 byte strings, since it is the worst case. | 6768 // 2 byte strings, since it is the worst case. |
| 6757 static const intptr_t kSizeofRawString = | 6769 #if defined(HASH_IN_OBJECT_HEADER) |
| 6758 sizeof(RawInstance) + (2 * kWordSize); | 6770 static const intptr_t kSizeofRawString = sizeof(RawInstance) + kWordSize; |
| 6771 #else |
| 6772 static const intptr_t kSizeofRawString = sizeof(RawInstance) + 2 * kWordSize; |
| 6773 #endif |
| 6759 static const intptr_t kMaxElements = kSmiMax / kTwoByteChar; | 6774 static const intptr_t kMaxElements = kSmiMax / kTwoByteChar; |
| 6760 | 6775 |
| 6761 class CodePointIterator : public ValueObject { | 6776 class CodePointIterator : public ValueObject { |
| 6762 public: | 6777 public: |
| 6763 explicit CodePointIterator(const String& str) | 6778 explicit CodePointIterator(const String& str) |
| 6764 : str_(str), ch_(0), index_(-1), end_(str.Length()) { | 6779 : str_(str), ch_(0), index_(-1), end_(str.Length()) { |
| 6765 ASSERT(!str_.IsNull()); | 6780 ASSERT(!str_.IsNull()); |
| 6766 } | 6781 } |
| 6767 | 6782 |
| 6768 CodePointIterator(const String& str, intptr_t start, intptr_t length) | 6783 CodePointIterator(const String& str, intptr_t start, intptr_t length) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6784 int32_t ch_; | 6799 int32_t ch_; |
| 6785 intptr_t index_; | 6800 intptr_t index_; |
| 6786 intptr_t end_; | 6801 intptr_t end_; |
| 6787 DISALLOW_IMPLICIT_CONSTRUCTORS(CodePointIterator); | 6802 DISALLOW_IMPLICIT_CONSTRUCTORS(CodePointIterator); |
| 6788 }; | 6803 }; |
| 6789 | 6804 |
| 6790 intptr_t Length() const { return Smi::Value(raw_ptr()->length_); } | 6805 intptr_t Length() const { return Smi::Value(raw_ptr()->length_); } |
| 6791 static intptr_t length_offset() { return OFFSET_OF(RawString, length_); } | 6806 static intptr_t length_offset() { return OFFSET_OF(RawString, length_); } |
| 6792 | 6807 |
| 6793 intptr_t Hash() const { | 6808 intptr_t Hash() const { |
| 6794 intptr_t result = Smi::Value(raw_ptr()->hash_); | 6809 intptr_t result = GetCachedHash(raw()); |
| 6795 if (result != 0) { | 6810 if (result != 0) { |
| 6796 return result; | 6811 return result; |
| 6797 } | 6812 } |
| 6798 result = String::Hash(*this, 0, this->Length()); | 6813 result = String::Hash(*this, 0, this->Length()); |
| 6799 this->SetHash(result); | 6814 SetCachedHash(raw(), result); |
| 6800 return result; | 6815 return result; |
| 6801 } | 6816 } |
| 6802 | 6817 |
| 6803 bool HasHash() const { | 6818 bool HasHash() const { |
| 6804 ASSERT(Smi::New(0) == NULL); | 6819 ASSERT(Smi::New(0) == NULL); |
| 6805 return (raw_ptr()->hash_ != NULL); | 6820 return GetCachedHash(raw()) != 0; |
| 6806 } | 6821 } |
| 6807 | 6822 |
| 6823 #if defined(HASH_IN_OBJECT_HEADER) |
| 6824 static intptr_t hash_offset() { return kInt32Size; } // Wrong for big-endian? |
| 6825 #else |
| 6808 static intptr_t hash_offset() { return OFFSET_OF(RawString, hash_); } | 6826 static intptr_t hash_offset() { return OFFSET_OF(RawString, hash_); } |
| 6827 #endif |
| 6809 static intptr_t Hash(const String& str, intptr_t begin_index, intptr_t len); | 6828 static intptr_t Hash(const String& str, intptr_t begin_index, intptr_t len); |
| 6810 static intptr_t Hash(const char* characters, intptr_t len); | 6829 static intptr_t Hash(const char* characters, intptr_t len); |
| 6811 static intptr_t Hash(const uint16_t* characters, intptr_t len); | 6830 static intptr_t Hash(const uint16_t* characters, intptr_t len); |
| 6812 static intptr_t Hash(const int32_t* characters, intptr_t len); | 6831 static intptr_t Hash(const int32_t* characters, intptr_t len); |
| 6813 static intptr_t HashRawSymbol(const RawString* symbol) { | 6832 static intptr_t HashRawSymbol(const RawString* symbol) { |
| 6814 ASSERT(symbol->IsCanonical()); | 6833 ASSERT(symbol->IsCanonical()); |
| 6815 intptr_t result = Smi::Value(symbol->ptr()->hash_); | 6834 intptr_t result = GetCachedHash(symbol); |
| 6816 ASSERT(result != 0); | 6835 ASSERT(result != 0); |
| 6817 return result; | 6836 return result; |
| 6818 } | 6837 } |
| 6819 | 6838 |
| 6820 // Returns the hash of str1 + str2. | 6839 // Returns the hash of str1 + str2. |
| 6821 static intptr_t HashConcat(const String& str1, const String& str2); | 6840 static intptr_t HashConcat(const String& str1, const String& str2); |
| 6822 | 6841 |
| 6823 virtual RawObject* HashCode() const { return Integer::New(Hash()); } | 6842 virtual RawObject* HashCode() const { return Integer::New(Hash()); } |
| 6824 | 6843 |
| 6825 uint16_t CharAt(intptr_t index) const; | 6844 uint16_t CharAt(intptr_t index) const; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7024 PRINTF_ATTRIBUTE(2, 3); | 7043 PRINTF_ATTRIBUTE(2, 3); |
| 7025 static RawString* NewFormattedV(const char* format, | 7044 static RawString* NewFormattedV(const char* format, |
| 7026 va_list args, | 7045 va_list args, |
| 7027 Heap::Space space = Heap::kNew); | 7046 Heap::Space space = Heap::kNew); |
| 7028 | 7047 |
| 7029 static bool ParseDouble(const String& str, | 7048 static bool ParseDouble(const String& str, |
| 7030 intptr_t start, | 7049 intptr_t start, |
| 7031 intptr_t end, | 7050 intptr_t end, |
| 7032 double* result); | 7051 double* result); |
| 7033 | 7052 |
| 7053 #if !defined(HASH_IN_OBJECT_HEADER) |
| 7054 static uint32_t GetCachedHash(const RawString* obj) { |
| 7055 return Smi::Value(obj->ptr()->hash_); |
| 7056 } |
| 7057 |
| 7058 static void SetCachedHash(RawString* obj, uintptr_t hash) { |
| 7059 obj->ptr()->hash_ = Smi::New(hash); |
| 7060 } |
| 7061 #endif |
| 7062 |
| 7034 protected: | 7063 protected: |
| 7035 // These two operate on an array of Latin-1 encoded characters. | 7064 // These two operate on an array of Latin-1 encoded characters. |
| 7036 // They are protected to avoid mistaking Latin-1 for UTF-8, but used | 7065 // They are protected to avoid mistaking Latin-1 for UTF-8, but used |
| 7037 // by friendly templated code (e.g., Symbols). | 7066 // by friendly templated code (e.g., Symbols). |
| 7038 bool Equals(const uint8_t* characters, intptr_t len) const; | 7067 bool Equals(const uint8_t* characters, intptr_t len) const; |
| 7039 static intptr_t Hash(const uint8_t* characters, intptr_t len); | 7068 static intptr_t Hash(const uint8_t* characters, intptr_t len); |
| 7040 | 7069 |
| 7041 void SetLength(intptr_t value) const { | 7070 void SetLength(intptr_t value) const { |
| 7042 // This is only safe because we create a new Smi, which does not cause | 7071 // This is only safe because we create a new Smi, which does not cause |
| 7043 // heap allocation. | 7072 // heap allocation. |
| 7044 StoreSmi(&raw_ptr()->length_, Smi::New(value)); | 7073 StoreSmi(&raw_ptr()->length_, Smi::New(value)); |
| 7045 } | 7074 } |
| 7046 | 7075 |
| 7047 void SetHash(intptr_t value) const { | 7076 void SetHash(intptr_t value) const { SetCachedHash(raw(), value); } |
| 7048 // This is only safe because we create a new Smi, which does not cause | |
| 7049 // heap allocation. | |
| 7050 StoreSmi(&raw_ptr()->hash_, Smi::New(value)); | |
| 7051 } | |
| 7052 | 7077 |
| 7053 template <typename HandleType, typename ElementType, typename CallbackType> | 7078 template <typename HandleType, typename ElementType, typename CallbackType> |
| 7054 static void ReadFromImpl(SnapshotReader* reader, | 7079 static void ReadFromImpl(SnapshotReader* reader, |
| 7055 String* str_obj, | 7080 String* str_obj, |
| 7056 intptr_t len, | 7081 intptr_t len, |
| 7057 intptr_t tags, | 7082 intptr_t tags, |
| 7058 CallbackType new_symbol, | 7083 CallbackType new_symbol, |
| 7059 Snapshot::Kind kind); | 7084 Snapshot::Kind kind); |
| 7060 | 7085 |
| 7061 FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance); | 7086 FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7100 | 7125 |
| 7101 static intptr_t InstanceSize() { | 7126 static intptr_t InstanceSize() { |
| 7102 ASSERT(sizeof(RawOneByteString) == | 7127 ASSERT(sizeof(RawOneByteString) == |
| 7103 OFFSET_OF_RETURNED_VALUE(RawOneByteString, data)); | 7128 OFFSET_OF_RETURNED_VALUE(RawOneByteString, data)); |
| 7104 return 0; | 7129 return 0; |
| 7105 } | 7130 } |
| 7106 | 7131 |
| 7107 static intptr_t InstanceSize(intptr_t len) { | 7132 static intptr_t InstanceSize(intptr_t len) { |
| 7108 ASSERT(sizeof(RawOneByteString) == String::kSizeofRawString); | 7133 ASSERT(sizeof(RawOneByteString) == String::kSizeofRawString); |
| 7109 ASSERT(0 <= len && len <= kMaxElements); | 7134 ASSERT(0 <= len && len <= kMaxElements); |
| 7135 #if defined(HASH_IN_OBJECT_HEADER) |
| 7136 // We have to pad zero-length raw strings so that they can be externalized. |
| 7137 // If we don't pad, then the external string object does not fit in the |
| 7138 // memory allocated for the raw string. |
| 7139 if (len == 0) return InstanceSize(1); |
| 7140 #endif |
| 7110 return String::RoundedAllocationSize(sizeof(RawOneByteString) + | 7141 return String::RoundedAllocationSize(sizeof(RawOneByteString) + |
| 7111 (len * kBytesPerElement)); | 7142 (len * kBytesPerElement)); |
| 7112 } | 7143 } |
| 7113 | 7144 |
| 7114 static RawOneByteString* New(intptr_t len, Heap::Space space); | 7145 static RawOneByteString* New(intptr_t len, Heap::Space space); |
| 7115 static RawOneByteString* New(const char* c_string, | 7146 static RawOneByteString* New(const char* c_string, |
| 7116 Heap::Space space = Heap::kNew) { | 7147 Heap::Space space = Heap::kNew) { |
| 7117 return New(reinterpret_cast<const uint8_t*>(c_string), strlen(c_string), | 7148 return New(reinterpret_cast<const uint8_t*>(c_string), strlen(c_string), |
| 7118 space); | 7149 space); |
| 7119 } | 7150 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7233 | 7264 |
| 7234 static intptr_t InstanceSize() { | 7265 static intptr_t InstanceSize() { |
| 7235 ASSERT(sizeof(RawTwoByteString) == | 7266 ASSERT(sizeof(RawTwoByteString) == |
| 7236 OFFSET_OF_RETURNED_VALUE(RawTwoByteString, data)); | 7267 OFFSET_OF_RETURNED_VALUE(RawTwoByteString, data)); |
| 7237 return 0; | 7268 return 0; |
| 7238 } | 7269 } |
| 7239 | 7270 |
| 7240 static intptr_t InstanceSize(intptr_t len) { | 7271 static intptr_t InstanceSize(intptr_t len) { |
| 7241 ASSERT(sizeof(RawTwoByteString) == String::kSizeofRawString); | 7272 ASSERT(sizeof(RawTwoByteString) == String::kSizeofRawString); |
| 7242 ASSERT(0 <= len && len <= kMaxElements); | 7273 ASSERT(0 <= len && len <= kMaxElements); |
| 7274 // We have to pad zero-length raw strings so that they can be externalized. |
| 7275 // If we don't pad, then the external string object does not fit in the |
| 7276 // memory allocated for the raw string. |
| 7277 if (len == 0) return InstanceSize(1); |
| 7243 return String::RoundedAllocationSize(sizeof(RawTwoByteString) + | 7278 return String::RoundedAllocationSize(sizeof(RawTwoByteString) + |
| 7244 (len * kBytesPerElement)); | 7279 (len * kBytesPerElement)); |
| 7245 } | 7280 } |
| 7246 | 7281 |
| 7247 static RawTwoByteString* New(intptr_t len, Heap::Space space); | 7282 static RawTwoByteString* New(intptr_t len, Heap::Space space); |
| 7248 static RawTwoByteString* New(const uint16_t* characters, | 7283 static RawTwoByteString* New(const uint16_t* characters, |
| 7249 intptr_t len, | 7284 intptr_t len, |
| 7250 Heap::Space space); | 7285 Heap::Space space); |
| 7251 static RawTwoByteString* New(intptr_t utf16_len, | 7286 static RawTwoByteString* New(intptr_t utf16_len, |
| 7252 const int32_t* characters, | 7287 const int32_t* characters, |
| (...skipping 1673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8926 return false; // Two symbols that aren't identical aren't equal. | 8961 return false; // Two symbols that aren't identical aren't equal. |
| 8927 } | 8962 } |
| 8928 if (HasHash() && str.HasHash() && (Hash() != str.Hash())) { | 8963 if (HasHash() && str.HasHash() && (Hash() != str.Hash())) { |
| 8929 return false; // Both sides have hash codes and they do not match. | 8964 return false; // Both sides have hash codes and they do not match. |
| 8930 } | 8965 } |
| 8931 return Equals(str, 0, str.Length()); | 8966 return Equals(str, 0, str.Length()); |
| 8932 } | 8967 } |
| 8933 | 8968 |
| 8934 | 8969 |
| 8935 intptr_t Library::UrlHash() const { | 8970 intptr_t Library::UrlHash() const { |
| 8936 intptr_t result = Smi::Value(url()->ptr()->hash_); | 8971 intptr_t result = String::GetCachedHash(url()); |
| 8937 ASSERT(result != 0); | 8972 ASSERT(result != 0); |
| 8938 return result; | 8973 return result; |
| 8939 } | 8974 } |
| 8940 | 8975 |
| 8941 | 8976 |
| 8942 void MegamorphicCache::SetEntry(const Array& array, | 8977 void MegamorphicCache::SetEntry(const Array& array, |
| 8943 intptr_t index, | 8978 intptr_t index, |
| 8944 const Smi& class_id, | 8979 const Smi& class_id, |
| 8945 const Function& target) { | 8980 const Function& target) { |
| 8946 array.SetAt((index * kEntryLength) + kClassIdIndex, class_id); | 8981 array.SetAt((index * kEntryLength) + kClassIdIndex, class_id); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9020 | 9055 |
| 9021 inline void TypeArguments::SetHash(intptr_t value) const { | 9056 inline void TypeArguments::SetHash(intptr_t value) const { |
| 9022 // This is only safe because we create a new Smi, which does not cause | 9057 // This is only safe because we create a new Smi, which does not cause |
| 9023 // heap allocation. | 9058 // heap allocation. |
| 9024 StoreSmi(&raw_ptr()->hash_, Smi::New(value)); | 9059 StoreSmi(&raw_ptr()->hash_, Smi::New(value)); |
| 9025 } | 9060 } |
| 9026 | 9061 |
| 9027 } // namespace dart | 9062 } // namespace dart |
| 9028 | 9063 |
| 9029 #endif // RUNTIME_VM_OBJECT_H_ | 9064 #endif // RUNTIME_VM_OBJECT_H_ |
| OLD | NEW |