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