• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/optional.h"
9 #include "src/codegen/code-stub-assembler.h"
10 #include "src/compiler/code-assembler.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 namespace compiler {
16 class CodeAssemblerState;
17 }  // namespace compiler
18 
19 class ExitPoint;
20 
21 class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
22  public:
AccessorAssembler(compiler::CodeAssemblerState * state)23   explicit AccessorAssembler(compiler::CodeAssemblerState* state)
24       : CodeStubAssembler(state) {}
25 
26   void GenerateLoadIC();
27   void GenerateLoadIC_Megamorphic();
28   void GenerateLoadIC_Noninlined();
29   void GenerateLoadIC_NoFeedback();
30   void GenerateLoadGlobalIC_NoFeedback();
31   void GenerateLoadICTrampoline();
32   void GenerateLoadICBaseline();
33   void GenerateLoadICTrampoline_Megamorphic();
34   void GenerateLoadSuperIC();
35   void GenerateLoadSuperICBaseline();
36   void GenerateKeyedLoadIC();
37   void GenerateKeyedLoadIC_Megamorphic();
38   void GenerateKeyedLoadIC_PolymorphicName();
39   void GenerateKeyedLoadICTrampoline();
40   void GenerateKeyedLoadICBaseline();
41   void GenerateKeyedLoadICTrampoline_Megamorphic();
42   void GenerateStoreIC();
43   void GenerateStoreICTrampoline();
44   void GenerateStoreICBaseline();
45   void GenerateDefineNamedOwnIC();
46   void GenerateDefineNamedOwnICTrampoline();
47   void GenerateDefineNamedOwnICBaseline();
48   void GenerateStoreGlobalIC();
49   void GenerateStoreGlobalICTrampoline();
50   void GenerateStoreGlobalICBaseline();
51   void GenerateCloneObjectIC();
52   void GenerateCloneObjectICBaseline();
53   void GenerateCloneObjectIC_Slow();
54   void GenerateKeyedHasIC();
55   void GenerateKeyedHasICBaseline();
56   void GenerateKeyedHasIC_Megamorphic();
57   void GenerateKeyedHasIC_PolymorphicName();
58 
59   void GenerateLoadGlobalIC(TypeofMode typeof_mode);
60   void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
61   void GenerateLoadGlobalICBaseline(TypeofMode typeof_mode);
62   void GenerateLookupGlobalICBaseline(TypeofMode typeof_mode);
63   void GenerateLookupContextBaseline(TypeofMode typeof_mode);
64 
65   void GenerateKeyedStoreIC();
66   void GenerateKeyedStoreICTrampoline();
67   void GenerateKeyedStoreICBaseline();
68 
69   void GenerateDefineKeyedOwnIC();
70   void GenerateDefineKeyedOwnICTrampoline();
71   void GenerateDefineKeyedOwnICBaseline();
72 
73   void GenerateStoreInArrayLiteralIC();
74   void GenerateStoreInArrayLiteralICBaseline();
75 
76   void TryProbeStubCache(StubCache* stub_cache,
77                          TNode<Object> lookup_start_object, TNode<Name> name,
78                          Label* if_handler, TVariable<MaybeObject>* var_handler,
79                          Label* if_miss);
80 
StubCachePrimaryOffsetForTesting(TNode<Name> name,TNode<Map> map)81   TNode<IntPtrT> StubCachePrimaryOffsetForTesting(TNode<Name> name,
82                                                   TNode<Map> map) {
83     return StubCachePrimaryOffset(name, map);
84   }
StubCacheSecondaryOffsetForTesting(TNode<Name> name,TNode<Map> map)85   TNode<IntPtrT> StubCacheSecondaryOffsetForTesting(TNode<Name> name,
86                                                     TNode<Map> map) {
87     return StubCacheSecondaryOffset(name, map);
88   }
89 
90   struct LoadICParameters {
91     LoadICParameters(
92         TNode<Context> context, TNode<Object> receiver, TNode<Object> name,
93         TNode<TaggedIndex> slot, TNode<HeapObject> vector,
94         base::Optional<TNode<Object>> lookup_start_object = base::nullopt)
context_LoadICParameters95         : context_(context),
96           receiver_(receiver),
97           name_(name),
98           slot_(slot),
99           vector_(vector),
100           lookup_start_object_(lookup_start_object ? lookup_start_object.value()
101                                                    : receiver) {}
102 
LoadICParametersLoadICParameters103     LoadICParameters(const LoadICParameters* p, TNode<Object> unique_name)
104         : context_(p->context_),
105           receiver_(p->receiver_),
106           name_(unique_name),
107           slot_(p->slot_),
108           vector_(p->vector_),
109           lookup_start_object_(p->lookup_start_object_) {}
110 
contextLoadICParameters111     TNode<Context> context() const { return context_; }
receiverLoadICParameters112     TNode<Object> receiver() const { return receiver_; }
nameLoadICParameters113     TNode<Object> name() const { return name_; }
slotLoadICParameters114     TNode<TaggedIndex> slot() const { return slot_; }
vectorLoadICParameters115     TNode<HeapObject> vector() const { return vector_; }
lookup_start_objectLoadICParameters116     TNode<Object> lookup_start_object() const {
117       return lookup_start_object_.value();
118     }
119 
120     // Usable in cases where the receiver and the lookup start object are
121     // expected to be the same, i.e., when "receiver != lookup_start_object"
122     // case is not supported or not expected by the surrounding code.
receiver_and_lookup_start_objectLoadICParameters123     TNode<Object> receiver_and_lookup_start_object() const {
124       DCHECK_EQ(receiver_, lookup_start_object_);
125       return receiver_;
126     }
127 
128    private:
129     TNode<Context> context_;
130     TNode<Object> receiver_;
131     TNode<Object> name_;
132     TNode<TaggedIndex> slot_;
133     TNode<HeapObject> vector_;
134     base::Optional<TNode<Object>> lookup_start_object_;
135   };
136 
137   struct LazyLoadICParameters {
138     LazyLoadICParameters(
139         LazyNode<Context> context, TNode<Object> receiver,
140         LazyNode<Object> name, LazyNode<TaggedIndex> slot,
141         TNode<HeapObject> vector,
142         base::Optional<TNode<Object>> lookup_start_object = base::nullopt)
context_LazyLoadICParameters143         : context_(context),
144           receiver_(receiver),
145           name_(name),
146           slot_(slot),
147           vector_(vector),
148           lookup_start_object_(lookup_start_object ? lookup_start_object.value()
149                                                    : receiver) {}
150 
LazyLoadICParametersLazyLoadICParameters151     explicit LazyLoadICParameters(const LoadICParameters* p)
152         : receiver_(p->receiver()),
153           vector_(p->vector()),
154           lookup_start_object_(p->lookup_start_object()) {
155       slot_ = [=] { return p->slot(); };
156       context_ = [=] { return p->context(); };
157       name_ = [=] { return p->name(); };
158     }
159 
contextLazyLoadICParameters160     TNode<Context> context() const { return context_(); }
receiverLazyLoadICParameters161     TNode<Object> receiver() const { return receiver_; }
nameLazyLoadICParameters162     TNode<Object> name() const { return name_(); }
slotLazyLoadICParameters163     TNode<TaggedIndex> slot() const { return slot_(); }
vectorLazyLoadICParameters164     TNode<HeapObject> vector() const { return vector_; }
lookup_start_objectLazyLoadICParameters165     TNode<Object> lookup_start_object() const { return lookup_start_object_; }
166 
167     // Usable in cases where the receiver and the lookup start object are
168     // expected to be the same, i.e., when "receiver != lookup_start_object"
169     // case is not supported or not expected by the surrounding code.
receiver_and_lookup_start_objectLazyLoadICParameters170     TNode<Object> receiver_and_lookup_start_object() const {
171       DCHECK_EQ(receiver_, lookup_start_object_);
172       return receiver_;
173     }
174 
175    private:
176     LazyNode<Context> context_;
177     TNode<Object> receiver_;
178     LazyNode<Object> name_;
179     LazyNode<TaggedIndex> slot_;
180     TNode<HeapObject> vector_;
181     TNode<Object> lookup_start_object_;
182   };
183 
184   void LoadGlobalIC(TNode<HeapObject> maybe_feedback_vector,
185                     const LazyNode<TaggedIndex>& lazy_slot,
186                     const LazyNode<Context>& lazy_context,
187                     const LazyNode<Name>& lazy_name, TypeofMode typeof_mode,
188                     ExitPoint* exit_point);
189 
190   // Specialized LoadIC for inlined bytecode handler, hand-tuned to omit frame
191   // construction on common paths.
192   void LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
193                               ExitPoint* exit_point);
194 
195   // Loads dataX field from the DataHandler object.
196   TNode<MaybeObject> LoadHandlerDataField(TNode<DataHandler> handler,
197                                           int data_index);
198 
199  protected:
200   enum class StoreICMode {
201     // TODO(v8:12548): rename to kDefineKeyedOwnInLiteral
202     kDefault,
203     kDefineNamedOwn,
204     kDefineKeyedOwn,
205   };
206   struct StoreICParameters {
StoreICParametersStoreICParameters207     StoreICParameters(TNode<Context> context,
208                       base::Optional<TNode<Object>> receiver,
209                       TNode<Object> name, TNode<Object> value,
210                       TNode<TaggedIndex> slot, TNode<HeapObject> vector,
211                       StoreICMode mode)
212         : context_(context),
213           receiver_(receiver),
214           name_(name),
215           value_(value),
216           slot_(slot),
217           vector_(vector),
218           mode_(mode) {}
219 
contextStoreICParameters220     TNode<Context> context() const { return context_; }
receiverStoreICParameters221     TNode<Object> receiver() const { return receiver_.value(); }
nameStoreICParameters222     TNode<Object> name() const { return name_; }
valueStoreICParameters223     TNode<Object> value() const { return value_; }
slotStoreICParameters224     TNode<TaggedIndex> slot() const { return slot_; }
vectorStoreICParameters225     TNode<HeapObject> vector() const { return vector_; }
226 
lookup_start_objectStoreICParameters227     TNode<Object> lookup_start_object() const { return receiver(); }
228 
receiver_is_nullStoreICParameters229     bool receiver_is_null() const { return !receiver_.has_value(); }
230 
IsDefineNamedOwnStoreICParameters231     bool IsDefineNamedOwn() const {
232       return mode_ == StoreICMode::kDefineNamedOwn;
233     }
IsDefineKeyedOwnStoreICParameters234     bool IsDefineKeyedOwn() const {
235       return mode_ == StoreICMode::kDefineKeyedOwn;
236     }
IsAnyDefineOwnStoreICParameters237     bool IsAnyDefineOwn() const {
238       return IsDefineNamedOwn() || IsDefineKeyedOwn();
239     }
240 
241    private:
242     TNode<Context> context_;
243     base::Optional<TNode<Object>> receiver_;
244     TNode<Object> name_;
245     TNode<Object> value_;
246     TNode<TaggedIndex> slot_;
247     TNode<HeapObject> vector_;
248     StoreICMode mode_;
249   };
250 
251   enum class LoadAccessMode { kLoad, kHas };
252   enum class ICMode { kNonGlobalIC, kGlobalIC };
253   enum ElementSupport { kOnlyProperties, kSupportElements };
254   void HandleStoreICHandlerCase(
255       const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss,
256       ICMode ic_mode, ElementSupport support_elements = kOnlyProperties);
257   enum StoreTransitionMapFlags {
258     kDontCheckPrototypeValidity = 0,
259     kCheckPrototypeValidity = 1 << 0,
260     kValidateTransitionHandler = 1 << 1,
261     kStoreTransitionMapFlagsMask =
262         kCheckPrototypeValidity | kValidateTransitionHandler,
263   };
264   void HandleStoreICTransitionMapHandlerCase(const StoreICParameters* p,
265                                              TNode<Map> transition_map,
266                                              Label* miss,
267                                              StoreTransitionMapFlags flags);
268 
269   void JumpIfDataProperty(TNode<Uint32T> details, Label* writable,
270                           Label* readonly);
271 
272   void InvalidateValidityCellIfPrototype(
273       TNode<Map> map, base::Optional<TNode<Uint32T>> bitfield3 = base::nullopt);
274 
275   void OverwriteExistingFastDataProperty(TNode<HeapObject> object,
276                                          TNode<Map> object_map,
277                                          TNode<DescriptorArray> descriptors,
278                                          TNode<IntPtrT> descriptor_name_index,
279                                          TNode<Uint32T> details,
280                                          TNode<Object> value, Label* slow,
281                                          bool do_transitioning_store);
282 
283   void StoreJSSharedStructField(TNode<Context> context,
284                                 TNode<HeapObject> shared_struct,
285                                 TNode<Map> shared_struct_map,
286                                 TNode<DescriptorArray> descriptors,
287                                 TNode<IntPtrT> descriptor_name_index,
288                                 TNode<Uint32T> details, TNode<Object> value);
289 
290   TNode<BoolT> IsPropertyDetailsConst(TNode<Uint32T> details);
291 
292   void CheckFieldType(TNode<DescriptorArray> descriptors,
293                       TNode<IntPtrT> name_index, TNode<Word32T> representation,
294                       TNode<Object> value, Label* bailout);
295 
296  private:
297   // Stub generation entry points.
298 
299   // LoadIC contains the full LoadIC logic, while LoadIC_Noninlined contains
300   // logic not inlined into Ignition bytecode handlers.
301   void LoadIC(const LoadICParameters* p);
302 
303   // Can be used in the receiver != lookup_start_object case.
304   void LoadIC_Noninlined(const LoadICParameters* p,
305                          TNode<Map> lookup_start_object_map,
306                          TNode<HeapObject> feedback,
307                          TVariable<MaybeObject>* var_handler, Label* if_handler,
308                          Label* miss, ExitPoint* exit_point);
309 
310   void LoadSuperIC(const LoadICParameters* p);
311 
312   TNode<Object> LoadDescriptorValue(TNode<Map> map,
313                                     TNode<IntPtrT> descriptor_entry);
314   TNode<MaybeObject> LoadDescriptorValueOrFieldType(
315       TNode<Map> map, TNode<IntPtrT> descriptor_entry);
316 
317   void LoadIC_NoFeedback(const LoadICParameters* p, TNode<Smi> smi_typeof_mode);
318   void LoadSuperIC_NoFeedback(const LoadICParameters* p);
319   void LoadGlobalIC_NoFeedback(TNode<Context> context, TNode<Object> name,
320                                TNode<Smi> smi_typeof_mode);
321 
322   void KeyedLoadIC(const LoadICParameters* p, LoadAccessMode access_mode);
323   void KeyedLoadICGeneric(const LoadICParameters* p);
324   void KeyedLoadICPolymorphicName(const LoadICParameters* p,
325                                   LoadAccessMode access_mode);
326 
327   void StoreIC(const StoreICParameters* p);
328   void StoreGlobalIC(const StoreICParameters* p);
329   void StoreGlobalIC_PropertyCellCase(TNode<PropertyCell> property_cell,
330                                       TNode<Object> value,
331                                       ExitPoint* exit_point, Label* miss);
332   void KeyedStoreIC(const StoreICParameters* p);
333   void DefineKeyedOwnIC(const StoreICParameters* p);
334   void StoreInArrayLiteralIC(const StoreICParameters* p);
335 
336   // IC dispatcher behavior.
337 
338   // Checks monomorphic case. Returns {feedback} entry of the vector.
339   TNode<MaybeObject> TryMonomorphicCase(TNode<TaggedIndex> slot,
340                                         TNode<FeedbackVector> vector,
341                                         TNode<Map> lookup_start_object_map,
342                                         Label* if_handler,
343                                         TVariable<MaybeObject>* var_handler,
344                                         Label* if_miss);
345   void HandlePolymorphicCase(TNode<Map> lookup_start_object_map,
346                              TNode<WeakFixedArray> feedback, Label* if_handler,
347                              TVariable<MaybeObject>* var_handler,
348                              Label* if_miss);
349 
350   void TryMegaDOMCase(TNode<Object> lookup_start_object,
351                       TNode<Map> lookup_start_object_map,
352                       TVariable<MaybeObject>* var_handler, TNode<Object> vector,
353                       TNode<TaggedIndex> slot, Label* miss,
354                       ExitPoint* exit_point);
355 
356   // LoadIC implementation.
357   void HandleLoadICHandlerCase(
358       const LazyLoadICParameters* p, TNode<Object> handler, Label* miss,
359       ExitPoint* exit_point, ICMode ic_mode = ICMode::kNonGlobalIC,
360       OnNonExistent on_nonexistent = OnNonExistent::kReturnUndefined,
361       ElementSupport support_elements = kOnlyProperties,
362       LoadAccessMode access_mode = LoadAccessMode::kLoad);
363 
364   void HandleLoadICSmiHandlerCase(const LazyLoadICParameters* p,
365                                   TNode<Object> holder, TNode<Smi> smi_handler,
366                                   TNode<Object> handler, Label* miss,
367                                   ExitPoint* exit_point, ICMode ic_mode,
368                                   OnNonExistent on_nonexistent,
369                                   ElementSupport support_elements,
370                                   LoadAccessMode access_mode);
371 
372   void HandleLoadICProtoHandler(const LazyLoadICParameters* p,
373                                 TNode<DataHandler> handler,
374                                 TVariable<Object>* var_holder,
375                                 TVariable<Object>* var_smi_handler,
376                                 Label* if_smi_handler, Label* miss,
377                                 ExitPoint* exit_point, ICMode ic_mode,
378                                 LoadAccessMode access_mode);
379 
380   void HandleLoadCallbackProperty(const LazyLoadICParameters* p,
381                                   TNode<JSObject> holder,
382                                   TNode<WordT> handler_word,
383                                   ExitPoint* exit_point);
384 
385   void HandleLoadAccessor(const LazyLoadICParameters* p,
386                           TNode<CallHandlerInfo> call_handler_info,
387                           TNode<WordT> handler_word, TNode<DataHandler> handler,
388                           TNode<IntPtrT> handler_kind, ExitPoint* exit_point);
389 
390   void HandleLoadField(TNode<JSObject> holder, TNode<WordT> handler_word,
391                        TVariable<Float64T>* var_double_value,
392                        Label* rebox_double, Label* miss, ExitPoint* exit_point);
393 
394 #if V8_ENABLE_WEBASSEMBLY
395   void HandleLoadWasmField(TNode<WasmObject> holder,
396                            TNode<Int32T> wasm_value_type,
397                            TNode<IntPtrT> field_offset,
398                            TVariable<Float64T>* var_double_value,
399                            Label* rebox_double, ExitPoint* exit_point);
400 
401   void HandleLoadWasmField(TNode<WasmObject> holder, TNode<WordT> handler_word,
402                            TVariable<Float64T>* var_double_value,
403                            Label* rebox_double, ExitPoint* exit_point);
404 #endif  // V8_ENABLE_WEBASSEMBLY
405 
406   void EmitAccessCheck(TNode<Context> expected_native_context,
407                        TNode<Context> context, TNode<Object> receiver,
408                        Label* can_access, Label* miss);
409 
410   void HandleLoadICSmiHandlerLoadNamedCase(
411       const LazyLoadICParameters* p, TNode<Object> holder,
412       TNode<IntPtrT> handler_kind, TNode<WordT> handler_word,
413       Label* rebox_double, TVariable<Float64T>* var_double_value,
414       TNode<Object> handler, Label* miss, ExitPoint* exit_point, ICMode ic_mode,
415       OnNonExistent on_nonexistent, ElementSupport support_elements);
416 
417   void HandleLoadICSmiHandlerHasNamedCase(const LazyLoadICParameters* p,
418                                           TNode<Object> holder,
419                                           TNode<IntPtrT> handler_kind,
420                                           Label* miss, ExitPoint* exit_point,
421                                           ICMode ic_mode);
422 
423   // LoadGlobalIC implementation.
424 
425   void LoadGlobalIC_TryPropertyCellCase(TNode<FeedbackVector> vector,
426                                         TNode<TaggedIndex> slot,
427                                         const LazyNode<Context>& lazy_context,
428                                         ExitPoint* exit_point,
429                                         Label* try_handler, Label* miss);
430 
431   void LoadGlobalIC_TryHandlerCase(TNode<FeedbackVector> vector,
432                                    TNode<TaggedIndex> slot,
433                                    const LazyNode<Context>& lazy_context,
434                                    const LazyNode<Name>& lazy_name,
435                                    TypeofMode typeof_mode,
436                                    ExitPoint* exit_point, Label* miss);
437 
438   // This is a copy of ScriptContextTable::Lookup. They should be kept in sync.
439   void ScriptContextTableLookup(TNode<Name> name,
440                                 TNode<NativeContext> native_context,
441                                 Label* found_hole, Label* not_found);
442 
443   // StoreIC implementation.
444 
445   void HandleStoreICProtoHandler(const StoreICParameters* p,
446                                  TNode<StoreHandler> handler, Label* miss,
447                                  ICMode ic_mode,
448                                  ElementSupport support_elements);
449   void HandleStoreICSmiHandlerCase(TNode<Word32T> handler_word,
450                                    TNode<JSObject> holder, TNode<Object> value,
451                                    Label* miss);
452   void HandleStoreICSmiHandlerJSSharedStructFieldCase(
453       TNode<Context> context, TNode<Word32T> handler_word,
454       TNode<JSObject> holder, TNode<Object> value);
455   void HandleStoreFieldAndReturn(TNode<Word32T> handler_word,
456                                  TNode<JSObject> holder, TNode<Object> value,
457                                  base::Optional<TNode<Float64T>> double_value,
458                                  Representation representation, Label* miss);
459 
460   void CheckPrototypeValidityCell(TNode<Object> maybe_validity_cell,
461                                   Label* miss);
462   void HandleStoreICNativeDataProperty(const StoreICParameters* p,
463                                        TNode<HeapObject> holder,
464                                        TNode<Word32T> handler_word);
465 
466   void HandleStoreToProxy(const StoreICParameters* p, TNode<JSProxy> proxy,
467                           Label* miss, ElementSupport support_elements);
468 
469   void HandleStoreAccessor(const StoreICParameters* p, TNode<HeapObject> holder,
470                            TNode<Word32T> handler_word);
471 
472   // KeyedLoadIC_Generic implementation.
473 
474   void GenericElementLoad(TNode<HeapObject> lookup_start_object,
475                           TNode<Map> lookup_start_object_map,
476                           TNode<Int32T> lookup_start_object_instance_type,
477                           TNode<IntPtrT> index, Label* slow);
478 
479   enum UseStubCache { kUseStubCache, kDontUseStubCache };
480   void GenericPropertyLoad(TNode<HeapObject> lookup_start_object,
481                            TNode<Map> lookup_start_object_map,
482                            TNode<Int32T> lookup_start_object_instance_type,
483                            const LoadICParameters* p, Label* slow,
484                            UseStubCache use_stub_cache = kUseStubCache);
485 
486   // Low-level helpers.
487 
488   using OnCodeHandler = std::function<void(TNode<CodeT> code_handler)>;
489   using OnFoundOnLookupStartObject = std::function<void(
490       TNode<PropertyDictionary> properties, TNode<IntPtrT> name_index)>;
491 
492   template <typename ICHandler, typename ICParameters>
493   TNode<Object> HandleProtoHandler(
494       const ICParameters* p, TNode<DataHandler> handler,
495       const OnCodeHandler& on_code_handler,
496       const OnFoundOnLookupStartObject& on_found_on_lookup_start_object,
497       Label* miss, ICMode ic_mode);
498 
499   void CheckHeapObjectTypeMatchesDescriptor(TNode<Word32T> handler_word,
500                                             TNode<JSObject> holder,
501                                             TNode<Object> value,
502                                             Label* bailout);
503   // Double fields store double values in a mutable box, where stores are
504   // writes into this box rather than HeapNumber assignment.
505   void CheckDescriptorConsidersNumbersMutable(TNode<Word32T> handler_word,
506                                               TNode<JSObject> holder,
507                                               Label* bailout);
508 
509   // Extends properties backing store by JSObject::kFieldsAdded elements,
510   // returns updated properties backing store.
511   TNode<PropertyArray> ExtendPropertiesBackingStore(TNode<HeapObject> object,
512                                                     TNode<IntPtrT> index);
513 
514   void EmitFastElementsBoundsCheck(TNode<JSObject> object,
515                                    TNode<FixedArrayBase> elements,
516                                    TNode<IntPtrT> intptr_index,
517                                    TNode<BoolT> is_jsarray_condition,
518                                    Label* miss);
519   void EmitElementLoad(TNode<HeapObject> object, TNode<Word32T> elements_kind,
520                        TNode<IntPtrT> key, TNode<BoolT> is_jsarray_condition,
521                        Label* if_hole, Label* rebox_double,
522                        TVariable<Float64T>* var_double_value,
523                        Label* unimplemented_elements_kind, Label* out_of_bounds,
524                        Label* miss, ExitPoint* exit_point,
525                        LoadAccessMode access_mode = LoadAccessMode::kLoad);
526 
527   // Stub cache access helpers.
528 
529   // This enum is used here as a replacement for StubCache::Table to avoid
530   // including stub cache header.
531   enum StubCacheTable : int;
532 
533   TNode<IntPtrT> StubCachePrimaryOffset(TNode<Name> name, TNode<Map> map);
534   TNode<IntPtrT> StubCacheSecondaryOffset(TNode<Name> name, TNode<Map> map);
535 
536   void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
537                               TNode<IntPtrT> entry_offset, TNode<Object> name,
538                               TNode<Map> map, Label* if_handler,
539                               TVariable<MaybeObject>* var_handler,
540                               Label* if_miss);
541 
542   void BranchIfPrototypesHaveNoElements(TNode<Map> receiver_map,
543                                         Label* definitely_no_elements,
544                                         Label* possibly_elements);
545 };
546 
547 // Abstraction over direct and indirect exit points. Direct exits correspond to
548 // tailcalls and Return, while indirect exits store the result in a variable
549 // and then jump to an exit label.
550 class ExitPoint {
551  private:
552   using CodeAssemblerLabel = compiler::CodeAssemblerLabel;
553 
554  public:
555   using IndirectReturnHandler = std::function<void(TNode<Object> result)>;
556 
ExitPoint(CodeStubAssembler * assembler)557   explicit ExitPoint(CodeStubAssembler* assembler)
558       : ExitPoint(assembler, nullptr) {}
559 
ExitPoint(CodeStubAssembler * assembler,const IndirectReturnHandler & indirect_return_handler)560   ExitPoint(CodeStubAssembler* assembler,
561             const IndirectReturnHandler& indirect_return_handler)
562       : asm_(assembler), indirect_return_handler_(indirect_return_handler) {}
563 
ExitPoint(CodeStubAssembler * assembler,CodeAssemblerLabel * out,compiler::CodeAssembler::TVariable<Object> * var_result)564   ExitPoint(CodeStubAssembler* assembler, CodeAssemblerLabel* out,
565             compiler::CodeAssembler::TVariable<Object>* var_result)
566       : ExitPoint(assembler, [=](TNode<Object> result) {
567           *var_result = result;
568           assembler->Goto(out);
569         }) {
570     DCHECK_EQ(out != nullptr, var_result != nullptr);
571   }
572 
573   template <class... TArgs>
ReturnCallRuntime(Runtime::FunctionId function,TNode<Context> context,TArgs...args)574   void ReturnCallRuntime(Runtime::FunctionId function, TNode<Context> context,
575                          TArgs... args) {
576     if (IsDirect()) {
577       asm_->TailCallRuntime(function, context, args...);
578     } else {
579       indirect_return_handler_(asm_->CallRuntime(function, context, args...));
580     }
581   }
582 
583   template <class... TArgs>
ReturnCallStub(Callable const & callable,TNode<Context> context,TArgs...args)584   void ReturnCallStub(Callable const& callable, TNode<Context> context,
585                       TArgs... args) {
586     if (IsDirect()) {
587       asm_->TailCallStub(callable, context, args...);
588     } else {
589       indirect_return_handler_(asm_->CallStub(callable, context, args...));
590     }
591   }
592 
593   template <class... TArgs>
ReturnCallStub(const CallInterfaceDescriptor & descriptor,TNode<CodeT> target,TNode<Context> context,TArgs...args)594   void ReturnCallStub(const CallInterfaceDescriptor& descriptor,
595                       TNode<CodeT> target, TNode<Context> context,
596                       TArgs... args) {
597     if (IsDirect()) {
598       asm_->TailCallStub(descriptor, target, context, args...);
599     } else {
600       indirect_return_handler_(
601           asm_->CallStub(descriptor, target, context, args...));
602     }
603   }
604 
Return(const TNode<Object> result)605   void Return(const TNode<Object> result) {
606     if (IsDirect()) {
607       asm_->Return(result);
608     } else {
609       indirect_return_handler_(result);
610     }
611   }
612 
IsDirect()613   bool IsDirect() const { return !indirect_return_handler_; }
614 
615  private:
616   CodeStubAssembler* const asm_;
617   IndirectReturnHandler indirect_return_handler_;
618 };
619 
620 }  // namespace internal
621 }  // namespace v8
622 
623 #endif  // V8_IC_ACCESSOR_ASSEMBLER_H_
624