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