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