11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_INTERPRETER_CONSTANT_ARRAY_BUILDER_H_ 61cb0ef41Sopenharmony_ci#define V8_INTERPRETER_CONSTANT_ARRAY_BUILDER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/ast/ast-value-factory.h" 91cb0ef41Sopenharmony_ci#include "src/common/globals.h" 101cb0ef41Sopenharmony_ci#include "src/handles/handles.h" 111cb0ef41Sopenharmony_ci#include "src/interpreter/bytecodes.h" 121cb0ef41Sopenharmony_ci#include "src/objects/smi.h" 131cb0ef41Sopenharmony_ci#include "src/utils/identity-map.h" 141cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h" 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cinamespace v8 { 171cb0ef41Sopenharmony_cinamespace internal { 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciclass Isolate; 201cb0ef41Sopenharmony_ciclass AstRawString; 211cb0ef41Sopenharmony_ciclass AstValue; 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cinamespace interpreter { 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci// Constant array entries that represent singletons. 261cb0ef41Sopenharmony_ci#define SINGLETON_CONSTANT_ENTRY_TYPES(V) \ 271cb0ef41Sopenharmony_ci V(AsyncIteratorSymbol, async_iterator_symbol) \ 281cb0ef41Sopenharmony_ci V(ClassFieldsSymbol, class_fields_symbol) \ 291cb0ef41Sopenharmony_ci V(EmptyObjectBoilerplateDescription, empty_object_boilerplate_description) \ 301cb0ef41Sopenharmony_ci V(EmptyArrayBoilerplateDescription, empty_array_boilerplate_description) \ 311cb0ef41Sopenharmony_ci V(EmptyFixedArray, empty_fixed_array) \ 321cb0ef41Sopenharmony_ci V(IteratorSymbol, iterator_symbol) \ 331cb0ef41Sopenharmony_ci V(InterpreterTrampolineSymbol, interpreter_trampoline_symbol) \ 341cb0ef41Sopenharmony_ci V(NaN, nan_value) 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci// A helper class for constructing constant arrays for the 371cb0ef41Sopenharmony_ci// interpreter. Each instance of this class is intended to be used to 381cb0ef41Sopenharmony_ci// generate exactly one FixedArray of constants via the ToFixedArray 391cb0ef41Sopenharmony_ci// method. 401cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE ConstantArrayBuilder final { 411cb0ef41Sopenharmony_ci public: 421cb0ef41Sopenharmony_ci // Capacity of the 8-bit operand slice. 431cb0ef41Sopenharmony_ci static const size_t k8BitCapacity = 1u << kBitsPerByte; 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci // Capacity of the 16-bit operand slice. 461cb0ef41Sopenharmony_ci static const size_t k16BitCapacity = (1u << 2 * kBitsPerByte) - k8BitCapacity; 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci // Capacity of the 32-bit operand slice. 491cb0ef41Sopenharmony_ci static const size_t k32BitCapacity = 501cb0ef41Sopenharmony_ci kMaxUInt32 - k16BitCapacity - k8BitCapacity + 1; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci explicit ConstantArrayBuilder(Zone* zone); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci // Generate a fixed array of constant handles based on inserted objects. 551cb0ef41Sopenharmony_ci template <typename IsolateT> 561cb0ef41Sopenharmony_ci EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 571cb0ef41Sopenharmony_ci Handle<FixedArray> ToFixedArray(IsolateT* isolate); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci // Returns the object, as a handle in |isolate|, that is in the constant pool 601cb0ef41Sopenharmony_ci // array at index |index|. Returns null if there is no handle at this index. 611cb0ef41Sopenharmony_ci // Only expected to be used in tests. 621cb0ef41Sopenharmony_ci template <typename IsolateT> 631cb0ef41Sopenharmony_ci EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 641cb0ef41Sopenharmony_ci MaybeHandle<Object> At(size_t index, IsolateT* isolate) const; 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci // Returns the number of elements in the array. 671cb0ef41Sopenharmony_ci size_t size() const; 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci // Insert an object into the constants array if it is not already present. 701cb0ef41Sopenharmony_ci // Returns the array index associated with the object. 711cb0ef41Sopenharmony_ci size_t Insert(Smi smi); 721cb0ef41Sopenharmony_ci size_t Insert(double number); 731cb0ef41Sopenharmony_ci size_t Insert(const AstRawString* raw_string); 741cb0ef41Sopenharmony_ci size_t Insert(AstBigInt bigint); 751cb0ef41Sopenharmony_ci size_t Insert(const Scope* scope); 761cb0ef41Sopenharmony_ci#define INSERT_ENTRY(NAME, ...) size_t Insert##NAME(); 771cb0ef41Sopenharmony_ci SINGLETON_CONSTANT_ENTRY_TYPES(INSERT_ENTRY) 781cb0ef41Sopenharmony_ci#undef INSERT_ENTRY 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci // Inserts an empty entry and returns the array index associated with the 811cb0ef41Sopenharmony_ci // reservation. The entry's handle value can be inserted by calling 821cb0ef41Sopenharmony_ci // SetDeferredAt(). 831cb0ef41Sopenharmony_ci size_t InsertDeferred(); 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci // Inserts |size| consecutive empty entries and returns the array index 861cb0ef41Sopenharmony_ci // associated with the first reservation. Each entry's Smi value can be 871cb0ef41Sopenharmony_ci // inserted by calling SetJumpTableSmi(). 881cb0ef41Sopenharmony_ci size_t InsertJumpTable(size_t size); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci // Sets the deferred value at |index| to |object|. 911cb0ef41Sopenharmony_ci void SetDeferredAt(size_t index, Handle<Object> object); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci // Sets the jump table entry at |index| to |smi|. Note that |index| is the 941cb0ef41Sopenharmony_ci // constant pool index, not the switch case value. 951cb0ef41Sopenharmony_ci void SetJumpTableSmi(size_t index, Smi smi); 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci // Creates a reserved entry in the constant pool and returns 981cb0ef41Sopenharmony_ci // the size of the operand that'll be required to hold the entry 991cb0ef41Sopenharmony_ci // when committed. 1001cb0ef41Sopenharmony_ci OperandSize CreateReservedEntry(); 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci // Commit reserved entry and returns the constant pool index for the 1031cb0ef41Sopenharmony_ci // SMI value. 1041cb0ef41Sopenharmony_ci size_t CommitReservedEntry(OperandSize operand_size, Smi value); 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci // Discards constant pool reservation. 1071cb0ef41Sopenharmony_ci void DiscardReservedEntry(OperandSize operand_size); 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci private: 1101cb0ef41Sopenharmony_ci using index_t = uint32_t; 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci struct ConstantArraySlice; 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci class Entry { 1151cb0ef41Sopenharmony_ci private: 1161cb0ef41Sopenharmony_ci enum class Tag : uint8_t; 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci public: 1191cb0ef41Sopenharmony_ci explicit Entry(Smi smi) : smi_(smi), tag_(Tag::kSmi) {} 1201cb0ef41Sopenharmony_ci explicit Entry(double heap_number) 1211cb0ef41Sopenharmony_ci : heap_number_(heap_number), tag_(Tag::kHeapNumber) {} 1221cb0ef41Sopenharmony_ci explicit Entry(const AstRawString* raw_string) 1231cb0ef41Sopenharmony_ci : raw_string_(raw_string), tag_(Tag::kRawString) {} 1241cb0ef41Sopenharmony_ci explicit Entry(AstBigInt bigint) : bigint_(bigint), tag_(Tag::kBigInt) {} 1251cb0ef41Sopenharmony_ci explicit Entry(const Scope* scope) : scope_(scope), tag_(Tag::kScope) {} 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci#define CONSTRUCT_ENTRY(NAME, LOWER_NAME) \ 1281cb0ef41Sopenharmony_ci static Entry NAME() { return Entry(Tag::k##NAME); } 1291cb0ef41Sopenharmony_ci SINGLETON_CONSTANT_ENTRY_TYPES(CONSTRUCT_ENTRY) 1301cb0ef41Sopenharmony_ci#undef CONSTRUCT_ENTRY 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci static Entry Deferred() { return Entry(Tag::kDeferred); } 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci static Entry UninitializedJumpTableSmi() { 1351cb0ef41Sopenharmony_ci return Entry(Tag::kUninitializedJumpTableSmi); 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci bool IsDeferred() const { return tag_ == Tag::kDeferred; } 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci bool IsJumpTableEntry() const { 1411cb0ef41Sopenharmony_ci return tag_ == Tag::kUninitializedJumpTableSmi || 1421cb0ef41Sopenharmony_ci tag_ == Tag::kJumpTableSmi; 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci void SetDeferred(Handle<Object> handle) { 1461cb0ef41Sopenharmony_ci DCHECK_EQ(tag_, Tag::kDeferred); 1471cb0ef41Sopenharmony_ci tag_ = Tag::kHandle; 1481cb0ef41Sopenharmony_ci handle_ = handle; 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci void SetJumpTableSmi(Smi smi) { 1521cb0ef41Sopenharmony_ci DCHECK_EQ(tag_, Tag::kUninitializedJumpTableSmi); 1531cb0ef41Sopenharmony_ci tag_ = Tag::kJumpTableSmi; 1541cb0ef41Sopenharmony_ci smi_ = smi; 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci template <typename IsolateT> 1581cb0ef41Sopenharmony_ci Handle<Object> ToHandle(IsolateT* isolate) const; 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci private: 1611cb0ef41Sopenharmony_ci explicit Entry(Tag tag) : tag_(tag) {} 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci union { 1641cb0ef41Sopenharmony_ci Handle<Object> handle_; 1651cb0ef41Sopenharmony_ci Smi smi_; 1661cb0ef41Sopenharmony_ci double heap_number_; 1671cb0ef41Sopenharmony_ci const AstRawString* raw_string_; 1681cb0ef41Sopenharmony_ci AstBigInt bigint_; 1691cb0ef41Sopenharmony_ci const Scope* scope_; 1701cb0ef41Sopenharmony_ci }; 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci enum class Tag : uint8_t { 1731cb0ef41Sopenharmony_ci kDeferred, 1741cb0ef41Sopenharmony_ci kHandle, 1751cb0ef41Sopenharmony_ci kSmi, 1761cb0ef41Sopenharmony_ci kRawString, 1771cb0ef41Sopenharmony_ci kHeapNumber, 1781cb0ef41Sopenharmony_ci kBigInt, 1791cb0ef41Sopenharmony_ci kScope, 1801cb0ef41Sopenharmony_ci kUninitializedJumpTableSmi, 1811cb0ef41Sopenharmony_ci kJumpTableSmi, 1821cb0ef41Sopenharmony_ci#define ENTRY_TAG(NAME, ...) k##NAME, 1831cb0ef41Sopenharmony_ci SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_TAG) 1841cb0ef41Sopenharmony_ci#undef ENTRY_TAG 1851cb0ef41Sopenharmony_ci } tag_; 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci#if DEBUG 1881cb0ef41Sopenharmony_ci // Required by CheckAllElementsAreUnique(). 1891cb0ef41Sopenharmony_ci friend struct ConstantArraySlice; 1901cb0ef41Sopenharmony_ci#endif 1911cb0ef41Sopenharmony_ci }; 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci index_t AllocateIndex(Entry constant_entry); 1941cb0ef41Sopenharmony_ci index_t AllocateIndexArray(Entry constant_entry, size_t size); 1951cb0ef41Sopenharmony_ci index_t AllocateReservedEntry(Smi value); 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci struct ConstantArraySlice final : public ZoneObject { 1981cb0ef41Sopenharmony_ci ConstantArraySlice(Zone* zone, size_t start_index, size_t capacity, 1991cb0ef41Sopenharmony_ci OperandSize operand_size); 2001cb0ef41Sopenharmony_ci ConstantArraySlice(const ConstantArraySlice&) = delete; 2011cb0ef41Sopenharmony_ci ConstantArraySlice& operator=(const ConstantArraySlice&) = delete; 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci void Reserve(); 2041cb0ef41Sopenharmony_ci void Unreserve(); 2051cb0ef41Sopenharmony_ci size_t Allocate(Entry entry, size_t count = 1); 2061cb0ef41Sopenharmony_ci Entry& At(size_t index); 2071cb0ef41Sopenharmony_ci const Entry& At(size_t index) const; 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci#if DEBUG 2101cb0ef41Sopenharmony_ci template <typename IsolateT> 2111cb0ef41Sopenharmony_ci void CheckAllElementsAreUnique(IsolateT* isolate) const; 2121cb0ef41Sopenharmony_ci#endif 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci inline size_t available() const { return capacity() - reserved() - size(); } 2151cb0ef41Sopenharmony_ci inline size_t reserved() const { return reserved_; } 2161cb0ef41Sopenharmony_ci inline size_t capacity() const { return capacity_; } 2171cb0ef41Sopenharmony_ci inline size_t size() const { return constants_.size(); } 2181cb0ef41Sopenharmony_ci inline size_t start_index() const { return start_index_; } 2191cb0ef41Sopenharmony_ci inline size_t max_index() const { return start_index_ + capacity() - 1; } 2201cb0ef41Sopenharmony_ci inline OperandSize operand_size() const { return operand_size_; } 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci private: 2231cb0ef41Sopenharmony_ci const size_t start_index_; 2241cb0ef41Sopenharmony_ci const size_t capacity_; 2251cb0ef41Sopenharmony_ci size_t reserved_; 2261cb0ef41Sopenharmony_ci OperandSize operand_size_; 2271cb0ef41Sopenharmony_ci ZoneVector<Entry> constants_; 2281cb0ef41Sopenharmony_ci }; 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_ci ConstantArraySlice* IndexToSlice(size_t index) const; 2311cb0ef41Sopenharmony_ci ConstantArraySlice* OperandSizeToSlice(OperandSize operand_size) const; 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci ConstantArraySlice* idx_slice_[3]; 2341cb0ef41Sopenharmony_ci base::TemplateHashMapImpl<intptr_t, index_t, 2351cb0ef41Sopenharmony_ci base::KeyEqualityMatcher<intptr_t>, 2361cb0ef41Sopenharmony_ci ZoneAllocationPolicy> 2371cb0ef41Sopenharmony_ci constants_map_; 2381cb0ef41Sopenharmony_ci ZoneMap<Smi, index_t> smi_map_; 2391cb0ef41Sopenharmony_ci ZoneVector<std::pair<Smi, index_t>> smi_pairs_; 2401cb0ef41Sopenharmony_ci ZoneMap<double, index_t> heap_number_map_; 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci#define SINGLETON_ENTRY_FIELD(NAME, LOWER_NAME) int LOWER_NAME##_ = -1; 2431cb0ef41Sopenharmony_ci SINGLETON_CONSTANT_ENTRY_TYPES(SINGLETON_ENTRY_FIELD) 2441cb0ef41Sopenharmony_ci#undef SINGLETON_ENTRY_FIELD 2451cb0ef41Sopenharmony_ci}; 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci} // namespace interpreter 2481cb0ef41Sopenharmony_ci} // namespace internal 2491cb0ef41Sopenharmony_ci} // namespace v8 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci#endif // V8_INTERPRETER_CONSTANT_ARRAY_BUILDER_H_ 252