v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
feedback-vector.cc
Go to the documentation of this file.
1// Copyright 2014 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
6
7#include <bit>
8#include <optional>
9
11#include "src/common/globals.h"
14#include "src/heap/heap-inl.h"
17#include "src/ic/ic-inl.h"
21#include "src/objects/map-inl.h"
22#include "src/objects/objects.h"
23
24namespace v8::internal {
25
27 int slot = slot_count();
28 int entries_per_slot = FeedbackMetadata::GetSlotSize(kind);
29 append(kind);
30 for (int i = 1; i < entries_per_slot; i++) {
32 }
33 return FeedbackSlot(slot);
34}
35
37 Tagged<HeapObject> heap_object;
38 if (!feedback.GetHeapObjectIfStrong(&heap_object)) return false;
39 if (IsString(heap_object)) {
40 DCHECK(IsInternalizedString(heap_object));
41 return true;
42 }
43 if (!IsSymbol(heap_object)) return false;
44 Tagged<Symbol> symbol = Cast<Symbol>(heap_object);
46 return symbol != roots.uninitialized_symbol() &&
47 symbol != roots.mega_dom_symbol() &&
48 symbol != roots.megamorphic_symbol();
49}
50
51std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind) {
53}
54
56 int index = VectorICComputer::index(0, slot.ToInt());
57 int data = get(index);
58 return VectorICComputer::decode(data, slot.ToInt());
59}
60
62 int index = VectorICComputer::index(0, slot.ToInt());
63 int data = get(index);
64 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
65 set(index, new_data);
66}
67
73
80
81// static
82template <typename IsolateT>
84 const FeedbackVectorSpec* spec) {
85 auto* factory = isolate->factory();
86
87 const int slot_count = spec->slot_count();
89 if (slot_count == 0 && create_closure_slot_count == 0) {
90 return factory->empty_feedback_metadata();
91 }
92#ifdef DEBUG
93 for (int i = 0; i < slot_count;) {
95 int entry_size = FeedbackMetadata::GetSlotSize(kind);
96 for (int j = 1; j < entry_size; j++) {
97 kind = spec->GetKind(FeedbackSlot(i + j));
99 }
100 i += entry_size;
101 }
102#endif
103
104 Handle<FeedbackMetadata> metadata =
105 factory->NewFeedbackMetadata(slot_count, create_closure_slot_count);
106
107 // Initialize the slots. The raw data section has already been pre-zeroed in
108 // NewFeedbackMetadata.
109 for (int i = 0; i < slot_count; i++) {
110 FeedbackSlot slot(i);
111 FeedbackSlotKind kind = spec->GetKind(slot);
112 metadata->SetKind(slot, kind);
113 }
114
115 for (int i = 0; i < create_closure_slot_count; i++) {
117 metadata->SetCreateClosureParameterCount(i, parameter_count);
118 }
119
120 return metadata;
121}
122
124 Isolate* isolate, const FeedbackVectorSpec* spec);
126 LocalIsolate* isolate, const FeedbackVectorSpec* spec);
127
129 const FeedbackVectorSpec* other_spec) const {
130 if (other_spec->slot_count() != slot_count()) {
131 return true;
132 }
133
134 int slots = slot_count();
135 for (int i = 0; i < slots;) {
136 FeedbackSlot slot(i);
138 int entry_size = FeedbackMetadata::GetSlotSize(kind);
139
140 if (kind != other_spec->GetKind(slot)) {
141 return true;
142 }
143 i += entry_size;
144 }
145 return false;
146}
147
149 switch (kind) {
151 return "Invalid";
153 return "Call";
155 return "LoadProperty";
157 return "LoadGlobalInsideTypeof";
159 return "LoadGlobalNotInsideTypeof";
161 return "LoadKeyed";
163 return "HasKeyed";
165 return "SetNamedSloppy";
167 return "SetNamedStrict";
169 return "DefineNamedOwn";
171 return "DefineKeyedOwn";
173 return "StoreGlobalSloppy";
175 return "StoreGlobalStrict";
177 return "StoreKeyedSloppy";
179 return "StoreKeyedStrict";
181 return "StoreInArrayLiteral";
183 return "BinaryOp";
185 return "CompareOp";
187 return "DefineKeyedOwnPropertyInLiteral";
189 return "Literal";
191 return "ForIn";
193 return "InstanceOf";
195 return "TypeOf";
197 return "CloneObject";
199 return "JumpLoop";
200 }
201}
202
204 DCHECK(!is_empty());
205 return metadata()->GetKind(slot);
206}
207
209 AcquireLoadTag tag) const {
210 DCHECK(!is_empty());
211 return metadata(tag)->GetKind(slot);
212}
213
214// static
217 AllocationType allocation) {
218 int length = shared->feedback_metadata()->create_closure_slot_count();
219 if (length == 0) {
220 return isolate->factory()->empty_closure_feedback_cell_array();
221 }
222
223 // Pre-allocate the cells s.t. we can initialize `result` without further
224 // allocation.
226 cells.reserve(length);
227 for (int i = 0; i < length; i++) {
228 DirectHandle<FeedbackCell> cell = isolate->factory()->NewNoClosuresCell();
229#ifdef V8_ENABLE_LEAPTIERING
230 uint16_t parameter_count =
231 shared->feedback_metadata()->GetCreateClosureParameterCount(i);
232 auto initial_code = BUILTIN_CODE(isolate, CompileLazy);
233 FeedbackCell::AllocateAndInstallJSDispatchHandle(
234 cell, FeedbackCell::kDispatchHandleOffset, isolate, parameter_count,
235 initial_code);
236#endif
237 cells.push_back(cell);
238 }
239
240 std::optional<DisallowGarbageCollection> no_gc;
241 auto result = Allocate(isolate, length, &no_gc, allocation);
242 for (int i = 0; i < length; i++) {
243 result->set(i, *cells[i]);
244 }
245
246 return result;
247}
248
249// static
252 DirectHandle<ClosureFeedbackCellArray> closure_feedback_cell_array,
253 DirectHandle<FeedbackCell> parent_feedback_cell,
254 IsCompiledScope* is_compiled_scope) {
255 DCHECK(is_compiled_scope->is_compiled());
256 Factory* factory = isolate->factory();
257
258 DirectHandle<FeedbackMetadata> feedback_metadata(shared->feedback_metadata(),
259 isolate);
260 const int slot_count = feedback_metadata->slot_count();
261
263 shared, closure_feedback_cell_array, parent_feedback_cell);
264
265 DCHECK_EQ(vector->length(), slot_count);
266
267 DCHECK_EQ(vector->shared_function_info(), *shared);
268 DCHECK_EQ(vector->invocation_count(), 0);
269#ifndef V8_ENABLE_LEAPTIERING
270 DCHECK_EQ(vector->tiering_state(), TieringState::kNone);
271 DCHECK(!vector->maybe_has_maglev_code());
272 DCHECK(!vector->maybe_has_turbofan_code());
273 DCHECK(vector->maybe_optimized_code().IsCleared());
274#endif // !V8_ENABLE_LEAPTIERING
275
276 // Ensure we can skip the write barrier
277 DirectHandle<Symbol> uninitialized_sentinel = UninitializedSentinel(isolate);
278 DCHECK_EQ(ReadOnlyRoots(isolate).uninitialized_symbol(),
279 *uninitialized_sentinel);
280 for (int i = 0; i < slot_count;) {
281 FeedbackSlot slot(i);
282 FeedbackSlotKind kind = feedback_metadata->GetKind(slot);
283 int entry_size = FeedbackMetadata::GetSlotSize(kind);
284
285 Tagged<MaybeObject> extra_value = *uninitialized_sentinel;
286 switch (kind) {
292 vector->Set(slot, ClearedValue(isolate), SKIP_WRITE_BARRIER);
293 break;
298 vector->Set(slot, Smi::zero(), SKIP_WRITE_BARRIER);
299 break;
301 vector->Set(slot, Smi::zero(), SKIP_WRITE_BARRIER);
302 break;
304 vector->Set(slot, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
305 extra_value = Smi::zero();
306 break;
320 vector->Set(slot, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
321 break;
322
324 UNREACHABLE();
325 }
326 for (int j = 1; j < entry_size; j++) {
327 vector->Set(slot.WithOffset(j), extra_value, SKIP_WRITE_BARRIER);
328 }
329 i += entry_size;
330 }
331
332 if (!isolate->is_best_effort_code_coverage()) {
333 AddToVectorsForProfilingTools(isolate, vector);
334 }
335 parent_feedback_cell->set_value(*vector, kReleaseStore);
336 return vector;
337}
338
339// static
341 Isolate* isolate, const FeedbackVectorSpec* spec) {
343 FeedbackMetadata::New(isolate, spec);
345 isolate->factory()->NewSharedFunctionInfoForBuiltin(
346 isolate->factory()->empty_string(), Builtin::kIllegal, 0, kDontAdapt);
347 // Set the raw feedback metadata to circumvent checks that we are not
348 // overwriting existing metadata.
349 shared->set_raw_outer_scope_info_or_feedback_metadata(*metadata);
350 DirectHandle<ClosureFeedbackCellArray> closure_feedback_cell_array =
351 ClosureFeedbackCellArray::New(isolate, shared);
352 DirectHandle<FeedbackCell> parent_cell =
353 isolate->factory()->NewNoClosuresCell();
354
355 IsCompiledScope is_compiled_scope(shared->is_compiled_scope(isolate));
356 return FeedbackVector::New(isolate, shared, closure_feedback_cell_array,
357 parent_cell, &is_compiled_scope);
358}
359
360// static
362 Zone* zone, Isolate* isolate) {
363 FeedbackVectorSpec one_slot(zone);
364 one_slot.AddBinaryOpICSlot();
365 return NewForTesting(isolate, &one_slot);
366}
367
368// static
370 Zone* zone, Isolate* isolate) {
371 FeedbackVectorSpec one_slot(zone);
372 one_slot.AddCompareICSlot();
373 return NewForTesting(isolate, &one_slot);
374}
375
376// static
378 Isolate* isolate, DirectHandle<FeedbackVector> vector) {
379 DCHECK(!isolate->is_best_effort_code_coverage());
380 if (!vector->shared_function_info()->IsSubjectToDebugging()) return;
382 isolate->factory()->feedback_vectors_for_profiling_tools());
383 list = ArrayList::Add(isolate, list, vector);
384 isolate->SetFeedbackVectorsForProfilingTools(*list);
385}
386
387#ifdef V8_ENABLE_LEAPTIERING
388
389void FeedbackVector::set_tiering_in_progress(bool in_progress) {
390 set_flags(TieringInProgressBit::update(flags(), in_progress));
391}
392
393#else
394
396 Tagged<Code> code) {
398 int32_t state = flags();
399 // Skip setting optimized code if it would cause us to tier down.
400 if (!has_optimized_code()) {
401 state = MaybeHasTurbofanCodeBit::update(state, false);
402 } else if (!CodeKindCanTierUp(optimized_code(isolate)->kind()) ||
403 optimized_code(isolate)->kind() > code->kind()) {
404 if (!v8_flags.stress_concurrent_inlining_attach_code &&
405 !optimized_code(isolate)->marked_for_deoptimization()) {
406 return;
407 }
408 // If we fall through, we may be tiering down. This is fine since we only do
409 // that when the current code is marked for deoptimization, or because we're
410 // stress testing.
411 state = MaybeHasTurbofanCodeBit::update(state, false);
412 }
413 // TODO(mythria): We could see a CompileOptimized state here either from
414 // tests that use %OptimizeFunctionOnNextCall, --always-turbofan or because we
415 // re-mark the function for non-concurrent optimization after an OSR. We
416 // should avoid these cases and also check that marker isn't
417 // TieringState::kRequestTurbofan*.
418 set_maybe_optimized_code(MakeWeak(code->wrapper()));
419 // TODO(leszeks): Reconsider whether this could clear the tiering state vs.
420 // the callers doing so.
421 state = TieringStateBits::update(state, TieringState::kNone);
422 if (code->is_maglevved()) {
423 DCHECK(!MaybeHasTurbofanCodeBit::decode(state));
424 state = MaybeHasMaglevCodeBit::update(state, true);
425 } else {
426 DCHECK(code->is_turbofanned());
427 state = MaybeHasTurbofanCodeBit::update(state, true);
428 state = MaybeHasMaglevCodeBit::update(state, false);
429 }
430 set_flags(state);
431}
432
440
442 Isolate* isolate, Tagged<SharedFunctionInfo> shared, const char* reason) {
443 Tagged<MaybeObject> slot = maybe_optimized_code();
444 if (slot.IsCleared()) {
447 return;
448 }
449
450 Tagged<Code> code = Cast<CodeWrapper>(slot.GetHeapObject())->code(isolate);
451 if (code->marked_for_deoptimization()) {
452 Deoptimizer::TraceEvictFromOptimizedCodeCache(isolate, shared, reason);
454 }
455}
456
458 int32_t new_flags = flags();
459 new_flags = TieringStateBits::update(new_flags, state);
460 set_flags(new_flags);
461}
462
463#endif // V8_ENABLE_LEAPTIERING
464
466 set_flags(
467#ifdef V8_ENABLE_LEAPTIERING
468 TieringInProgressBit::encode(false) |
469#else
470 TieringStateBits::encode(TieringState::kNone) |
471 LogNextExecutionBit::encode(false) |
472 MaybeHasMaglevCodeBit::encode(false) |
473 MaybeHasTurbofanCodeBit::encode(false) |
474#endif // V8_ENABLE_LEAPTIERING
475 OsrTieringInProgressBit::encode(false) |
476 MaybeHasMaglevOsrCodeBit::encode(false) |
477 MaybeHasTurbofanOsrCodeBit::encode(false));
478}
479
481 Tagged<Code> code) {
483 DCHECK(!slot.IsInvalid());
484 auto current = GetOptimizedOsrCode(isolate, slot);
485 if (V8_UNLIKELY(current && current.value()->kind() > code->kind())) {
486 return;
487 }
488 Set(slot, MakeWeak(code->wrapper()));
489 set_maybe_has_optimized_osr_code(true, code->kind());
490}
491
493 return OsrTieringInProgressBit::decode(flags());
494}
495
497 set_flags(OsrTieringInProgressBit::update(flags(), osr_in_progress));
498}
499
501 if (!shared_function_info()->HasFeedbackMetadata()) return false;
502 Tagged<MaybeObject> uninitialized_sentinel =
504
505 bool feedback_updated = false;
506 FeedbackMetadataIterator iter(metadata());
507 while (iter.HasNext()) {
508 FeedbackSlot slot = iter.Next();
509
510 Tagged<MaybeObject> obj = Get(slot);
511 if (obj != uninitialized_sentinel) {
512 FeedbackNexus nexus(isolate, *this, slot);
513 feedback_updated |= nexus.Clear(behavior);
514 }
515 }
516 return feedback_updated;
517}
518
519#ifdef V8_TRACE_FEEDBACK_UPDATES
520
521// static
522void FeedbackVector::TraceFeedbackChange(Isolate* isolate,
524 FeedbackSlot slot,
525 const char* reason) {
526 int slot_count = vector->metadata()->slot_count();
527 StdoutStream os;
528 if (slot.IsInvalid()) {
529 os << "[Feedback slots in ";
530 } else {
531 FeedbackSlotKind kind = vector->metadata()->GetKind(slot);
532 os << "[Feedback slot " << slot.ToInt() << "/" << slot_count << " ("
534 << " in ";
535 }
536 ShortPrint(vector->shared_function_info(), os);
537 if (slot.IsInvalid()) {
538 os << " updated - ";
539 } else {
540 os << " updated to ";
541 vector->FeedbackSlotPrint(os, slot);
542 os << " - ";
543 }
544 os << reason << "]" << std::endl;
545}
546
547#endif
548
550 if (mode() == Mode::MainThread) {
551 return handle(object, isolate_);
552 }
554 return handle(object, local_heap_);
555}
556
558 FeedbackSlot start_slot,
559 Tagged<MaybeObject> feedback,
560 WriteBarrierMode mode,
561 Tagged<MaybeObject> feedback_extra,
562 WriteBarrierMode mode_extra) const {
563 CHECK(can_write());
564 CHECK_GT(vector->length(), start_slot.WithOffset(1).ToInt());
565 base::MutexGuard mutex_guard(isolate()->feedback_vector_access());
566 vector->Set(start_slot, feedback, mode);
567 vector->Set(start_slot.WithOffset(1), feedback_extra, mode_extra);
568}
569
570std::pair<Tagged<MaybeObject>, Tagged<MaybeObject>>
572 FeedbackSlot slot) const {
573 base::MutexGuardIf guard(isolate()->feedback_vector_access(),
575 Tagged<MaybeObject> feedback = vector->Get(slot);
576 Tagged<MaybeObject> feedback_extra = vector->Get(slot.WithOffset(1));
577 return std::make_pair(feedback, feedback_extra);
578}
579
581 FeedbackSlot slot)
582 : vector_handle_(vector),
583 slot_(slot),
584 config_(NexusConfig::FromMainThread(isolate)) {
585 kind_ = vector.is_null() ? FeedbackSlotKind::kInvalid : vector->GetKind(slot);
586}
587
589 FeedbackSlot slot)
590 : vector_(vector),
591 slot_(slot),
592 config_(NexusConfig::FromMainThread(isolate)) {
593 kind_ = vector.is_null() ? FeedbackSlotKind::kInvalid : vector->GetKind(slot);
594}
595
597 const NexusConfig& config)
598 : vector_handle_(vector),
599 slot_(slot),
600 kind_(vector->GetKind(slot, kAcquireLoad)),
601 config_(config) {}
602
604 DCHECK(config()->can_write());
606 config()->isolate()->factory()->NewWeakFixedArray(length);
607 return array;
608}
609
611 Isolate* isolate = config()->isolate();
612 switch (kind()) {
619 break;
624 break;
627 break;
641 break;
644 break;
645 default:
646 UNREACHABLE();
647 }
648}
649
651 bool feedback_updated = false;
652
653 switch (kind()) {
658 if (V8_LIKELY(behavior == ClearBehavior::kDefault)) {
659 // We don't clear these, either.
660 } else if (!IsCleared()) {
663 feedback_updated = true;
664 }
665 break;
666
668 if (!IsCleared()) {
670 feedback_updated = true;
671 }
672 break;
673
693 if (!IsCleared()) {
695 feedback_updated = true;
696 }
697 break;
698
700 UNREACHABLE();
701 }
702 return feedback_updated;
703}
704
707 Isolate* isolate = config()->isolate();
709 if (GetFeedback() != sentinel) {
710 SetFeedback(sentinel, SKIP_WRITE_BARRIER, ClearedValue(isolate));
711 return true;
712 }
713
714 return false;
715}
716
723
727 Tagged<MaybeObject> maybe_extra =
728 Smi::FromInt(static_cast<int>(property_type));
729
730 auto feedback = GetFeedbackPair();
731 bool update_required =
732 feedback.first != sentinel || feedback.second != maybe_extra;
733 if (update_required) {
734 SetFeedback(sentinel, SKIP_WRITE_BARRIER, maybe_extra, SKIP_WRITE_BARRIER);
735 }
736 return update_required;
737}
738
740 FeedbackIterator it(this);
741 if (!it.done()) {
742 return it.map();
743 }
744
745 return Map();
746}
747
749 Tagged<MaybeObject> feedback, extra;
750 std::tie(feedback, extra) = GetFeedbackPair();
751
752 switch (kind()) {
754 if (IsSmi(feedback)) return InlineCacheState::UNINITIALIZED;
756
762 if (IsSmi(feedback)) return InlineCacheState::MONOMORPHIC;
763
764 DCHECK(feedback.IsWeakOrCleared());
765 if (!feedback.IsCleared() || extra != UninitializedSentinel()) {
767 }
769 }
770
781 if (feedback == UninitializedSentinel()) {
783 }
784 if (feedback == MegamorphicSentinel()) {
786 }
787 if (feedback == MegaDOMSentinel()) {
790 }
791 if (feedback.IsWeakOrCleared()) {
792 // Don't check if the map is cleared.
794 }
795 Tagged<HeapObject> heap_object;
796 if (feedback.GetHeapObjectIfStrong(&heap_object)) {
797 if (IsWeakFixedArray(heap_object)) {
798 // Determine state purely by our structure, don't check if the maps
799 // are cleared.
801 }
802 if (IsName(heap_object)) {
805 Tagged<Object> extra_object = extra.GetHeapObjectAssumeStrong();
806 Tagged<WeakFixedArray> extra_array =
807 Cast<WeakFixedArray>(extra_object);
808 return extra_array->length() > 2 ? InlineCacheState::POLYMORPHIC
810 }
811 }
812 // TODO(1393773): Remove once the issue is solved.
813 Address vector_ptr = vector().ptr();
815 reinterpret_cast<void*>(feedback.ptr()),
816 reinterpret_cast<void*>(extra.ptr()),
817 reinterpret_cast<void*>(vector_ptr),
818 reinterpret_cast<void*>(static_cast<intptr_t>(slot_.ToInt())),
819 reinterpret_cast<void*>(static_cast<intptr_t>(kind())),
820 // Include part of the feedback vector containing the slot.
821 reinterpret_cast<void*>(
823 UNREACHABLE();
824 }
826 Tagged<HeapObject> heap_object;
827 if (feedback == MegamorphicSentinel()) {
829 } else if (feedback.IsWeakOrCleared()) {
830 if (feedback.GetHeapObjectIfWeak(&heap_object)) {
831 if (IsFeedbackCell(heap_object)) {
833 }
834 CHECK(IsJSFunction(heap_object) || IsJSBoundFunction(heap_object));
835 }
837 } else if (feedback.GetHeapObjectIfStrong(&heap_object) &&
838 IsAllocationSite(heap_object)) {
840 }
841
842 CHECK_EQ(feedback, UninitializedSentinel());
844 }
847 if (hint == BinaryOperationHint::kNone) {
849 } else if (hint == BinaryOperationHint::kAny) {
851 }
852
854 }
857 if (hint == CompareOperationHint::kNone) {
859 } else if (hint == CompareOperationHint::kAny) {
861 }
862
864 }
867 if (hint == ForInHint::kNone) {
869 } else if (hint == ForInHint::kAny) {
871 }
873 }
875 if (feedback == Smi::zero()) {
877 } else if (feedback == Smi::FromInt(TypeOfFeedback::kAny)) {
880 static_cast<uint32_t>(feedback.ToSmi().value())) == 1) {
882 } else {
884 }
885 }
887 if (feedback == UninitializedSentinel()) {
889 } else if (feedback == MegamorphicSentinel()) {
891 }
893 }
895 if (feedback == UninitializedSentinel()) {
897 } else if (feedback.IsWeakOrCleared()) {
898 // Don't check if the map is cleared.
900 }
901
903 }
904
906 if (feedback == UninitializedSentinel()) {
908 }
909 if (feedback == MegamorphicSentinel()) {
911 }
912 if (feedback.IsWeakOrCleared()) {
914 }
915
916 DCHECK(IsWeakFixedArray(feedback.GetHeapObjectAssumeStrong()));
918 }
919
921 UNREACHABLE();
922 }
924}
925
931
932#if DEBUG
933namespace {
934bool shouldStressLexicalIC(int script_context_index, int context_slot_index) {
935 return (script_context_index + context_slot_index) % 100 == 0;
936}
937} // namespace
938#endif
939
940bool FeedbackNexus::ConfigureLexicalVarMode(int script_context_index,
941 int context_slot_index,
942 bool immutable) {
944 DCHECK_LE(0, script_context_index);
945 DCHECK_LE(0, context_slot_index);
946#if DEBUG
947 if (v8_flags.stress_ic &&
948 shouldStressLexicalIC(script_context_index, context_slot_index)) {
949 return false;
950 }
951#endif
952 if (!ContextIndexBits::is_valid(script_context_index) ||
953 !SlotIndexBits::is_valid(context_slot_index) ||
954 !ImmutabilityBit::is_valid(immutable)) {
955 return false;
956 }
957 int config = ContextIndexBits::encode(script_context_index) |
958 SlotIndexBits::encode(context_slot_index) |
959 ImmutabilityBit::encode(immutable);
960
963 return true;
964}
965
973
975 DirectHandle<Map> source_map, const MaybeObjectHandle& handler_handle) {
976 // TODO(olivf): Introduce a CloneHandler to deal with all the logic of this
977 // state machine which is now spread between Runtime_CloneObjectIC_Miss and
978 // this method.
979 auto GetHandler = [=]() {
980 if (IsSmi(*handler_handle)) {
981 return *handler_handle;
982 }
983 return MakeWeak(*handler_handle);
984 };
985 DCHECK(config()->can_write());
986 Isolate* isolate = config()->isolate();
988 {
989 Tagged<MaybeObject> maybe_feedback = GetFeedback();
990 if (maybe_feedback.IsStrongOrWeak()) {
991 feedback = direct_handle(maybe_feedback.GetHeapObject(), isolate);
992 } else {
993 DCHECK(maybe_feedback.IsCleared());
994 }
995 }
996 switch (ic_state()) {
998 // Cache the first map seen which meets the fast case requirements.
999 SetFeedback(MakeWeak(*source_map), UPDATE_WRITE_BARRIER, GetHandler());
1000 break;
1002 if (feedback.is_null() || feedback.is_identical_to(source_map) ||
1003 Cast<Map>(*feedback)->is_deprecated()) {
1004 SetFeedback(MakeWeak(*source_map), UPDATE_WRITE_BARRIER, GetHandler());
1005 } else {
1006 // Transition to POLYMORPHIC.
1010 Tagged<WeakFixedArray> raw_array = *array;
1011 raw_array->set(0, MakeWeak(*feedback));
1012 raw_array->set(1, GetFeedbackExtra());
1013 raw_array->set(2, MakeWeak(*source_map));
1014 raw_array->set(3, GetHandler());
1015 SetFeedback(raw_array, UPDATE_WRITE_BARRIER, ClearedValue(isolate));
1016 }
1017 break;
1019 const int kMaxElements = v8_flags.max_valid_polymorphic_map_count *
1022 int i = 0;
1023 for (; i < array->length(); i += kCloneObjectPolymorphicEntrySize) {
1024 Tagged<MaybeObject> feedback_map = array->get(i);
1025 if (feedback_map.IsCleared()) break;
1026 DirectHandle<Map> cached_map(Cast<Map>(feedback_map.GetHeapObject()),
1027 isolate);
1028 if (cached_map.is_identical_to(source_map) ||
1029 cached_map->is_deprecated())
1030 break;
1031 }
1032
1033 if (i >= array->length()) {
1034 if (i == kMaxElements) {
1035 // Transition to MEGAMORPHIC.
1037 SetFeedback(sentinel, SKIP_WRITE_BARRIER, ClearedValue(isolate));
1038 break;
1039 }
1040
1041 // Grow polymorphic feedback array.
1043 array->length() + kCloneObjectPolymorphicEntrySize);
1044 for (int j = 0; j < array->length(); ++j) {
1045 new_array->set(j, array->get(j));
1046 }
1047 SetFeedback(*new_array);
1048 array = new_array;
1049 }
1050
1051 array->set(i, MakeWeak(*source_map));
1052 array->set(i + 1, GetHandler());
1053 break;
1054 }
1055
1056 default:
1057 UNREACHABLE();
1058 }
1059}
1060
1063
1065 CHECK(IsSmi(call_count));
1066 uint32_t value = static_cast<uint32_t>(Smi::ToInt(call_count));
1067 return CallCountField::decode(value);
1068}
1069
1072
1074 CHECK(IsSmi(call_count));
1075 uint32_t count = static_cast<uint32_t>(Smi::ToInt(call_count));
1077 Tagged<MaybeObject> feedback = GetFeedback();
1078 // We could've skipped WB here (since we set the slot to the same value again)
1079 // but we don't to make WB verification happy.
1082}
1083
1086
1088 CHECK(IsSmi(call_count));
1089 uint32_t value = static_cast<uint32_t>(Smi::ToInt(call_count));
1090 return SpeculationModeField::decode(value);
1091}
1092
1095
1097 CHECK(IsSmi(call_count));
1098 uint32_t value = static_cast<uint32_t>(Smi::ToInt(call_count));
1100}
1101
1104
1105 double const invocation_count = vector()->invocation_count(kRelaxedLoad);
1106 double const call_count = GetCallCount();
1107 if (invocation_count == 0.0) { // Prevent division by 0.
1108 return 0.0f;
1109 }
1110 return static_cast<float>(call_count / invocation_count);
1111}
1112
1114 DirectHandle<Name> name, DirectHandle<Map> receiver_map,
1115 const MaybeObjectDirectHandle& handler) {
1116 DCHECK(handler.is_null() || IC::IsHandler(*handler));
1118 SetFeedback(MakeWeak(*receiver_map), UPDATE_WRITE_BARRIER, *name);
1119 } else {
1120 if (name.is_null()) {
1121 SetFeedback(MakeWeak(*receiver_map), UPDATE_WRITE_BARRIER, *handler);
1122 } else {
1124 array->set(0, MakeWeak(*receiver_map));
1125 array->set(1, *handler);
1126 SetFeedback(*name, UPDATE_WRITE_BARRIER, *array);
1127 }
1128 }
1129}
1130
1132 DirectHandle<Name> name, MapsAndHandlers const& maps_and_handlers) {
1133 int receiver_count = static_cast<int>(maps_and_handlers.size());
1134 DCHECK_GT(receiver_count, 1);
1135 DirectHandle<WeakFixedArray> array = CreateArrayOfSize(receiver_count * 2);
1136
1137 for (int current = 0; current < receiver_count; ++current) {
1138 auto [map, handler] = maps_and_handlers[current];
1139 array->set(current * 2, MakeWeak(*map));
1140 DCHECK(IC::IsHandler(*handler));
1141 array->set(current * 2 + 1, *handler);
1142 }
1143
1144 if (name.is_null()) {
1147 } else {
1148 SetFeedback(*name, UPDATE_WRITE_BARRIER, *array);
1149 }
1150}
1151
1154 int found = 0;
1155 for (FeedbackIterator it(this); !it.done(); it.Advance()) {
1156 maps->push_back(config()->NewHandle(it.map()));
1157 found++;
1158 }
1159
1160 return found;
1161}
1162
1166
1167 auto pair = GetFeedbackPair();
1168 Tagged<MaybeObject> maybe_handler = pair.second;
1169 if (!maybe_handler.IsCleared()) {
1170 MaybeObjectHandle handler = config()->NewHandle(maybe_handler);
1171 return handler;
1172 }
1173
1174 return MaybeObjectHandle();
1175}
1176
1178 TryUpdateHandler map_handler) const {
1181 int found = 0;
1182
1183 for (FeedbackIterator it(this); !it.done(); it.Advance()) {
1184 Handle<Map> map = config()->NewHandle(it.map());
1185 Tagged<MaybeObject> maybe_handler = it.handler();
1186 if (!maybe_handler.IsCleared()) {
1187 DCHECK(IC::IsHandler(maybe_handler));
1188 MaybeObjectHandle handler = config()->NewHandle(maybe_handler);
1189 if (map_handler && !(map_handler(map).ToHandle(&map))) {
1190 continue;
1191 }
1192 maps_and_handlers->emplace_back(map, handler);
1193 found++;
1194 }
1195 }
1196
1197 return found;
1198}
1199
1201 DirectHandle<Map> map) const {
1203
1204 for (FeedbackIterator it(this); !it.done(); it.Advance()) {
1205 if (it.map() == *map && !it.handler().IsCleared()) {
1206 return config()->NewHandle(it.handler());
1207 }
1208 }
1209 return MaybeObjectDirectHandle();
1210}
1211
1215 Tagged<MaybeObject> feedback = GetFeedback();
1216 if (IsPropertyNameFeedback(feedback)) {
1217 return Cast<Name>(feedback.GetHeapObjectAssumeStrong());
1218 }
1219 }
1222 if (IsPropertyNameFeedback(extra)) {
1223 return Cast<Name>(extra.GetHeapObjectAssumeStrong());
1224 }
1225 }
1226 return {};
1227}
1228
1231 // TODO(victorgomes): The KeyedAccessLoadMode::kInBounds is doing double duty
1232 // here. It shouldn't be used for property loads.
1235 }
1236 MapsAndHandlers maps_and_handlers(isolate_);
1237 ExtractMapsAndHandlers(&maps_and_handlers);
1239 for (auto [_, handler] : maps_and_handlers) {
1241 mode, LoadHandler::GetKeyedAccessLoadMode(*handler));
1242 }
1243 return mode;
1244}
1245
1246namespace {
1247
1248bool BuiltinHasKeyedAccessStoreMode(Builtin builtin) {
1249 DCHECK(Builtins::IsBuiltinId(builtin));
1250 switch (builtin) {
1251 case Builtin::kKeyedStoreIC_SloppyArguments_InBounds:
1252 case Builtin::kKeyedStoreIC_SloppyArguments_NoTransitionGrowAndHandleCOW:
1253 case Builtin::kKeyedStoreIC_SloppyArguments_NoTransitionIgnoreTypedArrayOOB:
1254 case Builtin::kKeyedStoreIC_SloppyArguments_NoTransitionHandleCOW:
1255 case Builtin::kStoreFastElementIC_InBounds:
1256 case Builtin::kStoreFastElementIC_NoTransitionGrowAndHandleCOW:
1257 case Builtin::kStoreFastElementIC_NoTransitionIgnoreTypedArrayOOB:
1258 case Builtin::kStoreFastElementIC_NoTransitionHandleCOW:
1259 case Builtin::kElementsTransitionAndStore_InBounds:
1260 case Builtin::kElementsTransitionAndStore_NoTransitionGrowAndHandleCOW:
1261 case Builtin::kElementsTransitionAndStore_NoTransitionIgnoreTypedArrayOOB:
1262 case Builtin::kElementsTransitionAndStore_NoTransitionHandleCOW:
1263 return true;
1264 default:
1265 return false;
1266 }
1267 UNREACHABLE();
1268}
1269
1270KeyedAccessStoreMode KeyedAccessStoreModeForBuiltin(Builtin builtin) {
1271 DCHECK(BuiltinHasKeyedAccessStoreMode(builtin));
1272 switch (builtin) {
1273 case Builtin::kKeyedStoreIC_SloppyArguments_InBounds:
1274 case Builtin::kStoreFastElementIC_InBounds:
1275 case Builtin::kElementsTransitionAndStore_InBounds:
1277 case Builtin::kKeyedStoreIC_SloppyArguments_NoTransitionGrowAndHandleCOW:
1278 case Builtin::kStoreFastElementIC_NoTransitionGrowAndHandleCOW:
1279 case Builtin::kElementsTransitionAndStore_NoTransitionGrowAndHandleCOW:
1281 case Builtin::kKeyedStoreIC_SloppyArguments_NoTransitionIgnoreTypedArrayOOB:
1282 case Builtin::kStoreFastElementIC_NoTransitionIgnoreTypedArrayOOB:
1283 case Builtin::kElementsTransitionAndStore_NoTransitionIgnoreTypedArrayOOB:
1285 case Builtin::kKeyedStoreIC_SloppyArguments_NoTransitionHandleCOW:
1286 case Builtin::kStoreFastElementIC_NoTransitionHandleCOW:
1287 case Builtin::kElementsTransitionAndStore_NoTransitionHandleCOW:
1289 default:
1290 UNREACHABLE();
1291 }
1292}
1293
1294} // namespace
1295
1301
1302 if (GetKeyType() == IcCheckType::kProperty) return mode;
1303
1304 MapsAndHandlers maps_and_handlers(isolate_);
1305 ExtractMapsAndHandlers(&maps_and_handlers);
1306 for (auto [_, maybe_code_handler] : maps_and_handlers) {
1307 // The first handler that isn't the slow handler will have the bits we need.
1308 Builtin builtin_handler = Builtin::kNoBuiltinId;
1309 if (IsStoreHandler(*maybe_code_handler.object())) {
1310 auto data_handler = Cast<StoreHandler>(maybe_code_handler.object());
1311
1312 if (IsSmi(data_handler->smi_handler())) {
1313 // Decode the KeyedAccessStoreMode information from the Handler.
1314 mode =
1315 StoreHandler::GetKeyedAccessStoreMode(data_handler->smi_handler());
1316 if (!StoreModeIsInBounds(mode)) return mode;
1317 continue;
1318 } else {
1319 Tagged<Code> code = Cast<Code>(data_handler->smi_handler());
1320 builtin_handler = code->builtin_id();
1321 }
1322
1323 } else if (IsSmi(*maybe_code_handler.object())) {
1324 // Skip for Proxy Handlers.
1325 if (*maybe_code_handler.object() == StoreHandler::StoreProxy()) {
1326 continue;
1327 }
1328 // Decode the KeyedAccessStoreMode information from the Handler.
1329 mode = StoreHandler::GetKeyedAccessStoreMode(*maybe_code_handler);
1330 if (!StoreModeIsInBounds(mode)) return mode;
1331 continue;
1332 } else if (IsDefineKeyedOwnICKind(kind())) {
1333 mode = StoreHandler::GetKeyedAccessStoreMode(*maybe_code_handler);
1334 if (!StoreModeIsInBounds(mode)) return mode;
1335 continue;
1336 } else {
1337 // Element store without prototype chain check.
1338 Tagged<Code> code = Cast<Code>(*maybe_code_handler.object());
1339 builtin_handler = code->builtin_id();
1340 }
1341
1342 if (Builtins::IsBuiltinId(builtin_handler)) {
1343 if (!BuiltinHasKeyedAccessStoreMode(builtin_handler)) continue;
1344
1345 mode = KeyedAccessStoreModeForBuiltin(builtin_handler);
1346 break;
1347 }
1348 }
1349
1350 return mode;
1351}
1352
1358 auto pair = GetFeedbackPair();
1359 Tagged<MaybeObject> feedback = pair.first;
1360 if (feedback == MegamorphicSentinel()) {
1361 return static_cast<IcCheckType>(Smi::ToInt(Cast<Smi>(pair.second)));
1362 }
1363 Tagged<MaybeObject> maybe_name =
1366 ? pair.second
1367 : feedback;
1370}
1371
1377
1383
1388
1391 int feedback = GetFeedback().ToSmi().value();
1392 return ForInHintFromFeedback(static_cast<ForInFeedback>(feedback));
1393}
1394
1397 Tagged<MaybeObject> feedback = GetFeedback();
1398 Tagged<HeapObject> heap_object;
1399 if (feedback.GetHeapObjectIfWeak(&heap_object)) {
1400 return config()->NewHandle(Cast<JSObject>(heap_object));
1401 }
1403}
1404
1406 : done_(false), index_(-1), state_(kOther) {
1407 DCHECK(
1408 IsLoadICKind(nexus->kind()) || IsSetNamedICKind(nexus->kind()) ||
1409 IsKeyedLoadICKind(nexus->kind()) || IsKeyedStoreICKind(nexus->kind()) ||
1410 IsDefineNamedOwnICKind(nexus->kind()) ||
1413 IsKeyedHasICKind(nexus->kind()) || IsDefineKeyedOwnICKind(nexus->kind()));
1414
1416 auto pair = nexus->GetFeedbackPair();
1417 Tagged<MaybeObject> feedback = pair.first;
1418 bool is_named_feedback = IsPropertyNameFeedback(feedback);
1419 Tagged<HeapObject> heap_object;
1420
1421 if ((feedback.GetHeapObjectIfStrong(&heap_object) &&
1422 IsWeakFixedArray(heap_object)) ||
1423 is_named_feedback) {
1424 index_ = 0;
1426 heap_object = feedback.GetHeapObjectAssumeStrong();
1427 if (is_named_feedback) {
1428 polymorphic_feedback_ = nexus->config()->NewHandle(
1429 Cast<WeakFixedArray>(pair.second.GetHeapObjectAssumeStrong()));
1430 } else {
1432 nexus->config()->NewHandle(Cast<WeakFixedArray>(heap_object));
1433 }
1435 } else if (feedback.GetHeapObjectIfWeak(&heap_object)) {
1437 Tagged<MaybeObject> handler = pair.second;
1438 map_ = Cast<Map>(heap_object);
1439 handler_ = handler;
1440 } else {
1441 done_ = true;
1442 }
1443}
1444
1446 CHECK(!done_);
1447
1448 if (state_ == kMonomorphic) {
1449 done_ = true;
1450 return;
1451 }
1452
1455}
1456
1458 CHECK(!done_);
1460 int length = polymorphic_feedback_->length();
1461 Tagged<HeapObject> heap_object;
1462
1463 while (index_ < length) {
1464 if (polymorphic_feedback_->get(index_).GetHeapObjectIfWeak(&heap_object)) {
1465 Tagged<MaybeObject> handler =
1467 map_ = Cast<Map>(heap_object);
1468 handler_ = handler;
1469 index_ += kEntrySize;
1470 return;
1471 }
1472 index_ += kEntrySize;
1473 }
1474
1475 CHECK_EQ(index_, length);
1476 done_ = true;
1477}
1478} // namespace v8::internal
int16_t parameter_count
Definition builtins.cc:67
Builtins::Kind kind
Definition builtins.cc:40
#define BUILTIN_CODE(isolate, name)
Definition builtins.h:45
static constexpr T decode(U value)
Definition bit-field.h:66
static V8_NODISCARD constexpr U update(U previous, T value)
Definition bit-field.h:61
static int index(int base_index, int item)
Definition bit-field.h:154
static U encode(U previous, int item, T value)
Definition bit-field.h:164
static T decode(U data, int item)
Definition bit-field.h:159
static V8_EXPORT_PRIVATE DirectHandle< ArrayList > Add(Isolate *isolate, DirectHandle< ArrayList > array, Tagged< Smi > obj, AllocationType allocation=AllocationType::kYoung)
static constexpr bool IsBuiltinId(Builtin builtin)
Definition builtins.h:128
static V8_EXPORT_PRIVATE DirectHandle< ClosureFeedbackCellArray > New(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared, AllocationType allocation=AllocationType::kYoung)
static void TraceEvictFromOptimizedCodeCache(Isolate *isolate, Tagged< SharedFunctionInfo > sfi, const char *reason)
void push_back(const DirectHandle< T > &x)
Definition handles.h:940
V8_INLINE bool is_identical_to(Handle< S > other) const
Definition handles.h:716
Handle< FeedbackVector > NewFeedbackVector(DirectHandle< SharedFunctionInfo > shared, DirectHandle< ClosureFeedbackCellArray > closure_feedback_cell_array, DirectHandle< FeedbackCell > parent_feedback_cell)
Definition factory.cc:453
DirectHandle< WeakFixedArray > polymorphic_feedback_
FeedbackIterator(const FeedbackNexus *nexus)
static constexpr int kHandlerOffset
Tagged< MaybeObject > handler()
int32_t slot_count(AcquireLoadTag) const
void SetCreateClosureParameterCount(int index, uint16_t parameter_count)
V8_EXPORT_PRIVATE FeedbackSlotKind GetKind(FeedbackSlot slot) const
static V8_EXPORT_PRIVATE Handle< FeedbackMetadata > New(IsolateT *isolate, const FeedbackVectorSpec *spec)
V8_EXPORT_PRIVATE uint16_t GetCreateClosureParameterCount(int index) const
void SetKind(FeedbackSlot slot, FeedbackSlotKind kind)
static const char * Kind2String(FeedbackSlotKind kind)
int32_t create_closure_slot_count(AcquireLoadTag) const
int32_t get(int index) const
void set(int index, int32_t value)
static int GetSlotSize(FeedbackSlotKind kind)
bool SpecDiffersFrom(const FeedbackVectorSpec *other_spec) const
DirectHandle< WeakFixedArray > CreateArrayOfSize(int length)
Tagged< MaybeObject > UninitializedSentinel() const
void ConfigureCloneObject(DirectHandle< Map > source_map, const MaybeObjectHandle &handler)
bool ConfigureLexicalVarMode(int script_context_index, int context_slot_index, bool immutable)
std::function< MaybeHandle< Map >(Handle< Map >)> TryUpdateHandler
void ConfigureMegaDOM(const MaybeObjectDirectHandle &handler)
CompareOperationHint GetCompareOperationFeedback() const
const NexusConfig * config() const
Tagged< FeedbackVector > vector() const
Tagged< MaybeObject > GetFeedbackExtra() const
std::pair< Tagged< MaybeObject >, Tagged< MaybeObject > > GetFeedbackPair() const
FeedbackSlotKind kind() const
KeyedAccessStoreMode GetKeyedAccessStoreMode() const
Tagged< Name > GetName() const
MaybeObjectDirectHandle FindHandlerForMap(DirectHandle< Map > map) const
MaybeDirectHandle< JSObject > GetConstructorFeedback() const
int ExtractMapsAndHandlers(MapsAndHandlers *maps_and_handlers, TryUpdateHandler map_handler=TryUpdateHandler()) const
MaybeObjectHandle ExtractMegaDOMHandler()
FeedbackSlot slot() const
bool Clear(ClearBehavior behavior)
void ConfigureHandlerMode(const MaybeObjectDirectHandle &handler)
Tagged< MaybeObject > GetFeedback() const
CallFeedbackContent GetCallFeedbackContent()
Tagged< MaybeObject > MegaDOMSentinel() const
void ConfigurePolymorphic(DirectHandle< Name > name, MapsAndHandlers const &maps_and_handlers)
void ConfigureMonomorphic(DirectHandle< Name > name, DirectHandle< Map > receiver_map, const MaybeObjectDirectHandle &handler)
MaybeObjectHandle ToHandle(Tagged< MaybeObject > value) const
FeedbackNexus(Isolate *isolate, Handle< FeedbackVector > vector, FeedbackSlot slot)
void ConfigurePropertyCellMode(DirectHandle< PropertyCell > cell)
KeyedAccessLoadMode GetKeyedAccessLoadMode() const
TypeOfFeedback::Result GetTypeOfFeedback() const
int ExtractMaps(MapHandles *maps) const
static constexpr int kCloneObjectPolymorphicEntrySize
void SetSpeculationMode(SpeculationMode mode)
InlineCacheState ic_state() const
Tagged< MaybeObject > MegamorphicSentinel() const
SpeculationMode GetSpeculationMode()
void SetFeedback(Tagged< FeedbackType > feedback, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
BinaryOperationHint GetBinaryOperationFeedback() const
Tagged< Map > GetFirstMap() const
bool IsInvalid() const
Definition utils.h:649
FeedbackSlot WithOffset(int offset) const
Definition utils.h:658
FeedbackSlotKind GetKind(FeedbackSlot slot) const
void append(FeedbackSlotKind kind)
FeedbackSlot AddSlot(FeedbackSlotKind kind)
uint16_t GetCreateClosureParameterCount(int index) const
V8_EXPORT_PRIVATE void set_tiering_state(TieringState state)
Tagged< MaybeObject > Get(FeedbackSlot slot) const
static DirectHandle< Symbol > UninitializedSentinel(Isolate *isolate)
Tagged< Code > optimized_code(IsolateForSandbox isolate) const
void set_maybe_has_turbofan_code(bool value)
static V8_EXPORT_PRIVATE Handle< FeedbackVector > NewWithOneBinarySlotForTesting(Zone *zone, Isolate *isolate)
static V8_EXPORT_PRIVATE Handle< FeedbackVector > NewForTesting(Isolate *isolate, const FeedbackVectorSpec *spec)
void set_maybe_has_optimized_osr_code(bool value, CodeKind code_kind)
void SetOptimizedOsrCode(Isolate *isolate, FeedbackSlot slot, Tagged< Code > code)
void Set(FeedbackSlot slot, Tagged< MaybeObject > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
static Tagged< Symbol > RawUninitializedSentinel(Isolate *isolate)
static V8_EXPORT_PRIVATE Handle< FeedbackVector > New(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared, DirectHandle< ClosureFeedbackCellArray > closure_feedback_cell_array, DirectHandle< FeedbackCell > parent_feedback_cell, IsCompiledScope *is_compiled_scope)
std::optional< Tagged< Code > > GetOptimizedOsrCode(Isolate *isolate, FeedbackSlot slot)
bool ClearSlots(Isolate *isolate)
static void AddToVectorsForProfilingTools(Isolate *isolate, DirectHandle< FeedbackVector > vector)
void EvictOptimizedCodeMarkedForDeoptimization(Isolate *isolate, Tagged< SharedFunctionInfo > shared, const char *reason)
void SetOptimizedCode(IsolateForSandbox isolate, Tagged< Code > code)
static V8_EXPORT_PRIVATE Handle< FeedbackVector > NewWithOneCompareSlotForTesting(Zone *zone, Isolate *isolate)
void set_osr_tiering_in_progress(bool osr_in_progress)
V8_EXPORT_PRIVATE FeedbackSlotKind GetKind(FeedbackSlot slot) const
static constexpr int OffsetOfElementAt(int index)
static constexpr int kHeaderSize
T ReadField(size_t offset) const
void WriteField(size_t offset, T value) const
static bool IsHandler(Tagged< MaybeObject > object)
Definition ic-inl.h:29
V8_NOINLINE void PushParamsAndDie(void *ptr1=nullptr, void *ptr2=nullptr, void *ptr3=nullptr, void *ptr4=nullptr, void *ptr5=nullptr, void *ptr6=nullptr)
Definition isolate.cc:699
static KeyedAccessLoadMode GetKeyedAccessLoadMode(Tagged< MaybeObject > handler)
void emplace_back(DirectHandle< Map > map, MaybeObjectDirectHandle handler)
MaybeObjectHandle NewHandle(Tagged< MaybeObject > object) const
std::pair< Tagged< MaybeObject >, Tagged< MaybeObject > > GetFeedbackPair(Tagged< FeedbackVector > vector, FeedbackSlot slot) const
void SetFeedbackPair(Tagged< FeedbackVector > vector, FeedbackSlot start_slot, Tagged< MaybeObject > feedback, WriteBarrierMode mode, Tagged< MaybeObject > feedback_extra, WriteBarrierMode mode_extra) const
static constexpr int ToInt(const Tagged< Object > object)
Definition smi.h:33
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static constexpr Tagged< Smi > From31BitPattern(int value)
Definition smi.h:52
static constexpr Tagged< Smi > zero()
Definition smi.h:99
static KeyedAccessStoreMode GetKeyedAccessStoreMode(Tagged< MaybeObject > handler)
static Handle< ClosureFeedbackCellArray > Allocate(IsolateT *isolate, int capacity, std::optional< DisallowGarbageCollection > *no_gc_out, AllocationType allocation=AllocationType::kYoung)
V8_INLINE constexpr StorageType ptr() const
Tagged< HeapObject > GetHeapObjectAssumeStrong() const
constexpr bool IsStrongOrWeak() const
constexpr bool IsCleared() const
bool GetHeapObject(Tagged< HeapObject > *result) const
Register const index_
const PropertyKind kind_
bool done_
Definition compiler.cc:3788
std::vector< T > vector_
Definition sweeper.cc:212
enum v8::internal::@1270::DeoptimizableCodeIterator::@67 state_
LineAndColumn current
Isolate * isolate
int32_t offset
#define _
std::map< const std::string, const std::string > map
ZoneVector< RpoNumber > & result
MovableLabel handler
ZoneVector< int > slots
constexpr unsigned CountPopulation(T value)
Definition bits.h:26
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
bool IsKeyedHasICKind(FeedbackSlotKind kind)
bool StoreModeIsInBounds(KeyedAccessStoreMode store_mode)
Definition globals.h:2724
constexpr bool CodeKindIsOptimizedJSFunction(CodeKind kind)
Definition code-kind.h:66
bool IsDefineNamedOwnICKind(FeedbackSlotKind kind)
@ SKIP_WRITE_BARRIER
Definition objects.h:52
@ UPDATE_WRITE_BARRIER
Definition objects.h:55
ForInHint ForInHintFromFeedback(ForInFeedback type_feedback)
ReadOnlyRoots GetReadOnlyRoots()
Definition roots-inl.h:86
CompareOperationHint CompareOperationHintFromFeedback(int type_feedback)
bool IsSetNamedICKind(FeedbackSlotKind kind)
constexpr bool CodeKindCanTierUp(CodeKind kind)
Definition code-kind.h:95
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
bool IsLoadICKind(FeedbackSlotKind kind)
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
Flag flags[]
Definition flags.cc:3797
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage report a tick only when allocated zone memory changes by this amount TracingFlags::gc_stats TracingFlags::gc_stats track native contexts that are expected to be garbage collected verify heap pointers before and after GC memory reducer runs GC with ReduceMemoryFootprint flag Maximum number of memory reducer GCs scheduled Old gen GC speed is computed directly from gc tracer counters Perform compaction on full GCs based on V8 s default heuristics Perform compaction on every full GC Perform code space compaction when finalizing a full GC with stack Stress GC compaction to flush out bugs with moving objects flush of baseline code when it has not been executed recently Use time base code flushing instead of age Use a progress bar to scan large objects in increments when incremental marking is active force incremental marking for small heaps and run it more often force marking at random points between and force scavenge at random points between and reclaim otherwise unreachable unmodified wrapper objects when possible less compaction in non memory reducing mode use high priority threads for concurrent Marking Test mode only flag It allows an unit test to select evacuation candidates use incremental marking for CppHeap cppheap_concurrent_marking c value for membalancer A special constant to balance between memory and space tradeoff The smaller the more memory it uses enable use of SSE4 instructions if available enable use of AVX VNNI instructions if available enable use of POPCNT instruction if available force all emitted branches to be in long mode(MIPS/PPC only)") DEFINE_BOOL(partial_constant_pool
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
KeyedAccessLoadMode GeneralizeKeyedAccessLoadMode(KeyedAccessLoadMode mode1, KeyedAccessLoadMode mode2)
Definition globals.h:2682
bool IsCallICKind(FeedbackSlotKind kind)
bool IsStoreInArrayLiteralICKind(FeedbackSlotKind kind)
void ShortPrint(Tagged< Object > obj, FILE *out)
Definition objects.cc:1865
constexpr AdaptArguments kDontAdapt
Definition globals.h:2776
constexpr int kInt32Size
Definition globals.h:401
Tagged< MaybeWeak< T > > MakeWeak(Tagged< T > value)
Definition tagged.h:893
Tagged< ClearedWeakValue > ClearedValue(PtrComprCageBase cage_base)
V8_EXPORT_PRIVATE FlagValues v8_flags
bool IsKeyedLoadICKind(FeedbackSlotKind kind)
bool IsDefineKeyedOwnICKind(FeedbackSlotKind kind)
constexpr int kUInt16Size
Definition globals.h:399
bool IsDefineKeyedOwnPropertyInLiteralKind(FeedbackSlotKind kind)
BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback)
static bool IsPropertyNameFeedback(Tagged< MaybeObject > feedback)
bool IsGlobalICKind(FeedbackSlotKind kind)
bool IsKeyedStoreICKind(FeedbackSlotKind kind)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
static constexpr ReleaseStoreTag kReleaseStore
Definition globals.h:2910
static constexpr RelaxedLoadTag kRelaxedLoad
Definition globals.h:2909
static constexpr AcquireLoadTag kAcquireLoad
Definition globals.h:2908
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define CHECK_GT(lhs, rhs)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define V8_LIKELY(condition)
Definition v8config.h:661
#define V8_UNLIKELY(condition)
Definition v8config.h:660