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

Side by Side Diff: runtime/vm/object.h

Issue 2895183002: More compact string representation on 64 bit. (Closed)
Patch Set: Created 3 years, 7 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/intrinsifier_x64.cc ('k') | runtime/vm/object.cc » ('j') | 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 #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
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
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
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
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
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
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
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
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_
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_x64.cc ('k') | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698