V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
accessor-assembler.h
1 // Copyright 2016 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_IC_ACCESSOR_ASSEMBLER_H_
6 #define V8_IC_ACCESSOR_ASSEMBLER_H_
7 
8 #include "src/code-stub-assembler.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 namespace compiler {
14 class CodeAssemblerState;
15 }
16 
17 class ExitPoint;
18 
20  public:
21  using Node = compiler::Node;
22  template <class T>
23  using TNode = compiler::TNode<T>;
24  template <class T>
26 
28  : CodeStubAssembler(state) {}
29 
30  void GenerateLoadIC();
31  void GenerateLoadIC_Megamorphic();
32  void GenerateLoadIC_Noninlined();
33  void GenerateLoadIC_Uninitialized();
34  void GenerateLoadICTrampoline();
35  void GenerateLoadICTrampoline_Megamorphic();
36  void GenerateKeyedLoadIC();
37  void GenerateKeyedLoadIC_Megamorphic();
38  void GenerateKeyedLoadIC_PolymorphicName();
39  void GenerateKeyedLoadICTrampoline();
40  void GenerateKeyedLoadICTrampoline_Megamorphic();
41  void GenerateStoreIC();
42  void GenerateStoreICTrampoline();
43  void GenerateStoreGlobalIC();
44  void GenerateStoreGlobalICTrampoline();
45  void GenerateCloneObjectIC();
46  void GenerateCloneObjectIC_Slow();
47 
48  void GenerateLoadGlobalIC(TypeofMode typeof_mode);
49  void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
50 
51  void GenerateKeyedStoreIC();
52  void GenerateKeyedStoreICTrampoline();
53 
54  void GenerateStoreInArrayLiteralIC();
55 
56  void TryProbeStubCache(StubCache* stub_cache, Node* receiver, Node* name,
57  Label* if_handler, TVariable<MaybeObject>* var_handler,
58  Label* if_miss);
59 
60  Node* StubCachePrimaryOffsetForTesting(Node* name, Node* map) {
61  return StubCachePrimaryOffset(name, map);
62  }
63  Node* StubCacheSecondaryOffsetForTesting(Node* name, Node* map) {
64  return StubCacheSecondaryOffset(name, map);
65  }
66 
68  LoadICParameters(Node* context, Node* receiver, Node* name, Node* slot,
69  Node* vector, Node* holder = nullptr)
70  : context(context),
71  receiver(receiver),
72  name(name),
73  slot(slot),
74  vector(vector),
75  holder(holder ? holder : receiver) {}
76 
77  Node* context;
78  Node* receiver;
79  Node* name;
80  Node* slot;
81  Node* vector;
82  Node* holder;
83  };
84 
85  void LoadGlobalIC(TNode<FeedbackVector> vector, Node* slot,
86  const LazyNode<Context>& lazy_context,
87  const LazyNode<Name>& lazy_name, TypeofMode typeof_mode,
88  ExitPoint* exit_point,
89  ParameterMode slot_mode = SMI_PARAMETERS);
90 
91  // Specialized LoadIC for inlined bytecode handler, hand-tuned to omit frame
92  // construction on common paths.
93  void LoadIC_BytecodeHandler(const LoadICParameters* p, ExitPoint* exit_point);
94 
95  // Loads dataX field from the DataHandler object.
96  TNode<MaybeObject> LoadHandlerDataField(SloppyTNode<DataHandler> handler,
97  int data_index);
98 
99  protected:
101  StoreICParameters(Node* context, Node* receiver, Node* name,
102  SloppyTNode<Object> value, Node* slot, Node* vector)
103  : LoadICParameters(context, receiver, name, slot, vector),
104  value(value) {}
105  SloppyTNode<Object> value;
106  };
107 
108  enum class ICMode { kNonGlobalIC, kGlobalIC };
109  enum ElementSupport { kOnlyProperties, kSupportElements };
110  void HandleStoreICHandlerCase(
111  const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss,
112  ICMode ic_mode, ElementSupport support_elements = kOnlyProperties);
113  enum StoreTransitionMapFlags {
114  kCheckPrototypeValidity = 1 << 0,
115  kValidateTransitionHandler = 1 << 1,
116  kStoreTransitionMapFlagsMask =
117  kCheckPrototypeValidity | kValidateTransitionHandler,
118  };
119  void HandleStoreICTransitionMapHandlerCase(const StoreICParameters* p,
120  TNode<Map> transition_map,
121  Label* miss,
122  StoreTransitionMapFlags flags);
123 
124  void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
125 
126  void BranchIfStrictMode(Node* vector, Node* slot, Label* if_strict);
127 
128  void InvalidateValidityCellIfPrototype(Node* map, Node* bitfield2 = nullptr);
129 
130  void OverwriteExistingFastDataProperty(Node* object, Node* object_map,
131  Node* descriptors,
132  Node* descriptor_name_index,
133  Node* details, Node* value,
134  Label* slow,
135  bool do_transitioning_store);
136 
137  void CheckFieldType(TNode<DescriptorArray> descriptors, Node* name_index,
138  Node* representation, Node* value, Label* bailout);
139 
140  private:
141  // Stub generation entry points.
142 
143  // LoadIC contains the full LoadIC logic, while LoadIC_Noninlined contains
144  // logic not inlined into Ignition bytecode handlers.
145  void LoadIC(const LoadICParameters* p);
146  void LoadIC_Noninlined(const LoadICParameters* p, Node* receiver_map,
147  TNode<HeapObject> feedback,
148  TVariable<MaybeObject>* var_handler, Label* if_handler,
149  Label* miss, ExitPoint* exit_point);
150 
151  TNode<Object> LoadDescriptorValue(TNode<Map> map,
152  TNode<IntPtrT> descriptor_entry);
153  TNode<MaybeObject> LoadDescriptorValueOrFieldType(
154  TNode<Map> map, TNode<IntPtrT> descriptor_entry);
155 
156  void LoadIC_Uninitialized(const LoadICParameters* p);
157 
158  void KeyedLoadIC(const LoadICParameters* p);
159  void KeyedLoadICGeneric(const LoadICParameters* p);
160  void KeyedLoadICPolymorphicName(const LoadICParameters* p);
161  void StoreIC(const StoreICParameters* p);
162  void StoreGlobalIC(const StoreICParameters* p);
163  void StoreGlobalIC_PropertyCellCase(Node* property_cell, Node* value,
164  ExitPoint* exit_point, Label* miss);
165  void KeyedStoreIC(const StoreICParameters* p);
166  void StoreInArrayLiteralIC(const StoreICParameters* p);
167 
168  // IC dispatcher behavior.
169 
170  // Checks monomorphic case. Returns {feedback} entry of the vector.
171  TNode<MaybeObject> TryMonomorphicCase(Node* slot, Node* vector,
172  Node* receiver_map, Label* if_handler,
173  TVariable<MaybeObject>* var_handler,
174  Label* if_miss);
175  void HandlePolymorphicCase(Node* receiver_map, TNode<WeakFixedArray> feedback,
176  Label* if_handler,
177  TVariable<MaybeObject>* var_handler,
178  Label* if_miss, int min_feedback_capacity);
179 
180  // LoadIC implementation.
181  void HandleLoadICHandlerCase(
182  const LoadICParameters* p, TNode<Object> handler, Label* miss,
183  ExitPoint* exit_point, ICMode ic_mode = ICMode::kNonGlobalIC,
184  OnNonExistent on_nonexistent = OnNonExistent::kReturnUndefined,
185  ElementSupport support_elements = kOnlyProperties);
186 
187  void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder,
188  SloppyTNode<Smi> smi_handler,
189  SloppyTNode<Object> handler, Label* miss,
190  ExitPoint* exit_point,
191  OnNonExistent on_nonexistent,
192  ElementSupport support_elements);
193 
194  void HandleLoadICProtoHandler(const LoadICParameters* p, Node* handler,
195  Variable* var_holder, Variable* var_smi_handler,
196  Label* if_smi_handler, Label* miss,
197  ExitPoint* exit_point, ICMode ic_mode);
198 
199  void HandleLoadCallbackProperty(const LoadICParameters* p,
200  TNode<JSObject> holder,
201  TNode<WordT> handler_word,
202  ExitPoint* exit_point);
203 
204  void HandleLoadAccessor(const LoadICParameters* p,
205  TNode<CallHandlerInfo> call_handler_info,
206  TNode<WordT> handler_word, TNode<DataHandler> handler,
207  TNode<IntPtrT> handler_kind, ExitPoint* exit_point);
208 
209  void HandleLoadField(Node* holder, Node* handler_word,
210  Variable* var_double_value, Label* rebox_double,
211  ExitPoint* exit_point);
212 
213  void EmitAccessCheck(Node* expected_native_context, Node* context,
214  Node* receiver, Label* can_access, Label* miss);
215 
216  // LoadGlobalIC implementation.
217 
218  void LoadGlobalIC_TryPropertyCellCase(
219  TNode<FeedbackVector> vector, Node* slot,
220  const LazyNode<Context>& lazy_context, ExitPoint* exit_point,
221  Label* try_handler, Label* miss,
222  ParameterMode slot_mode = SMI_PARAMETERS);
223 
224  void LoadGlobalIC_TryHandlerCase(TNode<FeedbackVector> vector, Node* slot,
225  const LazyNode<Context>& lazy_context,
226  const LazyNode<Name>& lazy_name,
227  TypeofMode typeof_mode,
228  ExitPoint* exit_point, Label* miss,
229  ParameterMode slot_mode);
230 
231  // StoreIC implementation.
232 
233  void HandleStoreICProtoHandler(const StoreICParameters* p,
234  TNode<StoreHandler> handler, Label* miss,
235  ICMode ic_mode,
236  ElementSupport support_elements);
237  void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder,
238  Node* value, Label* miss);
239  void HandleStoreFieldAndReturn(Node* handler_word, Node* holder,
240  Representation representation, Node* value,
241  Label* miss);
242 
243  void CheckPrototypeValidityCell(Node* maybe_validity_cell, Label* miss);
244  void HandleStoreICNativeDataProperty(const StoreICParameters* p, Node* holder,
245  Node* handler_word);
246 
247  void HandleStoreToProxy(const StoreICParameters* p, Node* proxy, Label* miss,
248  ElementSupport support_elements);
249 
250  void HandleStoreAccessor(const StoreICParameters* p, Node* holder,
251  Node* handler_word);
252 
253  // KeyedLoadIC_Generic implementation.
254 
255  void GenericElementLoad(Node* receiver, Node* receiver_map,
256  SloppyTNode<Int32T> instance_type, Node* index,
257  Label* slow);
258 
259  enum UseStubCache { kUseStubCache, kDontUseStubCache };
260  void GenericPropertyLoad(Node* receiver, Node* receiver_map,
261  SloppyTNode<Int32T> instance_type,
262  const LoadICParameters* p, Label* slow,
263  UseStubCache use_stub_cache = kUseStubCache);
264 
265  // Low-level helpers.
266 
267  typedef std::function<void(Node* code_handler)> OnCodeHandler;
268  typedef std::function<void(Node* properties, Node* name_index)>
269  OnFoundOnReceiver;
270 
271  template <typename ICHandler, typename ICParameters>
272  Node* HandleProtoHandler(const ICParameters* p, Node* handler,
273  const OnCodeHandler& on_code_handler,
274  const OnFoundOnReceiver& on_found_on_receiver,
275  Label* miss, ICMode ic_mode);
276 
277  Node* GetLanguageMode(Node* vector, Node* slot);
278 
279  Node* PrepareValueForStore(Node* handler_word, Node* holder,
280  Representation representation, Node* value,
281  Label* bailout);
282 
283  // Extends properties backing store by JSObject::kFieldsAdded elements,
284  // returns updated properties backing store.
285  Node* ExtendPropertiesBackingStore(Node* object, Node* index);
286 
287  void StoreNamedField(Node* handler_word, Node* object, bool is_inobject,
288  Representation representation, Node* value,
289  Label* bailout);
290 
291  void EmitFastElementsBoundsCheck(Node* object, Node* elements,
292  Node* intptr_index,
293  Node* is_jsarray_condition, Label* miss);
294  void EmitElementLoad(Node* object, Node* elements, Node* elements_kind,
295  SloppyTNode<IntPtrT> key, Node* is_jsarray_condition,
296  Label* if_hole, Label* rebox_double,
297  Variable* var_double_value,
298  Label* unimplemented_elements_kind, Label* out_of_bounds,
299  Label* miss, ExitPoint* exit_point);
300  void NameDictionaryNegativeLookup(Node* object, SloppyTNode<Name> name,
301  Label* miss);
302 
303  // Stub cache access helpers.
304 
305  // This enum is used here as a replacement for StubCache::Table to avoid
306  // including stub cache header.
307  enum StubCacheTable : int;
308 
309  Node* StubCachePrimaryOffset(Node* name, Node* map);
310  Node* StubCacheSecondaryOffset(Node* name, Node* seed);
311 
312  void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
313  Node* entry_offset, Node* name, Node* map,
314  Label* if_handler,
315  TVariable<MaybeObject>* var_handler,
316  Label* if_miss);
317 };
318 
319 // Abstraction over direct and indirect exit points. Direct exits correspond to
320 // tailcalls and Return, while indirect exits store the result in a variable
321 // and then jump to an exit label.
322 class ExitPoint {
323  private:
324  typedef compiler::Node Node;
327 
328  public:
329  typedef std::function<void(Node* result)> IndirectReturnHandler;
330 
331  explicit ExitPoint(CodeStubAssembler* assembler)
332  : ExitPoint(assembler, nullptr) {}
333 
334  ExitPoint(CodeStubAssembler* assembler,
335  const IndirectReturnHandler& indirect_return_handler)
336  : asm_(assembler), indirect_return_handler_(indirect_return_handler) {}
337 
339  CodeAssemblerVariable* var_result)
340  : ExitPoint(assembler, [=](Node* result) {
341  var_result->Bind(result);
342  assembler->Goto(out);
343  }) {
344  DCHECK_EQ(out != nullptr, var_result != nullptr);
345  }
346 
347  template <class... TArgs>
348  void ReturnCallRuntime(Runtime::FunctionId function, Node* context,
349  TArgs... args) {
350  if (IsDirect()) {
351  asm_->TailCallRuntime(function, context, args...);
352  } else {
353  indirect_return_handler_(asm_->CallRuntime(function, context, args...));
354  }
355  }
356 
357  template <class... TArgs>
358  void ReturnCallStub(Callable const& callable, Node* context, TArgs... args) {
359  if (IsDirect()) {
360  asm_->TailCallStub(callable, context, args...);
361  } else {
362  indirect_return_handler_(asm_->CallStub(callable, context, args...));
363  }
364  }
365 
366  template <class... TArgs>
367  void ReturnCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
368  Node* context, TArgs... args) {
369  if (IsDirect()) {
370  asm_->TailCallStub(descriptor, target, context, args...);
371  } else {
372  indirect_return_handler_(
373  asm_->CallStub(descriptor, target, context, args...));
374  }
375  }
376 
377  void Return(Node* const result) {
378  if (IsDirect()) {
379  asm_->Return(result);
380  } else {
381  indirect_return_handler_(result);
382  }
383  }
384 
385  bool IsDirect() const { return !indirect_return_handler_; }
386 
387  private:
388  CodeStubAssembler* const asm_;
389  IndirectReturnHandler indirect_return_handler_;
390 };
391 
392 } // namespace internal
393 } // namespace v8
394 
395 #endif // V8_IC_ACCESSOR_ASSEMBLER_H_
Definition: libplatform.h:13