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

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

Issue 2893553002: 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
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 6734 matching lines...) Expand 10 before | Expand all | Expand 10 after
6745 // 64-bit architecture stay in Smi range when loaded on a 32-bit 6745 // 64-bit architecture stay in Smi range when loaded on a 32-bit
6746 // architecture. 6746 // architecture.
6747 static const intptr_t kHashBits = 30; 6747 static const intptr_t kHashBits = 30;
6748 6748
6749 static const intptr_t kOneByteChar = 1; 6749 static const intptr_t kOneByteChar = 1;
6750 static const intptr_t kTwoByteChar = 2; 6750 static const intptr_t kTwoByteChar = 2;
6751 6751
6752 // All strings share the same maximum element count to keep things 6752 // All strings share the same maximum element count to keep things
6753 // simple. We choose a value that will prevent integer overflow for 6753 // simple. We choose a value that will prevent integer overflow for
6754 // 2 byte strings, since it is the worst case. 6754 // 2 byte strings, since it is the worst case.
6755 static const intptr_t kSizeofRawString = 6755 #if defined(HASH_IN_OBJECT_HEADER)
6756 sizeof(RawInstance) + (2 * kWordSize); 6756 static const intptr_t kSizeofRawString = sizeof(RawInstance) + kWordSize;
6757 #else
6758 static const intptr_t kSizeofRawString = sizeof(RawInstance) + 2 * kWordSize;
6759 #endif
6757 static const intptr_t kMaxElements = kSmiMax / kTwoByteChar; 6760 static const intptr_t kMaxElements = kSmiMax / kTwoByteChar;
6758 6761
6759 class CodePointIterator : public ValueObject { 6762 class CodePointIterator : public ValueObject {
6760 public: 6763 public:
6761 explicit CodePointIterator(const String& str) 6764 explicit CodePointIterator(const String& str)
6762 : str_(str), ch_(0), index_(-1), end_(str.Length()) { 6765 : str_(str), ch_(0), index_(-1), end_(str.Length()) {
6763 ASSERT(!str_.IsNull()); 6766 ASSERT(!str_.IsNull());
6764 } 6767 }
6765 6768
6766 CodePointIterator(const String& str, intptr_t start, intptr_t length) 6769 CodePointIterator(const String& str, intptr_t start, intptr_t length)
(...skipping 15 matching lines...) Expand all
6782 int32_t ch_; 6785 int32_t ch_;
6783 intptr_t index_; 6786 intptr_t index_;
6784 intptr_t end_; 6787 intptr_t end_;
6785 DISALLOW_IMPLICIT_CONSTRUCTORS(CodePointIterator); 6788 DISALLOW_IMPLICIT_CONSTRUCTORS(CodePointIterator);
6786 }; 6789 };
6787 6790
6788 intptr_t Length() const { return Smi::Value(raw_ptr()->length_); } 6791 intptr_t Length() const { return Smi::Value(raw_ptr()->length_); }
6789 static intptr_t length_offset() { return OFFSET_OF(RawString, length_); } 6792 static intptr_t length_offset() { return OFFSET_OF(RawString, length_); }
6790 6793
6791 intptr_t Hash() const { 6794 intptr_t Hash() const {
6792 intptr_t result = Smi::Value(raw_ptr()->hash_); 6795 intptr_t result = GetRawHash();
Vyacheslav Egorov (Google) 2017/05/18 06:14:42 Maybe call it GetCachedHash(...)?
erikcorry 2017/05/18 14:28:38 Done.
6793 if (result != 0) { 6796 if (result != 0) {
6794 return result; 6797 return result;
6795 } 6798 }
6796 result = String::Hash(*this, 0, this->Length()); 6799 result = String::Hash(*this, 0, this->Length());
6797 this->SetHash(result); 6800 this->SetHash(result);
6798 return result; 6801 return result;
6799 } 6802 }
6800 6803
6801 bool HasHash() const { 6804 bool HasHash() const {
6802 ASSERT(Smi::New(0) == NULL); 6805 ASSERT(Smi::New(0) == NULL);
6803 return (raw_ptr()->hash_ != NULL); 6806 return GetRawHash() != 0;
6804 } 6807 }
6805 6808
6809 #if defined(HASH_IN_OBJECT_HEADER)
6810 static intptr_t hash_offset() { return kInt32Size; } // Wrong for big-endian?
Vyacheslav Egorov (Google) 2017/05/18 06:14:42 we don't support big-endian afaik
erikcorry 2017/05/18 14:28:38 No, but if we ever do, it's nice to leave hints th
6811 #else
6806 static intptr_t hash_offset() { return OFFSET_OF(RawString, hash_); } 6812 static intptr_t hash_offset() { return OFFSET_OF(RawString, hash_); }
6813 #endif
6814 uint32_t GetRawHash() const { return raw()->GetRawHash(); }
6815 void SetRawHash(uint32_t hash) { raw()->SetRawHash(hash); }
6807 static intptr_t Hash(const String& str, intptr_t begin_index, intptr_t len); 6816 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); 6817 static intptr_t Hash(const char* characters, intptr_t len);
6809 static intptr_t Hash(const uint16_t* characters, intptr_t len); 6818 static intptr_t Hash(const uint16_t* characters, intptr_t len);
6810 static intptr_t Hash(const int32_t* characters, intptr_t len); 6819 static intptr_t Hash(const int32_t* characters, intptr_t len);
6811 static intptr_t HashRawSymbol(const RawString* symbol) { 6820 static intptr_t HashRawSymbol(const RawString* symbol) {
6812 ASSERT(symbol->IsCanonical()); 6821 ASSERT(symbol->IsCanonical());
6813 intptr_t result = Smi::Value(symbol->ptr()->hash_); 6822 intptr_t result = symbol->GetRawHash();
6814 ASSERT(result != 0); 6823 ASSERT(result != 0);
6815 return result; 6824 return result;
6816 } 6825 }
6817 6826
6818 // Returns the hash of str1 + str2. 6827 // Returns the hash of str1 + str2.
6819 static intptr_t HashConcat(const String& str1, const String& str2); 6828 static intptr_t HashConcat(const String& str1, const String& str2);
6820 6829
6821 virtual RawObject* HashCode() const { return Integer::New(Hash()); } 6830 virtual RawObject* HashCode() const { return Integer::New(Hash()); }
6822 6831
6823 uint16_t CharAt(intptr_t index) const; 6832 uint16_t CharAt(intptr_t index) const;
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
7035 // by friendly templated code (e.g., Symbols). 7044 // by friendly templated code (e.g., Symbols).
7036 bool Equals(const uint8_t* characters, intptr_t len) const; 7045 bool Equals(const uint8_t* characters, intptr_t len) const;
7037 static intptr_t Hash(const uint8_t* characters, intptr_t len); 7046 static intptr_t Hash(const uint8_t* characters, intptr_t len);
7038 7047
7039 void SetLength(intptr_t value) const { 7048 void SetLength(intptr_t value) const {
7040 // This is only safe because we create a new Smi, which does not cause 7049 // This is only safe because we create a new Smi, which does not cause
7041 // heap allocation. 7050 // heap allocation.
7042 StoreSmi(&raw_ptr()->length_, Smi::New(value)); 7051 StoreSmi(&raw_ptr()->length_, Smi::New(value));
7043 } 7052 }
7044 7053
7045 void SetHash(intptr_t value) const { 7054 void SetHash(intptr_t value) const { raw()->SetRawHash(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 7055
7051 template <typename HandleType, typename ElementType, typename CallbackType> 7056 template <typename HandleType, typename ElementType, typename CallbackType>
7052 static void ReadFromImpl(SnapshotReader* reader, 7057 static void ReadFromImpl(SnapshotReader* reader,
7053 String* str_obj, 7058 String* str_obj,
7054 intptr_t len, 7059 intptr_t len,
7055 intptr_t tags, 7060 intptr_t tags,
7056 CallbackType new_symbol, 7061 CallbackType new_symbol,
7057 Snapshot::Kind kind); 7062 Snapshot::Kind kind);
7058 7063
7059 FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance); 7064 FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
7098 7103
7099 static intptr_t InstanceSize() { 7104 static intptr_t InstanceSize() {
7100 ASSERT(sizeof(RawOneByteString) == 7105 ASSERT(sizeof(RawOneByteString) ==
7101 OFFSET_OF_RETURNED_VALUE(RawOneByteString, data)); 7106 OFFSET_OF_RETURNED_VALUE(RawOneByteString, data));
7102 return 0; 7107 return 0;
7103 } 7108 }
7104 7109
7105 static intptr_t InstanceSize(intptr_t len) { 7110 static intptr_t InstanceSize(intptr_t len) {
7106 ASSERT(sizeof(RawOneByteString) == String::kSizeofRawString); 7111 ASSERT(sizeof(RawOneByteString) == String::kSizeofRawString);
7107 ASSERT(0 <= len && len <= kMaxElements); 7112 ASSERT(0 <= len && len <= kMaxElements);
7113 #if defined(HASH_IN_OBJECT_HEADER)
7114 // We have to pad zero-length raw strings so that they can be externalized.
7115 // If we don't pad, then the external string object does not fit in the
7116 // memory allocated for the raw string.
7117 if (len == 0) return InstanceSize(1);
7118 #endif
7108 return String::RoundedAllocationSize(sizeof(RawOneByteString) + 7119 return String::RoundedAllocationSize(sizeof(RawOneByteString) +
7109 (len * kBytesPerElement)); 7120 (len * kBytesPerElement));
7110 } 7121 }
7111 7122
7112 static RawOneByteString* New(intptr_t len, Heap::Space space); 7123 static RawOneByteString* New(intptr_t len, Heap::Space space);
7113 static RawOneByteString* New(const char* c_string, 7124 static RawOneByteString* New(const char* c_string,
7114 Heap::Space space = Heap::kNew) { 7125 Heap::Space space = Heap::kNew) {
7115 return New(reinterpret_cast<const uint8_t*>(c_string), strlen(c_string), 7126 return New(reinterpret_cast<const uint8_t*>(c_string), strlen(c_string),
7116 space); 7127 space);
7117 } 7128 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
7231 7242
7232 static intptr_t InstanceSize() { 7243 static intptr_t InstanceSize() {
7233 ASSERT(sizeof(RawTwoByteString) == 7244 ASSERT(sizeof(RawTwoByteString) ==
7234 OFFSET_OF_RETURNED_VALUE(RawTwoByteString, data)); 7245 OFFSET_OF_RETURNED_VALUE(RawTwoByteString, data));
7235 return 0; 7246 return 0;
7236 } 7247 }
7237 7248
7238 static intptr_t InstanceSize(intptr_t len) { 7249 static intptr_t InstanceSize(intptr_t len) {
7239 ASSERT(sizeof(RawTwoByteString) == String::kSizeofRawString); 7250 ASSERT(sizeof(RawTwoByteString) == String::kSizeofRawString);
7240 ASSERT(0 <= len && len <= kMaxElements); 7251 ASSERT(0 <= len && len <= kMaxElements);
7252 // We have to pad zero-length raw strings so that they can be externalized.
7253 // If we don't pad, then the external string object does not fit in the
7254 // memory allocated for the raw string.
7255 if (len == 0) return InstanceSize(1);
7241 return String::RoundedAllocationSize(sizeof(RawTwoByteString) + 7256 return String::RoundedAllocationSize(sizeof(RawTwoByteString) +
7242 (len * kBytesPerElement)); 7257 (len * kBytesPerElement));
7243 } 7258 }
7244 7259
7245 static RawTwoByteString* New(intptr_t len, Heap::Space space); 7260 static RawTwoByteString* New(intptr_t len, Heap::Space space);
7246 static RawTwoByteString* New(const uint16_t* characters, 7261 static RawTwoByteString* New(const uint16_t* characters,
7247 intptr_t len, 7262 intptr_t len,
7248 Heap::Space space); 7263 Heap::Space space);
7249 static RawTwoByteString* New(intptr_t utf16_len, 7264 static RawTwoByteString* New(intptr_t utf16_len,
7250 const int32_t* characters, 7265 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. 8939 return false; // Two symbols that aren't identical aren't equal.
8925 } 8940 }
8926 if (HasHash() && str.HasHash() && (Hash() != str.Hash())) { 8941 if (HasHash() && str.HasHash() && (Hash() != str.Hash())) {
8927 return false; // Both sides have hash codes and they do not match. 8942 return false; // Both sides have hash codes and they do not match.
8928 } 8943 }
8929 return Equals(str, 0, str.Length()); 8944 return Equals(str, 0, str.Length());
8930 } 8945 }
8931 8946
8932 8947
8933 intptr_t Library::UrlHash() const { 8948 intptr_t Library::UrlHash() const {
8934 intptr_t result = Smi::Value(url()->ptr()->hash_); 8949 intptr_t result = url()->GetRawHash();
8935 ASSERT(result != 0); 8950 ASSERT(result != 0);
8936 return result; 8951 return result;
8937 } 8952 }
8938 8953
8939 8954
8940 void MegamorphicCache::SetEntry(const Array& array, 8955 void MegamorphicCache::SetEntry(const Array& array,
8941 intptr_t index, 8956 intptr_t index,
8942 const Smi& class_id, 8957 const Smi& class_id,
8943 const Function& target) { 8958 const Function& target) {
8944 array.SetAt((index * kEntryLength) + kClassIdIndex, class_id); 8959 array.SetAt((index * kEntryLength) + kClassIdIndex, class_id);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
9018 9033
9019 inline void TypeArguments::SetHash(intptr_t value) const { 9034 inline void TypeArguments::SetHash(intptr_t value) const {
9020 // This is only safe because we create a new Smi, which does not cause 9035 // This is only safe because we create a new Smi, which does not cause
9021 // heap allocation. 9036 // heap allocation.
9022 StoreSmi(&raw_ptr()->hash_, Smi::New(value)); 9037 StoreSmi(&raw_ptr()->hash_, Smi::New(value));
9023 } 9038 }
9024 9039
9025 } // namespace dart 9040 } // namespace dart
9026 9041
9027 #endif // RUNTIME_VM_OBJECT_H_ 9042 #endif // RUNTIME_VM_OBJECT_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698