• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_INTERPRETER_CONSTANT_ARRAY_BUILDER_H_
6 #define V8_INTERPRETER_CONSTANT_ARRAY_BUILDER_H_
7 
8 #include "src/ast/ast-value-factory.h"
9 #include "src/globals.h"
10 #include "src/identity-map.h"
11 #include "src/interpreter/bytecodes.h"
12 #include "src/zone/zone-containers.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 class Isolate;
18 class AstRawString;
19 class AstValue;
20 
21 namespace interpreter {
22 
23 // Constant array entries that represent singletons.
24 #define SINGLETON_CONSTANT_ENTRY_TYPES(V)                                    \
25   V(AsyncIteratorSymbol, async_iterator_symbol)                              \
26   V(ClassFieldsSymbol, class_fields_symbol)                                  \
27   V(EmptyObjectBoilerplateDescription, empty_object_boilerplate_description) \
28   V(EmptyArrayBoilerplateDescription, empty_array_boilerplate_description)   \
29   V(EmptyFixedArray, empty_fixed_array)                                      \
30   V(HomeObjectSymbol, home_object_symbol)                                    \
31   V(IteratorSymbol, iterator_symbol)                                         \
32   V(InterpreterTrampolineSymbol, interpreter_trampoline_symbol)              \
33   V(NaN, nan_value)
34 
35 // A helper class for constructing constant arrays for the
36 // interpreter. Each instance of this class is intended to be used to
37 // generate exactly one FixedArray of constants via the ToFixedArray
38 // method.
39 class V8_EXPORT_PRIVATE ConstantArrayBuilder final BASE_EMBEDDED {
40  public:
41   // Capacity of the 8-bit operand slice.
42   static const size_t k8BitCapacity = 1u << kBitsPerByte;
43 
44   // Capacity of the 16-bit operand slice.
45   static const size_t k16BitCapacity = (1u << 2 * kBitsPerByte) - k8BitCapacity;
46 
47   // Capacity of the 32-bit operand slice.
48   static const size_t k32BitCapacity =
49       kMaxUInt32 - k16BitCapacity - k8BitCapacity + 1;
50 
51   ConstantArrayBuilder(Zone* zone);
52 
53   // Generate a fixed array of constant handles based on inserted objects.
54   Handle<FixedArray> ToFixedArray(Isolate* isolate);
55 
56   // Returns the object, as a handle in |isolate|, that is in the constant pool
57   // array at index |index|. Returns null if there is no handle at this index.
58   // Only expected to be used in tests.
59   MaybeHandle<Object> At(size_t index, Isolate* isolate) const;
60 
61   // Returns the number of elements in the array.
62   size_t size() const;
63 
64   // Insert an object into the constants array if it is not already present.
65   // Returns the array index associated with the object.
66   size_t Insert(Smi* smi);
67   size_t Insert(double number);
68   size_t Insert(const AstRawString* raw_string);
69   size_t Insert(AstBigInt bigint);
70   size_t Insert(const Scope* scope);
71 #define INSERT_ENTRY(NAME, ...) size_t Insert##NAME();
72   SINGLETON_CONSTANT_ENTRY_TYPES(INSERT_ENTRY)
73 #undef INSERT_ENTRY
74 
75   // Inserts an empty entry and returns the array index associated with the
76   // reservation. The entry's handle value can be inserted by calling
77   // SetDeferredAt().
78   size_t InsertDeferred();
79 
80   // Inserts |size| consecutive empty entries and returns the array index
81   // associated with the first reservation. Each entry's Smi value can be
82   // inserted by calling SetJumpTableSmi().
83   size_t InsertJumpTable(size_t size);
84 
85   // Sets the deferred value at |index| to |object|.
86   void SetDeferredAt(size_t index, Handle<Object> object);
87 
88   // Sets the jump table entry at |index| to |smi|. Note that |index| is the
89   // constant pool index, not the switch case value.
90   void SetJumpTableSmi(size_t index, Smi* smi);
91 
92   // Creates a reserved entry in the constant pool and returns
93   // the size of the operand that'll be required to hold the entry
94   // when committed.
95   OperandSize CreateReservedEntry();
96 
97   // Commit reserved entry and returns the constant pool index for the
98   // SMI value.
99   size_t CommitReservedEntry(OperandSize operand_size, Smi* value);
100 
101   // Discards constant pool reservation.
102   void DiscardReservedEntry(OperandSize operand_size);
103 
104  private:
105   typedef uint32_t index_t;
106 
107   struct ConstantArraySlice;
108 
109   class Entry {
110    private:
111     enum class Tag : uint8_t;
112 
113    public:
Entry(Smi * smi)114     explicit Entry(Smi* smi) : smi_(smi), tag_(Tag::kSmi) {}
Entry(double heap_number)115     explicit Entry(double heap_number)
116         : heap_number_(heap_number), tag_(Tag::kHeapNumber) {}
Entry(const AstRawString * raw_string)117     explicit Entry(const AstRawString* raw_string)
118         : raw_string_(raw_string), tag_(Tag::kRawString) {}
Entry(AstBigInt bigint)119     explicit Entry(AstBigInt bigint) : bigint_(bigint), tag_(Tag::kBigInt) {}
Entry(const Scope * scope)120     explicit Entry(const Scope* scope) : scope_(scope), tag_(Tag::kScope) {}
121 
122 #define CONSTRUCT_ENTRY(NAME, LOWER_NAME) \
123   static Entry NAME() { return Entry(Tag::k##NAME); }
SINGLETON_CONSTANT_ENTRY_TYPES(CONSTRUCT_ENTRY)124     SINGLETON_CONSTANT_ENTRY_TYPES(CONSTRUCT_ENTRY)
125 #undef CONSTRUCT_ENTRY
126 
127     static Entry Deferred() { return Entry(Tag::kDeferred); }
128 
UninitializedJumpTableSmi()129     static Entry UninitializedJumpTableSmi() {
130       return Entry(Tag::kUninitializedJumpTableSmi);
131     }
132 
IsDeferred()133     bool IsDeferred() const { return tag_ == Tag::kDeferred; }
134 
IsJumpTableEntry()135     bool IsJumpTableEntry() const {
136       return tag_ == Tag::kUninitializedJumpTableSmi ||
137              tag_ == Tag::kJumpTableSmi;
138     }
139 
SetDeferred(Handle<Object> handle)140     void SetDeferred(Handle<Object> handle) {
141       DCHECK_EQ(tag_, Tag::kDeferred);
142       tag_ = Tag::kHandle;
143       handle_ = handle;
144     }
145 
SetJumpTableSmi(Smi * smi)146     void SetJumpTableSmi(Smi* smi) {
147       DCHECK_EQ(tag_, Tag::kUninitializedJumpTableSmi);
148       tag_ = Tag::kJumpTableSmi;
149       smi_ = smi;
150     }
151 
152     Handle<Object> ToHandle(Isolate* isolate) const;
153 
154    private:
Entry(Tag tag)155     explicit Entry(Tag tag) : tag_(tag) {}
156 
157     union {
158       Handle<Object> handle_;
159       Smi* smi_;
160       double heap_number_;
161       const AstRawString* raw_string_;
162       AstBigInt bigint_;
163       const Scope* scope_;
164     };
165 
166     enum class Tag : uint8_t {
167       kDeferred,
168       kHandle,
169       kSmi,
170       kRawString,
171       kHeapNumber,
172       kBigInt,
173       kScope,
174       kUninitializedJumpTableSmi,
175       kJumpTableSmi,
176 #define ENTRY_TAG(NAME, ...) k##NAME,
177       SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_TAG)
178 #undef ENTRY_TAG
179     } tag_;
180 
181 #if DEBUG
182     // Required by CheckAllElementsAreUnique().
183     friend struct ConstantArraySlice;
184 #endif
185   };
186 
187   index_t AllocateIndex(Entry constant_entry);
188   index_t AllocateIndexArray(Entry constant_entry, size_t size);
189   index_t AllocateReservedEntry(Smi* value);
190 
191   struct ConstantArraySlice final : public ZoneObject {
192     ConstantArraySlice(Zone* zone, size_t start_index, size_t capacity,
193                        OperandSize operand_size);
194     void Reserve();
195     void Unreserve();
196     size_t Allocate(Entry entry, size_t count = 1);
197     Entry& At(size_t index);
198     const Entry& At(size_t index) const;
199 
200 #if DEBUG
201     void CheckAllElementsAreUnique(Isolate* isolate) const;
202 #endif
203 
availablefinal204     inline size_t available() const { return capacity() - reserved() - size(); }
reservedfinal205     inline size_t reserved() const { return reserved_; }
capacityfinal206     inline size_t capacity() const { return capacity_; }
sizefinal207     inline size_t size() const { return constants_.size(); }
start_indexfinal208     inline size_t start_index() const { return start_index_; }
max_indexfinal209     inline size_t max_index() const { return start_index_ + capacity() - 1; }
operand_sizefinal210     inline OperandSize operand_size() const { return operand_size_; }
211 
212    private:
213     const size_t start_index_;
214     const size_t capacity_;
215     size_t reserved_;
216     OperandSize operand_size_;
217     ZoneVector<Entry> constants_;
218 
219     DISALLOW_COPY_AND_ASSIGN(ConstantArraySlice);
220   };
221 
222   ConstantArraySlice* IndexToSlice(size_t index) const;
223   ConstantArraySlice* OperandSizeToSlice(OperandSize operand_size) const;
224 
225   ConstantArraySlice* idx_slice_[3];
226   base::TemplateHashMapImpl<intptr_t, index_t,
227                             base::KeyEqualityMatcher<intptr_t>,
228                             ZoneAllocationPolicy>
229       constants_map_;
230   ZoneMap<Smi*, index_t> smi_map_;
231   ZoneVector<std::pair<Smi*, index_t>> smi_pairs_;
232   ZoneMap<double, index_t> heap_number_map_;
233 
234 #define SINGLETON_ENTRY_FIELD(NAME, LOWER_NAME) int LOWER_NAME##_;
235   SINGLETON_CONSTANT_ENTRY_TYPES(SINGLETON_ENTRY_FIELD)
236 #undef SINGLETON_ENTRY_FIELD
237 
238   Zone* zone_;
239 };
240 
241 }  // namespace interpreter
242 }  // namespace internal
243 }  // namespace v8
244 
245 #endif  // V8_INTERPRETER_CONSTANT_ARRAY_BUILDER_H_
246