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

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

Issue 2893553002: More compact string representation on 64 bit. (Closed)
Patch Set: Slava feedback 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 6300 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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_
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