blob: 2d1d446f8fc8ba36c5e5e97807b5a7c964dd2539 [file] [edit]
// 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_