5 #include "src/feedback-vector.h" 6 #include "src/code-stubs.h" 7 #include "src/feedback-vector-inl.h" 8 #include "src/ic/ic-inl.h" 9 #include "src/objects.h" 10 #include "src/objects/data-handler-inl.h" 11 #include "src/objects/hash-table-inl.h" 12 #include "src/objects/map-inl.h" 13 #include "src/objects/object-macros.h" 18 FeedbackSlot FeedbackVectorSpec::AddSlot(FeedbackSlotKind kind) {
20 int entries_per_slot = FeedbackMetadata::GetSlotSize(kind);
22 for (
int i = 1;
i < entries_per_slot;
i++) {
23 append(FeedbackSlotKind::kInvalid);
25 return FeedbackSlot(slot);
28 FeedbackSlot FeedbackVectorSpec::AddTypeProfileSlot() {
29 FeedbackSlot slot = AddSlot(FeedbackSlotKind::kTypeProfile);
30 CHECK_EQ(FeedbackVectorSpec::kTypeProfileSlotIndex,
31 FeedbackVector::GetIndex(slot));
35 bool FeedbackVectorSpec::HasTypeProfileSlot()
const {
37 FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
38 if (slots() <= slot.ToInt()) {
41 return GetKind(slot) == FeedbackSlotKind::kTypeProfile;
44 static bool IsPropertyNameFeedback(MaybeObject feedback) {
45 HeapObject* heap_object;
46 if (!feedback->GetHeapObjectIfStrong(&heap_object))
return false;
47 if (heap_object->IsString())
return true;
48 if (!heap_object->IsSymbol())
return false;
49 Symbol symbol = Symbol::cast(heap_object);
50 ReadOnlyRoots roots = symbol->GetReadOnlyRoots();
51 return symbol != roots.uninitialized_symbol() &&
52 symbol != roots.premonomorphic_symbol() &&
53 symbol != roots.megamorphic_symbol();
56 std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind) {
57 return os << FeedbackMetadata::Kind2String(kind);
60 FeedbackSlotKind FeedbackMetadata::GetKind(FeedbackSlot slot)
const {
61 int index = VectorICComputer::index(0, slot.ToInt());
62 int data =
get(index);
63 return VectorICComputer::decode(data, slot.ToInt());
66 void FeedbackMetadata::SetKind(FeedbackSlot slot, FeedbackSlotKind kind) {
67 int index = VectorICComputer::index(0, slot.ToInt());
68 int data =
get(index);
69 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
74 Handle<FeedbackMetadata> FeedbackMetadata::New(Isolate* isolate,
75 const FeedbackVectorSpec* spec) {
76 Factory* factory = isolate->factory();
78 const int slot_count = spec ==
nullptr ? 0 : spec->slots();
79 if (slot_count == 0) {
80 return factory->empty_feedback_metadata();
83 for (
int i = 0;
i < slot_count;) {
85 FeedbackSlotKind kind = spec->GetKind(FeedbackSlot(
i));
86 int entry_size = FeedbackMetadata::GetSlotSize(kind);
87 for (
int j = 1; j < entry_size; j++) {
88 FeedbackSlotKind kind = spec->GetKind(FeedbackSlot(
i + j));
89 DCHECK_EQ(FeedbackSlotKind::kInvalid, kind);
95 Handle<FeedbackMetadata> metadata = factory->NewFeedbackMetadata(slot_count);
99 for (
int i = 0;
i < slot_count;
i++) {
101 FeedbackSlot slot(
i);
102 FeedbackSlotKind kind = spec->GetKind(slot);
103 metadata->SetKind(slot, kind);
109 bool FeedbackMetadata::SpecDiffersFrom(
110 const FeedbackVectorSpec* other_spec)
const {
111 if (other_spec->slots() != slot_count()) {
115 int slots = slot_count();
116 for (
int i = 0;
i < slots;) {
117 FeedbackSlot slot(
i);
118 FeedbackSlotKind kind = GetKind(slot);
119 int entry_size = FeedbackMetadata::GetSlotSize(kind);
121 if (kind != other_spec->GetKind(slot)) {
129 const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
131 case FeedbackSlotKind::kInvalid:
133 case FeedbackSlotKind::kCall:
135 case FeedbackSlotKind::kLoadProperty:
136 return "LoadProperty";
137 case FeedbackSlotKind::kLoadGlobalInsideTypeof:
138 return "LoadGlobalInsideTypeof";
139 case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
140 return "LoadGlobalNotInsideTypeof";
141 case FeedbackSlotKind::kLoadKeyed:
143 case FeedbackSlotKind::kStoreNamedSloppy:
144 return "StoreNamedSloppy";
145 case FeedbackSlotKind::kStoreNamedStrict:
146 return "StoreNamedStrict";
147 case FeedbackSlotKind::kStoreOwnNamed:
148 return "StoreOwnNamed";
149 case FeedbackSlotKind::kStoreGlobalSloppy:
150 return "StoreGlobalSloppy";
151 case FeedbackSlotKind::kStoreGlobalStrict:
152 return "StoreGlobalStrict";
153 case FeedbackSlotKind::kStoreKeyedSloppy:
154 return "StoreKeyedSloppy";
155 case FeedbackSlotKind::kStoreKeyedStrict:
156 return "StoreKeyedStrict";
157 case FeedbackSlotKind::kStoreInArrayLiteral:
158 return "StoreInArrayLiteral";
159 case FeedbackSlotKind::kBinaryOp:
161 case FeedbackSlotKind::kCompareOp:
163 case FeedbackSlotKind::kStoreDataPropertyInLiteral:
164 return "StoreDataPropertyInLiteral";
165 case FeedbackSlotKind::kCreateClosure:
166 return "kCreateClosure";
167 case FeedbackSlotKind::kLiteral:
169 case FeedbackSlotKind::kTypeProfile:
170 return "TypeProfile";
171 case FeedbackSlotKind::kForIn:
173 case FeedbackSlotKind::kInstanceOf:
175 case FeedbackSlotKind::kCloneObject:
176 return "CloneObject";
177 case FeedbackSlotKind::kKindsNumber:
183 bool FeedbackMetadata::HasTypeProfileSlot()
const {
185 FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
186 return slot.ToInt() < slot_count() &&
187 GetKind(slot) == FeedbackSlotKind::kTypeProfile;
190 FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot)
const {
192 return metadata()->GetKind(slot);
195 FeedbackSlot FeedbackVector::GetTypeProfileSlot()
const {
196 DCHECK(metadata()->HasTypeProfileSlot());
198 FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
199 DCHECK_EQ(FeedbackSlotKind::kTypeProfile, GetKind(slot));
204 Handle<FeedbackVector> FeedbackVector::New(Isolate* isolate,
205 Handle<SharedFunctionInfo> shared) {
206 Factory* factory = isolate->factory();
208 const int slot_count = shared->feedback_metadata()->slot_count();
210 Handle<FeedbackVector> vector = factory->NewFeedbackVector(shared, TENURED);
212 DCHECK_EQ(vector->length(), slot_count);
214 DCHECK_EQ(vector->shared_function_info(), *shared);
216 vector->optimized_code_weak_or_smi(),
217 MaybeObject::FromSmi(Smi::FromEnum(
218 FLAG_log_function_events ? OptimizationMarker::kLogFirstExecution
219 : OptimizationMarker::kNone)));
220 DCHECK_EQ(vector->invocation_count(), 0);
221 DCHECK_EQ(vector->profiler_ticks(), 0);
222 DCHECK_EQ(vector->deopt_count(), 0);
225 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
226 DCHECK_EQ(ReadOnlyRoots(isolate).uninitialized_symbol(),
227 *uninitialized_sentinel);
228 Handle<Oddball> undefined_value = factory->undefined_value();
229 for (
int i = 0;
i < slot_count;) {
230 FeedbackSlot slot(
i);
231 FeedbackSlotKind kind = shared->feedback_metadata()->GetKind(slot);
232 int index = FeedbackVector::GetIndex(slot);
233 int entry_size = FeedbackMetadata::GetSlotSize(kind);
235 Object* extra_value = *uninitialized_sentinel;
237 case FeedbackSlotKind::kLoadGlobalInsideTypeof:
238 case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
239 case FeedbackSlotKind::kStoreGlobalSloppy:
240 case FeedbackSlotKind::kStoreGlobalStrict:
241 vector->set(index, HeapObjectReference::ClearedValue(isolate),
244 case FeedbackSlotKind::kForIn:
245 case FeedbackSlotKind::kCompareOp:
246 case FeedbackSlotKind::kBinaryOp:
247 vector->set(index, Smi::kZero, SKIP_WRITE_BARRIER);
249 case FeedbackSlotKind::kCreateClosure: {
250 Handle<FeedbackCell> cell = factory->NewNoClosuresCell(undefined_value);
251 vector->set(index, *cell);
254 case FeedbackSlotKind::kLiteral:
255 vector->set(index, Smi::kZero, SKIP_WRITE_BARRIER);
257 case FeedbackSlotKind::kCall:
258 vector->set(index, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
259 extra_value = Smi::kZero;
261 case FeedbackSlotKind::kCloneObject:
262 case FeedbackSlotKind::kLoadProperty:
263 case FeedbackSlotKind::kLoadKeyed:
264 case FeedbackSlotKind::kStoreNamedSloppy:
265 case FeedbackSlotKind::kStoreNamedStrict:
266 case FeedbackSlotKind::kStoreOwnNamed:
267 case FeedbackSlotKind::kStoreKeyedSloppy:
268 case FeedbackSlotKind::kStoreKeyedStrict:
269 case FeedbackSlotKind::kStoreInArrayLiteral:
270 case FeedbackSlotKind::kStoreDataPropertyInLiteral:
271 case FeedbackSlotKind::kTypeProfile:
272 case FeedbackSlotKind::kInstanceOf:
273 vector->set(index, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
276 case FeedbackSlotKind::kInvalid:
277 case FeedbackSlotKind::kKindsNumber:
281 for (
int j = 1; j < entry_size; j++) {
282 vector->set(index + j, extra_value, SKIP_WRITE_BARRIER);
287 Handle<FeedbackVector> result = Handle<FeedbackVector>::cast(vector);
288 if (!isolate->is_best_effort_code_coverage() ||
289 isolate->is_collecting_type_profile()) {
290 AddToVectorsForProfilingTools(isolate, result);
296 void FeedbackVector::AddToVectorsForProfilingTools(
297 Isolate* isolate, Handle<FeedbackVector> vector) {
298 DCHECK(!isolate->is_best_effort_code_coverage() ||
299 isolate->is_collecting_type_profile());
300 if (!vector->shared_function_info()->IsSubjectToDebugging())
return;
301 Handle<ArrayList> list = Handle<ArrayList>::cast(
302 isolate->factory()->feedback_vectors_for_profiling_tools());
303 list = ArrayList::Add(isolate, list, vector);
304 isolate->SetFeedbackVectorsForProfilingTools(*list);
308 void FeedbackVector::SetOptimizedCode(Handle<FeedbackVector> vector,
310 DCHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
311 vector->set_optimized_code_weak_or_smi(HeapObjectReference::Weak(*code));
314 void FeedbackVector::ClearOptimizedCode() {
315 DCHECK(has_optimized_code());
316 SetOptimizationMarker(OptimizationMarker::kNone);
319 void FeedbackVector::ClearOptimizationMarker() {
320 DCHECK(!has_optimized_code());
321 SetOptimizationMarker(OptimizationMarker::kNone);
324 void FeedbackVector::SetOptimizationMarker(OptimizationMarker marker) {
325 set_optimized_code_weak_or_smi(MaybeObject::FromSmi(Smi::FromEnum(marker)));
328 void FeedbackVector::EvictOptimizedCodeMarkedForDeoptimization(
329 SharedFunctionInfo* shared,
const char* reason) {
330 MaybeObject slot = optimized_code_weak_or_smi();
335 if (slot->IsCleared()) {
336 ClearOptimizationMarker();
340 Code code = Code::cast(slot->GetHeapObject());
341 if (code->marked_for_deoptimization()) {
342 if (FLAG_trace_deopt) {
343 PrintF(
"[evicting optimizing code marked for deoptimization (%s) for ",
345 shared->ShortPrint();
348 if (!code->deopt_already_counted()) {
349 increment_deopt_count();
350 code->set_deopt_already_counted(
true);
352 ClearOptimizedCode();
356 bool FeedbackVector::ClearSlots(Isolate* isolate) {
357 MaybeObject uninitialized_sentinel = MaybeObject::FromObject(
358 FeedbackVector::RawUninitializedSentinel(isolate));
360 bool feedback_updated =
false;
361 FeedbackMetadataIterator iter(metadata());
362 while (iter.HasNext()) {
363 FeedbackSlot slot = iter.Next();
365 MaybeObject obj = Get(slot);
366 if (obj != uninitialized_sentinel) {
367 FeedbackNexus nexus(
this, slot);
368 feedback_updated |= nexus.Clear();
371 return feedback_updated;
374 void FeedbackVector::AssertNoLegacyTypes(MaybeObject
object) {
376 HeapObject* heap_object;
377 if (object->GetHeapObject(&heap_object)) {
380 DCHECK_IMPLIES(heap_object->IsFixedArray(), heap_object->IsHashTable());
385 Handle<WeakFixedArray> FeedbackNexus::EnsureArrayOfSize(
int length) {
386 Isolate* isolate = GetIsolate();
387 HeapObject* heap_object;
388 if (GetFeedback()->GetHeapObjectIfStrong(&heap_object) &&
389 heap_object->IsWeakFixedArray() &&
390 WeakFixedArray::cast(heap_object)->length() == length) {
391 return handle(WeakFixedArray::cast(heap_object), isolate);
393 Handle<WeakFixedArray> array = isolate->factory()->NewWeakFixedArray(length);
398 Handle<WeakFixedArray> FeedbackNexus::EnsureExtraArrayOfSize(
int length) {
399 Isolate* isolate = GetIsolate();
400 HeapObject* heap_object;
401 if (GetFeedbackExtra()->GetHeapObjectIfStrong(&heap_object) &&
402 heap_object->IsWeakFixedArray() &&
403 WeakFixedArray::cast(heap_object)->length() == length) {
404 return handle(WeakFixedArray::cast(heap_object), isolate);
406 Handle<WeakFixedArray> array = isolate->factory()->NewWeakFixedArray(length);
407 SetFeedbackExtra(*array);
411 void FeedbackNexus::ConfigureUninitialized() {
412 Isolate* isolate = GetIsolate();
414 case FeedbackSlotKind::kStoreGlobalSloppy:
415 case FeedbackSlotKind::kStoreGlobalStrict:
416 case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
417 case FeedbackSlotKind::kLoadGlobalInsideTypeof: {
418 SetFeedback(HeapObjectReference::ClearedValue(isolate),
420 SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
424 case FeedbackSlotKind::kCloneObject:
425 case FeedbackSlotKind::kCall: {
426 SetFeedback(*FeedbackVector::UninitializedSentinel(isolate),
428 SetFeedbackExtra(Smi::kZero, SKIP_WRITE_BARRIER);
431 case FeedbackSlotKind::kInstanceOf: {
432 SetFeedback(*FeedbackVector::UninitializedSentinel(isolate),
436 case FeedbackSlotKind::kStoreNamedSloppy:
437 case FeedbackSlotKind::kStoreNamedStrict:
438 case FeedbackSlotKind::kStoreKeyedSloppy:
439 case FeedbackSlotKind::kStoreKeyedStrict:
440 case FeedbackSlotKind::kStoreInArrayLiteral:
441 case FeedbackSlotKind::kStoreOwnNamed:
442 case FeedbackSlotKind::kLoadProperty:
443 case FeedbackSlotKind::kLoadKeyed:
444 case FeedbackSlotKind::kStoreDataPropertyInLiteral: {
445 SetFeedback(*FeedbackVector::UninitializedSentinel(isolate),
447 SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
456 bool FeedbackNexus::Clear() {
457 bool feedback_updated =
false;
460 case FeedbackSlotKind::kCreateClosure:
461 case FeedbackSlotKind::kTypeProfile:
465 case FeedbackSlotKind::kCompareOp:
466 case FeedbackSlotKind::kForIn:
467 case FeedbackSlotKind::kBinaryOp:
471 case FeedbackSlotKind::kLiteral:
472 SetFeedback(Smi::kZero, SKIP_WRITE_BARRIER);
473 feedback_updated =
true;
476 case FeedbackSlotKind::kStoreNamedSloppy:
477 case FeedbackSlotKind::kStoreNamedStrict:
478 case FeedbackSlotKind::kStoreKeyedSloppy:
479 case FeedbackSlotKind::kStoreKeyedStrict:
480 case FeedbackSlotKind::kStoreInArrayLiteral:
481 case FeedbackSlotKind::kStoreOwnNamed:
482 case FeedbackSlotKind::kLoadProperty:
483 case FeedbackSlotKind::kLoadKeyed:
484 case FeedbackSlotKind::kStoreGlobalSloppy:
485 case FeedbackSlotKind::kStoreGlobalStrict:
486 case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
487 case FeedbackSlotKind::kLoadGlobalInsideTypeof:
488 case FeedbackSlotKind::kCall:
489 case FeedbackSlotKind::kInstanceOf:
490 case FeedbackSlotKind::kStoreDataPropertyInLiteral:
491 case FeedbackSlotKind::kCloneObject:
493 ConfigureUninitialized();
494 feedback_updated =
true;
498 case FeedbackSlotKind::kInvalid:
499 case FeedbackSlotKind::kKindsNumber:
503 return feedback_updated;
506 void FeedbackNexus::ConfigurePremonomorphic(Handle<Map> receiver_map) {
507 SetFeedback(*FeedbackVector::PremonomorphicSentinel(GetIsolate()),
509 SetFeedbackExtra(HeapObjectReference::Weak(*receiver_map));
512 bool FeedbackNexus::ConfigureMegamorphic() {
513 DisallowHeapAllocation no_gc;
514 Isolate* isolate = GetIsolate();
515 MaybeObject sentinel =
516 MaybeObject::FromObject(*FeedbackVector::MegamorphicSentinel(isolate));
517 if (GetFeedback() != sentinel) {
518 SetFeedback(sentinel, SKIP_WRITE_BARRIER);
519 SetFeedbackExtra(HeapObjectReference::ClearedValue(isolate));
526 bool FeedbackNexus::ConfigureMegamorphic(IcCheckType property_type) {
527 DisallowHeapAllocation no_gc;
528 Isolate* isolate = GetIsolate();
529 bool changed =
false;
530 MaybeObject sentinel =
531 MaybeObject::FromObject(*FeedbackVector::MegamorphicSentinel(isolate));
532 if (GetFeedback() != sentinel) {
533 SetFeedback(sentinel, SKIP_WRITE_BARRIER);
537 Smi extra = Smi::FromInt(static_cast<int>(property_type));
538 if (changed || GetFeedbackExtra() != MaybeObject::FromSmi(extra)) {
539 SetFeedbackExtra(extra, SKIP_WRITE_BARRIER);
545 Map FeedbackNexus::FindFirstMap()
const {
548 if (maps.size() > 0)
return *maps.at(0);
552 InlineCacheState FeedbackNexus::StateFromFeedback()
const {
553 Isolate* isolate = GetIsolate();
554 MaybeObject feedback = GetFeedback();
557 case FeedbackSlotKind::kCreateClosure:
560 case FeedbackSlotKind::kLiteral:
561 if (feedback->IsSmi())
return UNINITIALIZED;
564 case FeedbackSlotKind::kStoreGlobalSloppy:
565 case FeedbackSlotKind::kStoreGlobalStrict:
566 case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
567 case FeedbackSlotKind::kLoadGlobalInsideTypeof: {
568 if (feedback->IsSmi())
return MONOMORPHIC;
570 DCHECK(feedback->IsWeakOrCleared());
571 MaybeObject extra = GetFeedbackExtra();
572 if (!feedback->IsCleared() ||
573 extra != MaybeObject::FromObject(
574 *FeedbackVector::UninitializedSentinel(isolate))) {
577 return UNINITIALIZED;
580 case FeedbackSlotKind::kStoreNamedSloppy:
581 case FeedbackSlotKind::kStoreNamedStrict:
582 case FeedbackSlotKind::kStoreKeyedSloppy:
583 case FeedbackSlotKind::kStoreKeyedStrict:
584 case FeedbackSlotKind::kStoreInArrayLiteral:
585 case FeedbackSlotKind::kStoreOwnNamed:
586 case FeedbackSlotKind::kLoadProperty:
587 case FeedbackSlotKind::kLoadKeyed: {
588 if (feedback == MaybeObject::FromObject(
589 *FeedbackVector::UninitializedSentinel(isolate))) {
590 return UNINITIALIZED;
592 if (feedback == MaybeObject::FromObject(
593 *FeedbackVector::MegamorphicSentinel(isolate))) {
596 if (feedback == MaybeObject::FromObject(
597 *FeedbackVector::PremonomorphicSentinel(isolate))) {
598 return PREMONOMORPHIC;
600 if (feedback->IsWeakOrCleared()) {
604 HeapObject* heap_object;
605 if (feedback->GetHeapObjectIfStrong(&heap_object)) {
606 if (heap_object->IsWeakFixedArray()) {
611 if (heap_object->IsName()) {
612 DCHECK(IsKeyedLoadICKind(kind()) || IsKeyedStoreICKind(kind()));
613 Object* extra = GetFeedbackExtra()->GetHeapObjectAssumeStrong();
614 WeakFixedArray* extra_array = WeakFixedArray::cast(extra);
615 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
620 case FeedbackSlotKind::kCall: {
621 HeapObject* heap_object;
622 if (feedback == MaybeObject::FromObject(
623 *FeedbackVector::MegamorphicSentinel(isolate))) {
625 }
else if (feedback->IsWeakOrCleared() ||
626 (feedback->GetHeapObjectIfStrong(&heap_object) &&
627 heap_object->IsAllocationSite())) {
631 CHECK_EQ(feedback, MaybeObject::FromObject(
632 *FeedbackVector::UninitializedSentinel(isolate)));
633 return UNINITIALIZED;
635 case FeedbackSlotKind::kBinaryOp: {
636 BinaryOperationHint hint = GetBinaryOperationFeedback();
637 if (hint == BinaryOperationHint::kNone) {
638 return UNINITIALIZED;
639 }
else if (hint == BinaryOperationHint::kAny) {
645 case FeedbackSlotKind::kCompareOp: {
646 CompareOperationHint hint = GetCompareOperationFeedback();
647 if (hint == CompareOperationHint::kNone) {
648 return UNINITIALIZED;
649 }
else if (hint == CompareOperationHint::kAny) {
655 case FeedbackSlotKind::kForIn: {
656 ForInHint hint = GetForInFeedback();
657 if (hint == ForInHint::kNone) {
658 return UNINITIALIZED;
659 }
else if (hint == ForInHint::kAny) {
664 case FeedbackSlotKind::kInstanceOf: {
665 if (feedback == MaybeObject::FromObject(
666 *FeedbackVector::UninitializedSentinel(isolate))) {
667 return UNINITIALIZED;
668 }
else if (feedback ==
669 MaybeObject::FromObject(
670 *FeedbackVector::MegamorphicSentinel(isolate))) {
675 case FeedbackSlotKind::kStoreDataPropertyInLiteral: {
676 if (feedback == MaybeObject::FromObject(
677 *FeedbackVector::UninitializedSentinel(isolate))) {
678 return UNINITIALIZED;
679 }
else if (feedback->IsWeakOrCleared()) {
686 case FeedbackSlotKind::kTypeProfile: {
687 if (feedback == MaybeObject::FromObject(
688 *FeedbackVector::UninitializedSentinel(isolate))) {
689 return UNINITIALIZED;
694 case FeedbackSlotKind::kCloneObject: {
695 if (feedback == MaybeObject::FromObject(
696 *FeedbackVector::UninitializedSentinel(isolate))) {
697 return UNINITIALIZED;
699 if (feedback == MaybeObject::FromObject(
700 *FeedbackVector::MegamorphicSentinel(isolate))) {
703 if (feedback->IsWeakOrCleared()) {
707 DCHECK(feedback->GetHeapObjectAssumeStrong()->IsWeakFixedArray());
711 case FeedbackSlotKind::kInvalid:
712 case FeedbackSlotKind::kKindsNumber:
716 return UNINITIALIZED;
719 void FeedbackNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
720 DCHECK(IsGlobalICKind(kind()));
721 Isolate* isolate = GetIsolate();
722 SetFeedback(HeapObjectReference::Weak(*cell));
723 SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
727 bool FeedbackNexus::ConfigureLexicalVarMode(
int script_context_index,
728 int context_slot_index) {
729 DCHECK(IsGlobalICKind(kind()));
730 DCHECK_LE(0, script_context_index);
731 DCHECK_LE(0, context_slot_index);
732 if (!ContextIndexBits::is_valid(script_context_index) ||
733 !SlotIndexBits::is_valid(context_slot_index)) {
736 int config = ContextIndexBits::encode(script_context_index) |
737 SlotIndexBits::encode(context_slot_index);
739 SetFeedback(Smi::FromInt(config));
740 Isolate* isolate = GetIsolate();
741 SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
746 void FeedbackNexus::ConfigureHandlerMode(
const MaybeObjectHandle& handler) {
747 DCHECK(IsGlobalICKind(kind()));
748 DCHECK(IC::IsHandler(*handler));
749 SetFeedback(HeapObjectReference::ClearedValue(GetIsolate()));
750 SetFeedbackExtra(*handler);
753 void FeedbackNexus::ConfigureCloneObject(Handle<Map> source_map,
754 Handle<Map> result_map) {
755 Isolate* isolate = GetIsolate();
756 MaybeObject maybe_feedback = GetFeedback();
757 Handle<HeapObject> feedback(maybe_feedback->IsStrongOrWeak()
758 ? maybe_feedback->GetHeapObject()
761 switch (ic_state()) {
764 SetFeedback(HeapObjectReference::Weak(*source_map));
765 SetFeedbackExtra(*result_map);
768 if (maybe_feedback->IsCleared() || feedback.is_identical_to(source_map) ||
769 Map::cast(*feedback)->is_deprecated()) {
771 SetFeedback(HeapObjectReference::Weak(*source_map));
772 SetFeedbackExtra(*result_map);
775 Handle<WeakFixedArray> array =
776 EnsureArrayOfSize(2 * kCloneObjectPolymorphicEntrySize);
777 array->Set(0, maybe_feedback);
778 array->Set(1, GetFeedbackExtra());
779 array->Set(2, HeapObjectReference::Weak(*source_map));
780 array->Set(3, MaybeObject::FromObject(*result_map));
781 SetFeedbackExtra(HeapObjectReference::ClearedValue(isolate));
785 static constexpr
int kMaxElements =
786 IC::kMaxPolymorphicMapCount * kCloneObjectPolymorphicEntrySize;
787 Handle<WeakFixedArray> array = Handle<WeakFixedArray>::cast(feedback);
789 for (;
i < array->length();
i += kCloneObjectPolymorphicEntrySize) {
790 MaybeObject feedback = array->Get(
i);
791 if (feedback->IsCleared())
break;
792 Handle<Map> cached_map(Map::cast(feedback->GetHeapObject()), isolate);
793 if (cached_map.is_identical_to(source_map) ||
794 cached_map->is_deprecated())
798 if (
i >= array->length()) {
799 if (
i == kMaxElements) {
801 MaybeObject sentinel = MaybeObject::FromObject(
802 *FeedbackVector::MegamorphicSentinel(isolate));
803 SetFeedback(sentinel, SKIP_WRITE_BARRIER);
804 SetFeedbackExtra(HeapObjectReference::ClearedValue(isolate));
809 Handle<WeakFixedArray> new_array = EnsureArrayOfSize(
810 array->length() + kCloneObjectPolymorphicEntrySize);
811 for (
int j = 0; j < array->length(); ++j) {
812 new_array->Set(j, array->Get(j));
817 array->Set(
i, HeapObjectReference::Weak(*source_map));
818 array->Set(
i + 1, MaybeObject::FromObject(*result_map));
827 int FeedbackNexus::GetCallCount() {
828 DCHECK(IsCallICKind(kind()));
830 Object* call_count = GetFeedbackExtra()->cast<Object>();
831 CHECK(call_count->IsSmi());
833 return CallCountField::decode(value);
836 void FeedbackNexus::SetSpeculationMode(SpeculationMode mode) {
837 DCHECK(IsCallICKind(kind()));
839 Object* call_count = GetFeedbackExtra()->cast<Object>();
840 CHECK(call_count->IsSmi());
842 uint32_t value = CallCountField::encode(CallCountField::decode(count));
843 int result =
static_cast<int>(value | SpeculationModeField::encode(mode));
844 SetFeedbackExtra(Smi::FromInt(result), SKIP_WRITE_BARRIER);
847 SpeculationMode FeedbackNexus::GetSpeculationMode() {
848 DCHECK(IsCallICKind(kind()));
850 Object* call_count = GetFeedbackExtra()->cast<Object>();
851 CHECK(call_count->IsSmi());
853 return SpeculationModeField::decode(value);
856 float FeedbackNexus::ComputeCallFrequency() {
857 DCHECK(IsCallICKind(kind()));
859 double const invocation_count = vector()->invocation_count();
860 double const call_count = GetCallCount();
861 if (invocation_count == 0) {
865 return static_cast<float>(call_count / invocation_count);
868 void FeedbackNexus::ConfigureMonomorphic(Handle<Name> name,
869 Handle<Map> receiver_map,
870 const MaybeObjectHandle& handler) {
871 DCHECK(handler.is_null() || IC::IsHandler(*handler));
872 if (kind() == FeedbackSlotKind::kStoreDataPropertyInLiteral) {
873 SetFeedback(HeapObjectReference::Weak(*receiver_map));
874 SetFeedbackExtra(*name);
876 if (name.is_null()) {
877 SetFeedback(HeapObjectReference::Weak(*receiver_map));
878 SetFeedbackExtra(*handler);
880 Handle<WeakFixedArray> array = EnsureExtraArrayOfSize(2);
882 array->Set(0, HeapObjectReference::Weak(*receiver_map));
883 array->Set(1, *handler);
888 void FeedbackNexus::ConfigurePolymorphic(Handle<Name> name,
889 MapHandles
const& maps,
890 MaybeObjectHandles* handlers) {
891 DCHECK_EQ(handlers->size(), maps.size());
892 int receiver_count =
static_cast<int>(maps.size());
893 DCHECK_GT(receiver_count, 1);
894 Handle<WeakFixedArray> array;
895 if (name.is_null()) {
896 array = EnsureArrayOfSize(receiver_count * 2);
897 SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(GetIsolate()),
900 array = EnsureExtraArrayOfSize(receiver_count * 2);
904 for (
int current = 0; current < receiver_count; ++current) {
905 Handle<Map> map = maps[current];
906 array->Set(current * 2, HeapObjectReference::Weak(*map));
907 DCHECK(IC::IsHandler(*handlers->at(current)));
908 array->Set(current * 2 + 1, *handlers->at(current));
912 int FeedbackNexus::ExtractMaps(MapHandles* maps)
const {
913 DCHECK(IsLoadICKind(kind()) || IsStoreICKind(kind()) ||
914 IsKeyedLoadICKind(kind()) || IsKeyedStoreICKind(kind()) ||
915 IsStoreOwnICKind(kind()) || IsStoreDataPropertyInLiteralKind(kind()) ||
916 IsStoreInArrayLiteralICKind(kind()));
918 Isolate* isolate = GetIsolate();
919 MaybeObject feedback = GetFeedback();
920 bool is_named_feedback = IsPropertyNameFeedback(feedback);
921 HeapObject* heap_object;
922 if ((feedback->GetHeapObjectIfStrong(&heap_object) &&
923 heap_object->IsWeakFixedArray()) ||
926 WeakFixedArray* array;
927 if (is_named_feedback) {
929 WeakFixedArray::cast(GetFeedbackExtra()->GetHeapObjectAssumeStrong());
931 array = WeakFixedArray::cast(heap_object);
933 const int increment = 2;
934 HeapObject* heap_object;
935 for (
int i = 0;
i < array->length();
i += increment) {
936 DCHECK(array->Get(
i)->IsWeakOrCleared());
937 if (array->Get(
i)->GetHeapObjectIfWeak(&heap_object)) {
938 Map map = Map::cast(heap_object);
939 maps->push_back(handle(map, isolate));
944 }
else if (feedback->GetHeapObjectIfWeak(&heap_object)) {
945 Map map = Map::cast(heap_object);
946 maps->push_back(handle(map, isolate));
948 }
else if (feedback->GetHeapObjectIfStrong(&heap_object) &&
950 heap_object->GetReadOnlyRoots().premonomorphic_symbol()) {
951 if (GetFeedbackExtra()->GetHeapObjectIfWeak(&heap_object)) {
952 Map map = Map::cast(heap_object);
953 maps->push_back(handle(map, isolate));
961 MaybeObjectHandle FeedbackNexus::FindHandlerForMap(Handle<Map> map)
const {
962 DCHECK(IsLoadICKind(kind()) || IsStoreICKind(kind()) ||
963 IsKeyedLoadICKind(kind()) || IsKeyedStoreICKind(kind()) ||
964 IsStoreOwnICKind(kind()) || IsStoreDataPropertyInLiteralKind(kind()));
966 MaybeObject feedback = GetFeedback();
967 Isolate* isolate = GetIsolate();
968 bool is_named_feedback = IsPropertyNameFeedback(feedback);
969 HeapObject* heap_object;
970 if ((feedback->GetHeapObjectIfStrong(&heap_object) &&
971 heap_object->IsWeakFixedArray()) ||
973 WeakFixedArray* array;
974 if (is_named_feedback) {
976 WeakFixedArray::cast(GetFeedbackExtra()->GetHeapObjectAssumeStrong());
978 array = WeakFixedArray::cast(heap_object);
980 const int increment = 2;
981 HeapObject* heap_object;
982 for (
int i = 0;
i < array->length();
i += increment) {
983 DCHECK(array->Get(
i)->IsWeakOrCleared());
984 if (array->Get(
i)->GetHeapObjectIfWeak(&heap_object)) {
985 Map array_map = Map::cast(heap_object);
986 if (array_map == *map && !array->Get(
i + increment - 1)->IsCleared()) {
987 MaybeObject handler = array->Get(
i + increment - 1);
988 DCHECK(IC::IsHandler(handler));
989 return handle(handler, isolate);
993 }
else if (feedback->GetHeapObjectIfWeak(&heap_object)) {
994 Map cell_map = Map::cast(heap_object);
995 if (cell_map == *map && !GetFeedbackExtra()->IsCleared()) {
996 MaybeObject handler = GetFeedbackExtra();
997 DCHECK(IC::IsHandler(handler));
998 return handle(handler, isolate);
1002 return MaybeObjectHandle();
1005 bool FeedbackNexus::FindHandlers(MaybeObjectHandles* code_list,
1007 DCHECK(IsLoadICKind(kind()) || IsStoreICKind(kind()) ||
1008 IsKeyedLoadICKind(kind()) || IsKeyedStoreICKind(kind()) ||
1009 IsStoreOwnICKind(kind()) || IsStoreDataPropertyInLiteralKind(kind()) ||
1010 IsStoreInArrayLiteralICKind(kind()));
1012 MaybeObject feedback = GetFeedback();
1013 Isolate* isolate = GetIsolate();
1015 bool is_named_feedback = IsPropertyNameFeedback(feedback);
1016 HeapObject* heap_object;
1017 if ((feedback->GetHeapObjectIfStrong(&heap_object) &&
1018 heap_object->IsWeakFixedArray()) ||
1019 is_named_feedback) {
1020 WeakFixedArray* array;
1021 if (is_named_feedback) {
1023 WeakFixedArray::cast(GetFeedbackExtra()->GetHeapObjectAssumeStrong());
1025 array = WeakFixedArray::cast(heap_object);
1027 const int increment = 2;
1028 HeapObject* heap_object;
1029 for (
int i = 0;
i < array->length();
i += increment) {
1031 DCHECK(array->Get(
i)->IsWeakOrCleared());
1032 if (array->Get(
i)->GetHeapObjectIfWeak(&heap_object) &&
1033 !array->Get(
i + increment - 1)->IsCleared()) {
1034 MaybeObject handler = array->Get(
i + increment - 1);
1035 DCHECK(IC::IsHandler(handler));
1036 code_list->push_back(handle(handler, isolate));
1040 }
else if (feedback->GetHeapObjectIfWeak(&heap_object)) {
1041 MaybeObject extra = GetFeedbackExtra();
1042 if (!extra->IsCleared()) {
1043 DCHECK(IC::IsHandler(extra));
1044 code_list->push_back(handle(extra, isolate));
1048 return count == length;
1051 Name FeedbackNexus::FindFirstName()
const {
1052 if (IsKeyedStoreICKind(kind()) || IsKeyedLoadICKind(kind())) {
1053 MaybeObject feedback = GetFeedback();
1054 if (IsPropertyNameFeedback(feedback)) {
1055 return Name::cast(feedback->GetHeapObjectAssumeStrong());
1061 KeyedAccessLoadMode FeedbackNexus::GetKeyedAccessLoadMode()
const {
1062 DCHECK(IsKeyedLoadICKind(kind()));
1064 MaybeObjectHandles handlers;
1066 if (GetKeyType() == PROPERTY)
return STANDARD_LOAD;
1069 FindHandlers(&handlers, static_cast<int>(maps.size()));
1070 for (MaybeObjectHandle
const& handler : handlers) {
1071 KeyedAccessLoadMode mode = LoadHandler::GetKeyedAccessLoadMode(*handler);
1072 if (mode != STANDARD_LOAD)
return mode;
1075 return STANDARD_LOAD;
1080 bool BuiltinHasKeyedAccessStoreMode(
int builtin_index) {
1081 DCHECK(Builtins::IsBuiltinId(builtin_index));
1082 switch (builtin_index) {
1083 case Builtins::kKeyedStoreIC_SloppyArguments_Standard:
1084 case Builtins::kKeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW:
1085 case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB:
1086 case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionHandleCOW:
1087 case Builtins::kStoreFastElementIC_Standard:
1088 case Builtins::kStoreFastElementIC_GrowNoTransitionHandleCOW:
1089 case Builtins::kStoreFastElementIC_NoTransitionIgnoreOOB:
1090 case Builtins::kStoreFastElementIC_NoTransitionHandleCOW:
1091 case Builtins::kStoreInArrayLiteralIC_Slow_Standard:
1092 case Builtins::kStoreInArrayLiteralIC_Slow_GrowNoTransitionHandleCOW:
1093 case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionIgnoreOOB:
1094 case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionHandleCOW:
1095 case Builtins::kKeyedStoreIC_Slow_Standard:
1096 case Builtins::kKeyedStoreIC_Slow_GrowNoTransitionHandleCOW:
1097 case Builtins::kKeyedStoreIC_Slow_NoTransitionIgnoreOOB:
1098 case Builtins::kKeyedStoreIC_Slow_NoTransitionHandleCOW:
1099 case Builtins::kElementsTransitionAndStore_Standard:
1100 case Builtins::kElementsTransitionAndStore_GrowNoTransitionHandleCOW:
1101 case Builtins::kElementsTransitionAndStore_NoTransitionIgnoreOOB:
1102 case Builtins::kElementsTransitionAndStore_NoTransitionHandleCOW:
1110 KeyedAccessStoreMode KeyedAccessStoreModeForBuiltin(
int builtin_index) {
1111 DCHECK(BuiltinHasKeyedAccessStoreMode(builtin_index));
1112 switch (builtin_index) {
1113 case Builtins::kKeyedStoreIC_SloppyArguments_Standard:
1114 case Builtins::kStoreInArrayLiteralIC_Slow_Standard:
1115 case Builtins::kKeyedStoreIC_Slow_Standard:
1116 case Builtins::kStoreFastElementIC_Standard:
1117 case Builtins::kElementsTransitionAndStore_Standard:
1118 return STANDARD_STORE;
1119 case Builtins::kKeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW:
1120 case Builtins::kStoreInArrayLiteralIC_Slow_GrowNoTransitionHandleCOW:
1121 case Builtins::kKeyedStoreIC_Slow_GrowNoTransitionHandleCOW:
1122 case Builtins::kStoreFastElementIC_GrowNoTransitionHandleCOW:
1123 case Builtins::kElementsTransitionAndStore_GrowNoTransitionHandleCOW:
1124 return STORE_AND_GROW_NO_TRANSITION_HANDLE_COW;
1125 case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB:
1126 case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionIgnoreOOB:
1127 case Builtins::kKeyedStoreIC_Slow_NoTransitionIgnoreOOB:
1128 case Builtins::kStoreFastElementIC_NoTransitionIgnoreOOB:
1129 case Builtins::kElementsTransitionAndStore_NoTransitionIgnoreOOB:
1130 return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
1131 case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionHandleCOW:
1132 case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionHandleCOW:
1133 case Builtins::kKeyedStoreIC_Slow_NoTransitionHandleCOW:
1134 case Builtins::kStoreFastElementIC_NoTransitionHandleCOW:
1135 case Builtins::kElementsTransitionAndStore_NoTransitionHandleCOW:
1136 return STORE_NO_TRANSITION_HANDLE_COW;
1144 KeyedAccessStoreMode FeedbackNexus::GetKeyedAccessStoreMode()
const {
1145 DCHECK(IsKeyedStoreICKind(kind()) || IsStoreInArrayLiteralICKind(kind()));
1146 KeyedAccessStoreMode mode = STANDARD_STORE;
1148 MaybeObjectHandles handlers;
1150 if (GetKeyType() == PROPERTY)
return mode;
1153 FindHandlers(&handlers, static_cast<int>(maps.size()));
1154 for (
const MaybeObjectHandle& maybe_code_handler : handlers) {
1156 Handle<Code> handler;
1157 if (maybe_code_handler.object()->IsStoreHandler()) {
1158 Handle<StoreHandler> data_handler =
1159 Handle<StoreHandler>::cast(maybe_code_handler.object());
1160 handler = handle(Code::cast(data_handler->smi_handler()),
1161 vector()->GetIsolate());
1162 }
else if (maybe_code_handler.object()->IsSmi()) {
1164 DCHECK_EQ(*(maybe_code_handler.object()),
1165 *StoreHandler::StoreProxy(GetIsolate()));
1169 handler = Handle<Code>::cast(maybe_code_handler.object());
1172 if (handler->is_builtin()) {
1173 const int builtin_index = handler->builtin_index();
1174 if (!BuiltinHasKeyedAccessStoreMode(builtin_index))
continue;
1176 mode = KeyedAccessStoreModeForBuiltin(builtin_index);
1179 CHECK(CodeStub::MajorKeyFromKey(handler->stub_key()) ==
1187 IcCheckType FeedbackNexus::GetKeyType()
const {
1188 DCHECK(IsKeyedStoreICKind(kind()) || IsKeyedLoadICKind(kind()) ||
1189 IsStoreInArrayLiteralICKind(kind()));
1190 MaybeObject feedback = GetFeedback();
1191 if (feedback == MaybeObject::FromObject(
1192 *FeedbackVector::MegamorphicSentinel(GetIsolate()))) {
1193 return static_cast<IcCheckType
>(
1194 Smi::ToInt(GetFeedbackExtra()->cast<Object>()));
1196 return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
1199 BinaryOperationHint FeedbackNexus::GetBinaryOperationFeedback()
const {
1200 DCHECK_EQ(kind(), FeedbackSlotKind::kBinaryOp);
1201 int feedback = GetFeedback().ToSmi().value();
1202 return BinaryOperationHintFromFeedback(feedback);
1205 CompareOperationHint FeedbackNexus::GetCompareOperationFeedback()
const {
1206 DCHECK_EQ(kind(), FeedbackSlotKind::kCompareOp);
1207 int feedback = GetFeedback().ToSmi().value();
1208 return CompareOperationHintFromFeedback(feedback);
1211 ForInHint FeedbackNexus::GetForInFeedback()
const {
1212 DCHECK_EQ(kind(), FeedbackSlotKind::kForIn);
1213 int feedback = GetFeedback().ToSmi().value();
1214 return ForInHintFromFeedback(feedback);
1217 Handle<FeedbackCell> FeedbackNexus::GetFeedbackCell()
const {
1218 DCHECK_EQ(FeedbackSlotKind::kCreateClosure, kind());
1219 return handle(FeedbackCell::cast(GetFeedback()->cast<Object>()),
1220 vector()->GetIsolate());
1223 MaybeHandle<JSObject> FeedbackNexus::GetConstructorFeedback()
const {
1224 DCHECK_EQ(kind(), FeedbackSlotKind::kInstanceOf);
1225 Isolate* isolate = GetIsolate();
1226 MaybeObject feedback = GetFeedback();
1227 HeapObject* heap_object;
1228 if (feedback->GetHeapObjectIfWeak(&heap_object)) {
1229 return handle(JSObject::cast(heap_object), isolate);
1231 return MaybeHandle<JSObject>();
1236 bool InList(Handle<ArrayList> types, Handle<String> type) {
1237 for (
int i = 0;
i < types->Length();
i++) {
1238 Object* obj = types->Get(
i);
1239 if (String::cast(obj)->Equals(*type)) {
1247 void FeedbackNexus::Collect(Handle<String> type,
int position) {
1248 DCHECK(IsTypeProfileKind(kind()));
1249 DCHECK_GE(position, 0);
1250 Isolate* isolate = GetIsolate();
1252 MaybeObject
const feedback = GetFeedback();
1255 Handle<SimpleNumberDictionary> types;
1257 if (feedback == MaybeObject::FromObject(
1258 *FeedbackVector::UninitializedSentinel(isolate))) {
1259 types = SimpleNumberDictionary::New(isolate, 1);
1262 SimpleNumberDictionary::cast(feedback->GetHeapObjectAssumeStrong()),
1266 Handle<ArrayList> position_specific_types;
1268 int entry = types->FindEntry(isolate, position);
1269 if (entry == SimpleNumberDictionary::kNotFound) {
1270 position_specific_types = ArrayList::New(isolate, 1);
1271 types = SimpleNumberDictionary::Set(
1272 isolate, types, position,
1273 ArrayList::Add(isolate, position_specific_types, type));
1275 DCHECK(types->ValueAt(entry)->IsArrayList());
1276 position_specific_types =
1277 handle(ArrayList::cast(types->ValueAt(entry)), isolate);
1278 if (!InList(position_specific_types, type)) {
1279 types = SimpleNumberDictionary::Set(
1280 isolate, types, position,
1281 ArrayList::Add(isolate, position_specific_types, type));
1284 SetFeedback(*types);
1287 std::vector<int> FeedbackNexus::GetSourcePositions()
const {
1288 DCHECK(IsTypeProfileKind(kind()));
1289 std::vector<int> source_positions;
1290 Isolate* isolate = GetIsolate();
1292 MaybeObject
const feedback = GetFeedback();
1294 if (feedback == MaybeObject::FromObject(
1295 *FeedbackVector::UninitializedSentinel(isolate))) {
1296 return source_positions;
1299 Handle<SimpleNumberDictionary> types(
1300 SimpleNumberDictionary::cast(feedback->GetHeapObjectAssumeStrong()),
1303 for (
int index = SimpleNumberDictionary::kElementsStartIndex;
1304 index < types->length(); index += SimpleNumberDictionary::kEntrySize) {
1305 int key_index = index + SimpleNumberDictionary::kEntryKeyIndex;
1306 Object* key = types->get(key_index);
1308 int position = Smi::cast(key)->value();
1309 source_positions.push_back(position);
1312 return source_positions;
1315 std::vector<Handle<String>> FeedbackNexus::GetTypesForSourcePositions(
1317 DCHECK(IsTypeProfileKind(kind()));
1318 Isolate* isolate = GetIsolate();
1320 MaybeObject
const feedback = GetFeedback();
1321 std::vector<Handle<String>> types_for_position;
1322 if (feedback == MaybeObject::FromObject(
1323 *FeedbackVector::UninitializedSentinel(isolate))) {
1324 return types_for_position;
1327 Handle<SimpleNumberDictionary> types(
1328 SimpleNumberDictionary::cast(feedback->GetHeapObjectAssumeStrong()),
1331 int entry = types->FindEntry(isolate, position);
1332 if (entry == SimpleNumberDictionary::kNotFound) {
1333 return types_for_position;
1335 DCHECK(types->ValueAt(entry)->IsArrayList());
1336 Handle<ArrayList> position_specific_types =
1337 Handle<ArrayList>(ArrayList::cast(types->ValueAt(entry)), isolate);
1338 for (
int i = 0;
i < position_specific_types->Length();
i++) {
1339 Object* t = position_specific_types->Get(
i);
1340 types_for_position.push_back(Handle<String>(String::cast(t), isolate));
1343 return types_for_position;
1348 Handle<JSObject> ConvertToJSObject(Isolate* isolate,
1349 Handle<SimpleNumberDictionary> feedback) {
1350 Handle<JSObject> type_profile =
1351 isolate->factory()->NewJSObject(isolate->object_function());
1353 for (
int index = SimpleNumberDictionary::kElementsStartIndex;
1354 index < feedback->length();
1355 index += SimpleNumberDictionary::kEntrySize) {
1356 int key_index = index + SimpleNumberDictionary::kEntryKeyIndex;
1357 Object* key = feedback->get(key_index);
1359 int value_index = index + SimpleNumberDictionary::kEntryValueIndex;
1361 Handle<ArrayList> position_specific_types(
1362 ArrayList::cast(feedback->get(value_index)), isolate);
1364 int position = Smi::ToInt(key);
1365 JSObject::AddDataElement(
1366 type_profile, position,
1367 isolate->factory()->NewJSArrayWithElements(
1368 ArrayList::Elements(isolate, position_specific_types)),
1369 PropertyAttributes::NONE);
1372 return type_profile;
1376 JSObject* FeedbackNexus::GetTypeProfile()
const {
1377 DCHECK(IsTypeProfileKind(kind()));
1378 Isolate* isolate = GetIsolate();
1380 MaybeObject
const feedback = GetFeedback();
1382 if (feedback == MaybeObject::FromObject(
1383 *FeedbackVector::UninitializedSentinel(isolate))) {
1384 return *isolate->factory()->NewJSObject(isolate->object_function());
1387 return *ConvertToJSObject(isolate,
1388 handle(SimpleNumberDictionary::cast(
1389 feedback->GetHeapObjectAssumeStrong()),
1393 void FeedbackNexus::ResetTypeProfile() {
1394 DCHECK(IsTypeProfileKind(kind()));
1395 SetFeedback(*FeedbackVector::UninitializedSentinel(GetIsolate()));