| // Copyright 2025 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_OBJECTS_NUMBER_STRING_CACHE_H_ |
| #define V8_OBJECTS_NUMBER_STRING_CACHE_H_ |
| |
| #include "src/common/globals.h" |
| #include "src/handles/maybe-handles.h" |
| #include "src/objects/fixed-array.h" |
| #include "src/objects/objects.h" |
| #include "src/objects/smi.h" |
| |
| // Has to be the last include (doesn't have include guards): |
| #include "src/objects/object-macros.h" |
| |
| namespace v8::internal { |
| |
| // Used for mapping non-zero Smi to Strings. |
| V8_OBJECT class SmiStringCache : public FixedArray { |
| public: |
| using Super = FixedArray; |
| |
| // Empty entries are initialized with this sentinel (both key and value). |
| static constexpr Tagged<Smi> kEmptySentinel = Smi::zero(); |
| |
| static constexpr int kEntryKeyIndex = 0; |
| static constexpr int kEntryValueIndex = 1; |
| static constexpr uint32_t kEntrySize = 2; |
| |
| static constexpr uint32_t kInitialSize = 128; |
| |
| // Maximal allowed capacity in number of entries. |
| static constexpr uint32_t kMaxCapacity = |
| FixedArray::kMaxCapacity / kEntrySize; |
| |
| inline uint32_t capacity() const; |
| |
| // Clears all entries in the table. |
| inline void Clear(); |
| |
| // Iterates the table and computes the number of occupied entries. |
| uint32_t GetUsedEntriesCount(); |
| |
| // Prints contents of the cache with a comment. |
| void Print(const char* comment); |
| |
| // Returns entry index corresponding to given number. |
| inline InternalIndex GetEntryFor(Tagged<Smi> number) const; |
| static inline InternalIndex GetEntryFor(Isolate* isolate, Tagged<Smi> number); |
| |
| // Attempt to find the number in a cache. In case of success, returns |
| // the string representation of the number. Otherwise returns undefined. |
| static inline Handle<Object> Get(Isolate* isolate, InternalIndex entry, |
| Tagged<Smi> number); |
| |
| // Puts <number, string> entry to the cache, potentially overwriting |
| // existing entry. |
| static inline void Set(Isolate* isolate, InternalIndex entry, |
| Tagged<Smi> number, DirectHandle<String> string); |
| |
| template <class IsolateT> |
| static inline DirectHandle<SmiStringCache> New(IsolateT* isolate, |
| uint32_t capacity); |
| |
| protected: |
| using Super::capacity; |
| using Super::get; |
| using Super::length; |
| using Super::OffsetOfElementAt; |
| using Super::set; |
| } V8_OBJECT_END; |
| |
| // Used for mapping raw doubles to Strings. |
| V8_OBJECT class DoubleStringCache : public HeapObject { |
| public: |
| V8_OBJECT struct Entry { |
| UnalignedDoubleMember key_; |
| TaggedMember<UnionOf<Smi, String>> value_; |
| } V8_OBJECT_END; |
| |
| using Header = HeapObject; |
| |
| // Empty entries are initialized with this sentinel (both key and value). |
| static constexpr Tagged<Smi> kEmptySentinel = Smi::zero(); |
| |
| static constexpr int kInitialSize = 128; |
| static constexpr int kMaxCapacity = TAGGED_SIZE_8_BYTES ? 0x1000 : 0x2000; |
| |
| inline uint32_t capacity() const { return capacity_; } |
| |
| // Clears all entries in the table. |
| inline void Clear(); |
| |
| // Iterates the table and computes the number of occupied entries. |
| uint32_t GetUsedEntriesCount(); |
| |
| // Prints contents of the cache with a comment. |
| void Print(const char* comment); |
| |
| // Returns entry index corresponding to given bitwise representation of |
| // a double value. |
| inline InternalIndex GetEntryFor(uint64_t number_bits) const; |
| static inline InternalIndex GetEntryFor(Isolate* isolate, |
| uint64_t number_bits); |
| |
| // Attempt to find the number in a cache by given bitwise representation. |
| // In case of success, returns the string representation of the number. |
| // Otherwise returns undefined. |
| static inline Handle<Object> Get(Isolate* isolate, InternalIndex entry, |
| uint64_t number_bits); |
| |
| // Puts <number, string> entry to the cache, potentially overwriting |
| // existing entry. The number is given in bitwise representation. |
| static inline void Set(Isolate* isolate, InternalIndex entry, |
| uint64_t number_bits, DirectHandle<String> string); |
| |
| template <class IsolateT> |
| static inline DirectHandle<DoubleStringCache> New(IsolateT* isolate, |
| int capacity); |
| |
| DECL_PRINTER(DoubleStringCache) |
| DECL_VERIFIER(DoubleStringCache) |
| |
| inline int AllocatedSize() const { return SizeFor(this->capacity()); } |
| |
| static inline constexpr int SizeFor(int length) { |
| return OBJECT_POINTER_ALIGN(OffsetOfElementAt(length)); |
| } |
| static inline constexpr int OffsetOfElementAt(int index) { |
| return sizeof(Header) + kUInt32Size + index * sizeof(Entry); |
| } |
| |
| class BodyDescriptor; |
| |
| private: |
| friend class CodeStubAssembler; |
| |
| static inline InternalIndex GetEntryFor(uint64_t number_bits, |
| uint32_t capacity); |
| |
| inline Entry* begin() { return &entries()[0]; } |
| inline const Entry* begin() const { return &entries()[0]; } |
| inline Entry* end() { return &entries()[capacity_]; } |
| inline const Entry* end() const { return &entries()[capacity_]; } |
| |
| uint32_t capacity_; |
| #if TAGGED_SIZE_8_BYTES |
| uint32_t optional_padding_; |
| #endif |
| FLEXIBLE_ARRAY_MEMBER(Entry, entries); |
| } V8_OBJECT_END; |
| |
| static_assert(DoubleStringCache::SizeFor(DoubleStringCache::kMaxCapacity) < |
| kMaxRegularHeapObjectSize); |
| |
| } // namespace v8::internal |
| |
| #include "src/objects/object-macros-undef.h" |
| |
| #endif // V8_OBJECTS_NUMBER_STRING_CACHE_H_ |