Line data Source code
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 :
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/object-macros.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : template <typename Derived>
16 19422544 : FeedbackSlot FeedbackVectorSpecBase<Derived>::AddSlot(FeedbackSlotKind kind) {
17 0 : int slot = This()->slots();
18 19422544 : int entries_per_slot = FeedbackMetadata::GetSlotSize(kind);
19 : This()->append(kind);
20 32018893 : for (int i = 1; i < entries_per_slot; i++) {
21 : This()->append(FeedbackSlotKind::kInvalid);
22 : }
23 19422549 : return FeedbackSlot(slot);
24 : }
25 :
26 : template FeedbackSlot FeedbackVectorSpecBase<FeedbackVectorSpec>::AddSlot(
27 : FeedbackSlotKind kind);
28 : template FeedbackSlot FeedbackVectorSpecBase<StaticFeedbackVectorSpec>::AddSlot(
29 : FeedbackSlotKind kind);
30 :
31 : template <typename Derived>
32 85 : FeedbackSlot FeedbackVectorSpecBase<Derived>::AddTypeProfileSlot() {
33 85 : FeedbackSlot slot = AddSlot(FeedbackSlotKind::kTypeProfile);
34 85 : CHECK_EQ(FeedbackVectorSpec::kTypeProfileSlotIndex,
35 : FeedbackVector::GetIndex(slot));
36 85 : return slot;
37 : }
38 :
39 : template FeedbackSlot
40 : FeedbackVectorSpecBase<FeedbackVectorSpec>::AddTypeProfileSlot();
41 : template FeedbackSlot
42 : FeedbackVectorSpecBase<StaticFeedbackVectorSpec>::AddTypeProfileSlot();
43 :
44 0 : bool FeedbackVectorSpec::HasTypeProfileSlot() const {
45 : FeedbackSlot slot =
46 : FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
47 0 : if (slots() <= slot.ToInt()) {
48 : return false;
49 : }
50 0 : return GetKind(slot) == FeedbackSlotKind::kTypeProfile;
51 : }
52 :
53 2680638 : static bool IsPropertyNameFeedback(Object* feedback) {
54 2680638 : if (feedback->IsString()) return true;
55 2642368 : if (!feedback->IsSymbol()) return false;
56 : Symbol* symbol = Symbol::cast(feedback);
57 562493 : Heap* heap = symbol->GetHeap();
58 49957 : return symbol != heap->uninitialized_symbol() &&
59 512536 : symbol != heap->premonomorphic_symbol() &&
60 491746 : symbol != heap->megamorphic_symbol();
61 : }
62 :
63 0 : std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind) {
64 0 : return os << FeedbackMetadata::Kind2String(kind);
65 : }
66 :
67 70923692 : FeedbackSlotKind FeedbackMetadata::GetKind(FeedbackSlot slot) const {
68 : int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
69 : int data = Smi::ToInt(get(index));
70 141847384 : return VectorICComputer::decode(data, slot.ToInt());
71 : }
72 :
73 32012723 : void FeedbackMetadata::SetKind(FeedbackSlot slot, FeedbackSlotKind kind) {
74 : int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
75 : int data = Smi::ToInt(get(index));
76 64025446 : int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
77 : set(index, Smi::FromInt(new_data));
78 32012723 : }
79 :
80 : template Handle<FeedbackMetadata> FeedbackMetadata::New(
81 : Isolate* isolate, const StaticFeedbackVectorSpec* spec);
82 : template Handle<FeedbackMetadata> FeedbackMetadata::New(
83 : Isolate* isolate, const FeedbackVectorSpec* spec);
84 :
85 : // static
86 : template <typename Spec>
87 11529722 : Handle<FeedbackMetadata> FeedbackMetadata::New(Isolate* isolate,
88 : const Spec* spec) {
89 : Factory* factory = isolate->factory();
90 :
91 : const int slot_count = spec->slots();
92 : const int slot_kinds_length = VectorICComputer::word_count(slot_count);
93 11529722 : const int length = slot_kinds_length + kReservedIndexCount;
94 11529722 : if (length == kReservedIndexCount) {
95 : return Handle<FeedbackMetadata>::cast(factory->empty_fixed_array());
96 : }
97 : #ifdef DEBUG
98 : for (int i = 0; i < slot_count;) {
99 : FeedbackSlotKind kind = spec->GetKind(FeedbackSlot(i));
100 : int entry_size = FeedbackMetadata::GetSlotSize(kind);
101 : for (int j = 1; j < entry_size; j++) {
102 : FeedbackSlotKind kind = spec->GetKind(FeedbackSlot(i + j));
103 : DCHECK_EQ(FeedbackSlotKind::kInvalid, kind);
104 : }
105 : i += entry_size;
106 : }
107 : #endif
108 :
109 1662825 : Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
110 : array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
111 : // Fill the bit-vector part with zeros.
112 7925721 : for (int i = 0; i < slot_kinds_length; i++) {
113 : array->set(kReservedIndexCount + i, Smi::kZero);
114 : }
115 :
116 : Handle<FeedbackMetadata> metadata = Handle<FeedbackMetadata>::cast(array);
117 :
118 32012721 : for (int i = 0; i < slot_count; i++) {
119 : FeedbackSlot slot(i);
120 : FeedbackSlotKind kind = spec->GetKind(slot);
121 32012722 : metadata->SetKind(slot, kind);
122 : }
123 :
124 : // It's important that the FeedbackMetadata have a COW map, since it's
125 : // pointed to by both a SharedFunctionInfo and indirectly by closures through
126 : // the FeedbackVector. The serializer uses the COW map type to decide
127 : // this object belongs in the startup snapshot and not the partial
128 : // snapshot(s).
129 3325650 : metadata->set_map(isolate->heap()->fixed_cow_array_map());
130 :
131 1662825 : return metadata;
132 : }
133 :
134 2134855 : bool FeedbackMetadata::SpecDiffersFrom(
135 : const FeedbackVectorSpec* other_spec) const {
136 2134855 : if (other_spec->slots() != slot_count()) {
137 : return true;
138 : }
139 :
140 2134855 : int slots = slot_count();
141 23662428 : for (int i = 0; i < slots;) {
142 : FeedbackSlot slot(i);
143 19392709 : FeedbackSlotKind kind = GetKind(slot);
144 19392709 : int entry_size = FeedbackMetadata::GetSlotSize(kind);
145 :
146 19392717 : if (kind != other_spec->GetKind(slot)) {
147 : return true;
148 : }
149 19392718 : i += entry_size;
150 : }
151 : return false;
152 : }
153 :
154 0 : const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
155 0 : switch (kind) {
156 : case FeedbackSlotKind::kInvalid:
157 : return "Invalid";
158 : case FeedbackSlotKind::kCall:
159 0 : return "Call";
160 : case FeedbackSlotKind::kLoadProperty:
161 0 : return "LoadProperty";
162 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
163 0 : return "LoadGlobalInsideTypeof";
164 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
165 0 : return "LoadGlobalNotInsideTypeof";
166 : case FeedbackSlotKind::kLoadKeyed:
167 0 : return "LoadKeyed";
168 : case FeedbackSlotKind::kStoreNamedSloppy:
169 0 : return "StoreNamedSloppy";
170 : case FeedbackSlotKind::kStoreNamedStrict:
171 0 : return "StoreNamedStrict";
172 : case FeedbackSlotKind::kStoreOwnNamed:
173 0 : return "StoreOwnNamed";
174 : case FeedbackSlotKind::kStoreGlobalSloppy:
175 0 : return "StoreGlobalSloppy";
176 : case FeedbackSlotKind::kStoreGlobalStrict:
177 0 : return "StoreGlobalStrict";
178 : case FeedbackSlotKind::kStoreKeyedSloppy:
179 0 : return "StoreKeyedSloppy";
180 : case FeedbackSlotKind::kStoreKeyedStrict:
181 0 : return "StoreKeyedStrict";
182 : case FeedbackSlotKind::kBinaryOp:
183 0 : return "BinaryOp";
184 : case FeedbackSlotKind::kCompareOp:
185 0 : return "CompareOp";
186 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
187 0 : return "StoreDataPropertyInLiteral";
188 : case FeedbackSlotKind::kCreateClosure:
189 0 : return "kCreateClosure";
190 : case FeedbackSlotKind::kLiteral:
191 0 : return "Literal";
192 : case FeedbackSlotKind::kTypeProfile:
193 0 : return "TypeProfile";
194 : case FeedbackSlotKind::kForIn:
195 0 : return "ForIn";
196 : case FeedbackSlotKind::kKindsNumber:
197 : break;
198 : }
199 0 : UNREACHABLE();
200 : }
201 :
202 901 : bool FeedbackMetadata::HasTypeProfileSlot() const {
203 : FeedbackSlot slot =
204 : FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
205 1762 : return slot.ToInt() < this->length() &&
206 1762 : GetKind(slot) == FeedbackSlotKind::kTypeProfile;
207 : }
208 :
209 21034289 : FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot) const {
210 : DCHECK(!is_empty());
211 21034289 : return metadata()->GetKind(slot);
212 : }
213 :
214 570 : FeedbackSlot FeedbackVector::GetTypeProfileSlot() const {
215 : DCHECK(metadata()->HasTypeProfileSlot());
216 : FeedbackSlot slot =
217 : FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
218 : DCHECK_EQ(FeedbackSlotKind::kTypeProfile, GetKind(slot));
219 570 : return slot;
220 : }
221 :
222 : // static
223 6329861 : Handle<FeedbackVector> FeedbackVector::New(Isolate* isolate,
224 : Handle<SharedFunctionInfo> shared) {
225 : Factory* factory = isolate->factory();
226 :
227 6329861 : const int slot_count = shared->feedback_metadata()->slot_count();
228 :
229 6329862 : Handle<FeedbackVector> vector = factory->NewFeedbackVector(shared, TENURED);
230 :
231 : DCHECK_EQ(vector->length(), slot_count);
232 :
233 : DCHECK_EQ(vector->shared_function_info(), *shared);
234 : DCHECK_EQ(vector->optimized_code_cell(),
235 : Smi::FromEnum(OptimizationMarker::kNone));
236 : DCHECK_EQ(vector->invocation_count(), 0);
237 : DCHECK_EQ(vector->profiler_ticks(), 0);
238 : DCHECK_EQ(vector->deopt_count(), 0);
239 :
240 : // Ensure we can skip the write barrier
241 : Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
242 : DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel);
243 : Handle<Oddball> undefined_value = factory->undefined_value();
244 42921934 : for (int i = 0; i < slot_count;) {
245 : FeedbackSlot slot(i);
246 30262210 : FeedbackSlotKind kind = shared->feedback_metadata()->GetKind(slot);
247 : int index = FeedbackVector::GetIndex(slot);
248 30262209 : int entry_size = FeedbackMetadata::GetSlotSize(kind);
249 :
250 : Object* extra_value = *uninitialized_sentinel;
251 30262209 : switch (kind) {
252 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
253 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
254 4869406 : vector->set(index, isolate->heap()->empty_weak_cell(),
255 4869406 : SKIP_WRITE_BARRIER);
256 4869406 : break;
257 : case FeedbackSlotKind::kForIn:
258 : case FeedbackSlotKind::kCompareOp:
259 : case FeedbackSlotKind::kBinaryOp:
260 3226193 : vector->set(index, Smi::kZero, SKIP_WRITE_BARRIER);
261 3226193 : break;
262 : case FeedbackSlotKind::kCreateClosure: {
263 6100498 : Handle<Cell> cell = factory->NewNoClosuresCell(undefined_value);
264 6100498 : vector->set(index, *cell);
265 : break;
266 : }
267 : case FeedbackSlotKind::kLiteral:
268 951892 : vector->set(index, Smi::kZero, SKIP_WRITE_BARRIER);
269 951892 : break;
270 : case FeedbackSlotKind::kCall:
271 4790711 : vector->set(index, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
272 : extra_value = Smi::kZero;
273 4790711 : break;
274 : case FeedbackSlotKind::kLoadProperty:
275 : case FeedbackSlotKind::kLoadKeyed:
276 : case FeedbackSlotKind::kStoreNamedSloppy:
277 : case FeedbackSlotKind::kStoreNamedStrict:
278 : case FeedbackSlotKind::kStoreOwnNamed:
279 : case FeedbackSlotKind::kStoreGlobalSloppy:
280 : case FeedbackSlotKind::kStoreGlobalStrict:
281 : case FeedbackSlotKind::kStoreKeyedSloppy:
282 : case FeedbackSlotKind::kStoreKeyedStrict:
283 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
284 : case FeedbackSlotKind::kTypeProfile:
285 10323509 : vector->set(index, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
286 10323509 : break;
287 :
288 : case FeedbackSlotKind::kInvalid:
289 : case FeedbackSlotKind::kKindsNumber:
290 0 : UNREACHABLE();
291 : break;
292 : }
293 50245736 : for (int j = 1; j < entry_size; j++) {
294 39967052 : vector->set(index + j, extra_value, SKIP_WRITE_BARRIER);
295 : }
296 30262210 : i += entry_size;
297 : }
298 :
299 : Handle<FeedbackVector> result = Handle<FeedbackVector>::cast(vector);
300 12658550 : if (!isolate->is_best_effort_code_coverage() ||
301 : isolate->is_collecting_type_profile()) {
302 1605 : AddToVectorsForProfilingTools(isolate, result);
303 : }
304 6329862 : return result;
305 : }
306 :
307 : // static
308 0 : Handle<FeedbackVector> FeedbackVector::Copy(Isolate* isolate,
309 : Handle<FeedbackVector> vector) {
310 : Handle<FeedbackVector> result;
311 : result = Handle<FeedbackVector>::cast(
312 0 : isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
313 0 : if (!isolate->is_best_effort_code_coverage() ||
314 : isolate->is_collecting_type_profile()) {
315 0 : AddToVectorsForProfilingTools(isolate, result);
316 : }
317 0 : return result;
318 : }
319 :
320 : // static
321 1605 : void FeedbackVector::AddToVectorsForProfilingTools(
322 : Isolate* isolate, Handle<FeedbackVector> vector) {
323 : DCHECK(!isolate->is_best_effort_code_coverage() ||
324 : isolate->is_collecting_type_profile());
325 3210 : if (!vector->shared_function_info()->IsSubjectToDebugging()) return;
326 : Handle<ArrayList> list = Handle<ArrayList>::cast(
327 : isolate->factory()->feedback_vectors_for_profiling_tools());
328 1275 : list = ArrayList::Add(list, vector);
329 1275 : isolate->SetFeedbackVectorsForProfilingTools(*list);
330 : }
331 :
332 : // static
333 18557 : void FeedbackVector::SetOptimizedCode(Handle<FeedbackVector> vector,
334 : Handle<Code> code) {
335 : DCHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
336 : Factory* factory = vector->GetIsolate()->factory();
337 18557 : Handle<WeakCell> cell = factory->NewWeakCell(code);
338 18557 : vector->set_optimized_code_cell(*cell);
339 18557 : }
340 :
341 673541 : void FeedbackVector::SetOptimizationMarker(OptimizationMarker marker) {
342 673541 : set_optimized_code_cell(Smi::FromEnum(marker));
343 673541 : }
344 :
345 413852 : void FeedbackVector::ClearOptimizedCode() {
346 416059 : set_optimized_code_cell(Smi::FromEnum(OptimizationMarker::kNone));
347 413853 : }
348 :
349 4546278 : void FeedbackVector::EvictOptimizedCodeMarkedForDeoptimization(
350 : SharedFunctionInfo* shared, const char* reason) {
351 : Object* slot = optimized_code_cell();
352 4546278 : if (slot->IsSmi()) return;
353 :
354 : WeakCell* cell = WeakCell::cast(slot);
355 496396 : if (cell->cleared()) {
356 : ClearOptimizedCode();
357 : return;
358 : }
359 :
360 : Code* code = Code::cast(cell->value());
361 496160 : if (code->marked_for_deoptimization()) {
362 1971 : if (FLAG_trace_deopt) {
363 : PrintF("[evicting optimizing code marked for deoptimization (%s) for ",
364 0 : reason);
365 0 : shared->ShortPrint();
366 0 : PrintF("]\n");
367 : }
368 1971 : if (!code->deopt_already_counted()) {
369 : increment_deopt_count();
370 : code->set_deopt_already_counted(true);
371 : }
372 : ClearOptimizedCode();
373 : }
374 : }
375 :
376 67308 : bool FeedbackVector::ClearSlots(Isolate* isolate) {
377 : Object* uninitialized_sentinel =
378 : FeedbackVector::RawUninitializedSentinel(isolate);
379 :
380 : bool feedback_updated = false;
381 : FeedbackMetadataIterator iter(metadata());
382 300468 : while (iter.HasNext()) {
383 233160 : FeedbackSlot slot = iter.Next();
384 233160 : FeedbackSlotKind kind = iter.kind();
385 :
386 : Object* obj = Get(slot);
387 233160 : if (obj != uninitialized_sentinel) {
388 193040 : switch (kind) {
389 : case FeedbackSlotKind::kCall: {
390 : CallICNexus nexus(this, slot);
391 7701 : if (!nexus.IsCleared()) {
392 : nexus.Clear();
393 : feedback_updated = true;
394 : }
395 : break;
396 : }
397 : case FeedbackSlotKind::kLoadProperty: {
398 : LoadICNexus nexus(this, slot);
399 39173 : if (!nexus.IsCleared()) {
400 : nexus.Clear();
401 : feedback_updated = true;
402 : }
403 : break;
404 : }
405 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
406 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof: {
407 : LoadGlobalICNexus nexus(this, slot);
408 6749 : if (!nexus.IsCleared()) {
409 : nexus.Clear();
410 : feedback_updated = true;
411 : }
412 : break;
413 : }
414 : case FeedbackSlotKind::kLoadKeyed: {
415 : KeyedLoadICNexus nexus(this, slot);
416 4837 : if (!nexus.IsCleared()) {
417 : nexus.Clear();
418 : feedback_updated = true;
419 : }
420 : break;
421 : }
422 : case FeedbackSlotKind::kStoreNamedSloppy:
423 : case FeedbackSlotKind::kStoreNamedStrict:
424 : case FeedbackSlotKind::kStoreOwnNamed:
425 : case FeedbackSlotKind::kStoreGlobalSloppy:
426 : case FeedbackSlotKind::kStoreGlobalStrict: {
427 : StoreICNexus nexus(this, slot);
428 59863 : if (!nexus.IsCleared()) {
429 : nexus.Clear();
430 : feedback_updated = true;
431 : }
432 : break;
433 : }
434 : case FeedbackSlotKind::kStoreKeyedSloppy:
435 : case FeedbackSlotKind::kStoreKeyedStrict: {
436 : KeyedStoreICNexus nexus(this, slot);
437 4003 : if (!nexus.IsCleared()) {
438 : nexus.Clear();
439 : feedback_updated = true;
440 : }
441 : break;
442 : }
443 : case FeedbackSlotKind::kForIn:
444 : case FeedbackSlotKind::kBinaryOp:
445 : case FeedbackSlotKind::kCompareOp: {
446 : DCHECK(Get(slot)->IsSmi());
447 : // don't clear these smi slots.
448 : // Set(slot, Smi::kZero);
449 : break;
450 : }
451 : case FeedbackSlotKind::kCreateClosure: {
452 : case FeedbackSlotKind::kTypeProfile:
453 : break;
454 : }
455 : case FeedbackSlotKind::kLiteral: {
456 : Set(slot, Smi::kZero, SKIP_WRITE_BARRIER);
457 : feedback_updated = true;
458 3663 : break;
459 : }
460 : case FeedbackSlotKind::kStoreDataPropertyInLiteral: {
461 : StoreDataPropertyInLiteralICNexus nexus(this, slot);
462 473 : if (!nexus.IsCleared()) {
463 : nexus.Clear();
464 : feedback_updated = true;
465 : }
466 : break;
467 : }
468 : case FeedbackSlotKind::kInvalid:
469 : case FeedbackSlotKind::kKindsNumber:
470 0 : UNREACHABLE();
471 : break;
472 : }
473 : }
474 : }
475 67308 : return feedback_updated;
476 : }
477 :
478 284727 : Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
479 : Isolate* isolate = GetIsolate();
480 284727 : Handle<Object> feedback = handle(GetFeedback(), isolate);
481 396262 : if (!feedback->IsFixedArray() ||
482 : FixedArray::cast(*feedback)->length() != length) {
483 279186 : Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
484 279186 : SetFeedback(*array);
485 279186 : return array;
486 : }
487 : return Handle<FixedArray>::cast(feedback);
488 : }
489 :
490 29599 : Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) {
491 : Isolate* isolate = GetIsolate();
492 29599 : Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate);
493 34343 : if (!feedback_extra->IsFixedArray() ||
494 : FixedArray::cast(*feedback_extra)->length() != length) {
495 28920 : Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
496 28920 : SetFeedbackExtra(*array);
497 28920 : return array;
498 : }
499 : return Handle<FixedArray>::cast(feedback_extra);
500 : }
501 :
502 473 : void FeedbackNexus::ConfigureUninitialized() {
503 : SetFeedback(*FeedbackVector::UninitializedSentinel(GetIsolate()),
504 473 : SKIP_WRITE_BARRIER);
505 : SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(GetIsolate()),
506 473 : SKIP_WRITE_BARRIER);
507 473 : }
508 :
509 3590930 : void FeedbackNexus::ConfigurePremonomorphic() {
510 : SetFeedback(*FeedbackVector::PremonomorphicSentinel(GetIsolate()),
511 3590930 : SKIP_WRITE_BARRIER);
512 : SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(GetIsolate()),
513 3590930 : SKIP_WRITE_BARRIER);
514 3590930 : }
515 :
516 90372 : void FeedbackNexus::ConfigureMegamorphic(IcCheckType property_type) {
517 : Isolate* isolate = GetIsolate();
518 : SetFeedback(*FeedbackVector::MegamorphicSentinel(isolate),
519 90372 : SKIP_WRITE_BARRIER);
520 90372 : SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
521 90372 : SKIP_WRITE_BARRIER);
522 90372 : }
523 :
524 2554251 : InlineCacheState LoadICNexus::StateFromFeedback() const {
525 : Isolate* isolate = GetIsolate();
526 2554251 : Object* feedback = GetFeedback();
527 :
528 2554252 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
529 : return UNINITIALIZED;
530 1764248 : } else if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
531 : return MEGAMORPHIC;
532 1452220 : } else if (feedback == *FeedbackVector::PremonomorphicSentinel(isolate)) {
533 : return PREMONOMORPHIC;
534 549780 : } else if (feedback->IsFixedArray()) {
535 : // Determine state purely by our structure, don't check if the maps are
536 : // cleared.
537 : return POLYMORPHIC;
538 407120 : } else if (feedback->IsWeakCell()) {
539 : // Don't check if the map is cleared.
540 : return MONOMORPHIC;
541 : }
542 :
543 0 : return UNINITIALIZED;
544 : }
545 :
546 1889630 : InlineCacheState LoadGlobalICNexus::StateFromFeedback() const {
547 : Isolate* isolate = GetIsolate();
548 1889630 : Object* feedback = GetFeedback();
549 :
550 1889630 : Object* extra = GetFeedbackExtra();
551 3772534 : if (!WeakCell::cast(feedback)->cleared() ||
552 : extra != *FeedbackVector::UninitializedSentinel(isolate)) {
553 : return MONOMORPHIC;
554 : }
555 1882701 : return UNINITIALIZED;
556 : }
557 :
558 382037 : InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
559 : Isolate* isolate = GetIsolate();
560 382037 : Object* feedback = GetFeedback();
561 :
562 382037 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
563 : return UNINITIALIZED;
564 160518 : } else if (feedback == *FeedbackVector::PremonomorphicSentinel(isolate)) {
565 : return PREMONOMORPHIC;
566 129561 : } else if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
567 : return MEGAMORPHIC;
568 93031 : } else if (feedback->IsFixedArray()) {
569 : // Determine state purely by our structure, don't check if the maps are
570 : // cleared.
571 : return POLYMORPHIC;
572 79156 : } else if (feedback->IsWeakCell()) {
573 : // Don't check if the map is cleared.
574 : return MONOMORPHIC;
575 16985 : } else if (feedback->IsName()) {
576 16985 : Object* extra = GetFeedbackExtra();
577 : FixedArray* extra_array = FixedArray::cast(extra);
578 16985 : return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
579 : }
580 :
581 : return UNINITIALIZED;
582 : }
583 :
584 4656796 : InlineCacheState StoreICNexus::StateFromFeedback() const {
585 : Isolate* isolate = GetIsolate();
586 4656796 : Object* feedback = GetFeedback();
587 :
588 4656796 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
589 : return UNINITIALIZED;
590 1183291 : } else if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
591 : return MEGAMORPHIC;
592 781495 : } else if (feedback == *FeedbackVector::PremonomorphicSentinel(isolate)) {
593 : return PREMONOMORPHIC;
594 320106 : } else if (feedback->IsFixedArray()) {
595 : // Determine state purely by our structure, don't check if the maps are
596 : // cleared.
597 : return POLYMORPHIC;
598 224434 : } else if (feedback->IsWeakCell()) {
599 : // Don't check if the map is cleared.
600 : return MONOMORPHIC;
601 : }
602 :
603 0 : return UNINITIALIZED;
604 : }
605 :
606 412088 : InlineCacheState KeyedStoreICNexus::StateFromFeedback() const {
607 : Isolate* isolate = GetIsolate();
608 412088 : Object* feedback = GetFeedback();
609 :
610 412088 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
611 : return UNINITIALIZED;
612 98219 : } else if (feedback == *FeedbackVector::PremonomorphicSentinel(isolate)) {
613 : return PREMONOMORPHIC;
614 89232 : } else if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
615 : return MEGAMORPHIC;
616 52094 : } else if (feedback->IsFixedArray()) {
617 : // Determine state purely by our structure, don't check if the maps are
618 : // cleared.
619 : return POLYMORPHIC;
620 44213 : } else if (feedback->IsWeakCell()) {
621 : // Don't check if the map is cleared.
622 : return MONOMORPHIC;
623 2675 : } else if (feedback->IsName()) {
624 2675 : Object* extra = GetFeedbackExtra();
625 : FixedArray* extra_array = FixedArray::cast(extra);
626 2675 : return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
627 : }
628 :
629 : return UNINITIALIZED;
630 : }
631 :
632 538754 : InlineCacheState CallICNexus::StateFromFeedback() const {
633 : Isolate* isolate = GetIsolate();
634 538754 : Object* feedback = GetFeedback();
635 : DCHECK(GetFeedbackExtra() ==
636 : *FeedbackVector::UninitializedSentinel(isolate) ||
637 : GetFeedbackExtra()->IsSmi());
638 :
639 538756 : if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
640 : return GENERIC;
641 1034231 : } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) {
642 : return MONOMORPHIC;
643 : }
644 :
645 334752 : CHECK(feedback == *FeedbackVector::UninitializedSentinel(isolate));
646 : return UNINITIALIZED;
647 : }
648 :
649 618735 : int CallICNexus::ExtractCallCount() {
650 618735 : Object* call_count = GetFeedbackExtra();
651 618735 : CHECK(call_count->IsSmi());
652 : int value = Smi::ToInt(call_count);
653 618735 : return value;
654 : }
655 :
656 618715 : float CallICNexus::ComputeCallFrequency() {
657 618715 : double const invocation_count = vector()->invocation_count();
658 618715 : double const call_count = ExtractCallCount();
659 618715 : if (invocation_count == 0) {
660 : // Prevent division by 0.
661 : return 0.0f;
662 : }
663 173219 : return static_cast<float>(call_count / invocation_count);
664 : }
665 :
666 7701 : void CallICNexus::ConfigureUninitialized() {
667 : Isolate* isolate = GetIsolate();
668 : SetFeedback(*FeedbackVector::UninitializedSentinel(isolate),
669 7701 : SKIP_WRITE_BARRIER);
670 7701 : SetFeedbackExtra(Smi::kZero, SKIP_WRITE_BARRIER);
671 7701 : }
672 :
673 6325 : void LoadGlobalICNexus::ConfigureUninitialized() {
674 : Isolate* isolate = GetIsolate();
675 6325 : SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER);
676 : SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
677 6325 : SKIP_WRITE_BARRIER);
678 6325 : }
679 :
680 3274196 : void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
681 : Isolate* isolate = GetIsolate();
682 6548394 : SetFeedback(*isolate->factory()->NewWeakCell(cell));
683 : SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
684 3274198 : SKIP_WRITE_BARRIER);
685 3274198 : }
686 :
687 52292 : void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Object> handler) {
688 52292 : SetFeedback(GetIsolate()->heap()->empty_weak_cell());
689 52292 : SetFeedbackExtra(*handler);
690 52292 : }
691 :
692 1722616 : void FeedbackNexus::ConfigureMonomorphic(Handle<Name> name,
693 : Handle<Map> receiver_map,
694 : Handle<Object> handler) {
695 1722616 : Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
696 1722616 : if (name.is_null()) {
697 1697290 : SetFeedback(*cell);
698 1697290 : SetFeedbackExtra(*handler);
699 : } else {
700 25326 : Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
701 25326 : SetFeedback(*name);
702 25326 : array->set(0, *cell);
703 25326 : array->set(1, *handler);
704 : }
705 1722616 : }
706 :
707 289000 : void FeedbackNexus::ConfigurePolymorphic(Handle<Name> name,
708 1013492 : MapHandles const& maps,
709 : ObjectHandles* handlers) {
710 289000 : int receiver_count = static_cast<int>(maps.size());
711 : DCHECK_GT(receiver_count, 1);
712 : Handle<FixedArray> array;
713 289000 : if (name.is_null()) {
714 284727 : array = EnsureArrayOfSize(receiver_count * 2);
715 : SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(GetIsolate()),
716 284727 : SKIP_WRITE_BARRIER);
717 : } else {
718 4273 : array = EnsureExtraArrayOfSize(receiver_count * 2);
719 4273 : SetFeedback(*name);
720 : }
721 :
722 1013492 : for (int current = 0; current < receiver_count; ++current) {
723 1448984 : Handle<Map> map = maps[current];
724 724492 : Handle<WeakCell> cell = Map::WeakCellForMap(map);
725 1448984 : array->set(current * 2, *cell);
726 1448984 : array->set(current * 2 + 1, *handlers->at(current));
727 : }
728 289000 : }
729 :
730 1242654 : int FeedbackNexus::ExtractMaps(MapHandles* maps) const {
731 : Isolate* isolate = GetIsolate();
732 1242654 : Object* feedback = GetFeedback();
733 1242654 : bool is_named_feedback = IsPropertyNameFeedback(feedback);
734 1242654 : if (feedback->IsFixedArray() || is_named_feedback) {
735 : int found = 0;
736 234091 : if (is_named_feedback) {
737 6231 : feedback = GetFeedbackExtra();
738 : }
739 : FixedArray* array = FixedArray::cast(feedback);
740 : const int increment = 2;
741 1668704 : for (int i = 0; i < array->length(); i += increment) {
742 : DCHECK(array->get(i)->IsWeakCell());
743 : WeakCell* cell = WeakCell::cast(array->get(i));
744 600261 : if (!cell->cleared()) {
745 : Map* map = Map::cast(cell->value());
746 946146 : maps->push_back(handle(map, isolate));
747 473073 : found++;
748 : }
749 : }
750 : return found;
751 1008563 : } else if (feedback->IsWeakCell()) {
752 : WeakCell* cell = WeakCell::cast(feedback);
753 640186 : if (!cell->cleared()) {
754 : Map* map = Map::cast(cell->value());
755 885860 : maps->push_back(handle(map, isolate));
756 442930 : return 1;
757 : }
758 : }
759 :
760 : return 0;
761 : }
762 :
763 622836 : MaybeHandle<Object> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
764 622836 : Object* feedback = GetFeedback();
765 : Isolate* isolate = GetIsolate();
766 622836 : bool is_named_feedback = IsPropertyNameFeedback(feedback);
767 622836 : if (feedback->IsFixedArray() || is_named_feedback) {
768 203104 : if (is_named_feedback) {
769 2236 : feedback = GetFeedbackExtra();
770 : }
771 : FixedArray* array = FixedArray::cast(feedback);
772 : const int increment = 2;
773 1443888 : for (int i = 0; i < array->length(); i += increment) {
774 : DCHECK(array->get(i)->IsWeakCell());
775 : WeakCell* cell = WeakCell::cast(array->get(i));
776 520490 : if (!cell->cleared()) {
777 : Map* array_map = Map::cast(cell->value());
778 393625 : if (array_map == *map) {
779 1650 : Object* code = array->get(i + increment - 1);
780 : DCHECK(IC::IsHandler(code));
781 1650 : return handle(code, isolate);
782 : }
783 : }
784 : }
785 419732 : } else if (feedback->IsWeakCell()) {
786 : WeakCell* cell = WeakCell::cast(feedback);
787 419732 : if (!cell->cleared()) {
788 : Map* cell_map = Map::cast(cell->value());
789 227569 : if (cell_map == *map) {
790 40311 : Object* code = GetFeedbackExtra();
791 : DCHECK(IC::IsHandler(code));
792 40311 : return handle(code, isolate);
793 : }
794 : }
795 : }
796 :
797 580875 : return MaybeHandle<Code>();
798 : }
799 :
800 645781 : bool FeedbackNexus::FindHandlers(ObjectHandles* code_list, int length) const {
801 645781 : Object* feedback = GetFeedback();
802 : Isolate* isolate = GetIsolate();
803 : int count = 0;
804 645781 : bool is_named_feedback = IsPropertyNameFeedback(feedback);
805 645781 : if (feedback->IsFixedArray() || is_named_feedback) {
806 217126 : if (is_named_feedback) {
807 5565 : feedback = GetFeedbackExtra();
808 : }
809 : FixedArray* array = FixedArray::cast(feedback);
810 : const int increment = 2;
811 1627292 : for (int i = 0; i < array->length(); i += increment) {
812 : DCHECK(array->get(i)->IsWeakCell());
813 : WeakCell* cell = WeakCell::cast(array->get(i));
814 : // Be sure to skip handlers whose maps have been cleared.
815 596520 : if (!cell->cleared()) {
816 482704 : Object* code = array->get(i + increment - 1);
817 : DCHECK(IC::IsHandler(code));
818 965408 : code_list->push_back(handle(code, isolate));
819 482704 : count++;
820 : }
821 : }
822 428655 : } else if (feedback->IsWeakCell()) {
823 : WeakCell* cell = WeakCell::cast(feedback);
824 373691 : if (!cell->cleared()) {
825 221697 : Object* code = GetFeedbackExtra();
826 : DCHECK(IC::IsHandler(code));
827 443394 : code_list->push_back(handle(code, isolate));
828 : count++;
829 : }
830 : }
831 645781 : return count == length;
832 : }
833 :
834 49746 : Name* KeyedLoadICNexus::FindFirstName() const {
835 49746 : Object* feedback = GetFeedback();
836 49746 : if (IsPropertyNameFeedback(feedback)) {
837 32200 : return Name::cast(feedback);
838 : }
839 : return nullptr;
840 : }
841 :
842 14744 : Name* KeyedStoreICNexus::FindFirstName() const {
843 14744 : Object* feedback = GetFeedback();
844 14744 : if (IsPropertyNameFeedback(feedback)) {
845 4421 : return Name::cast(feedback);
846 : }
847 : return nullptr;
848 : }
849 :
850 79476 : KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
851 : KeyedAccessStoreMode mode = STANDARD_STORE;
852 : MapHandles maps;
853 : ObjectHandles handlers;
854 :
855 79476 : if (GetKeyType() == PROPERTY) return mode;
856 :
857 78718 : ExtractMaps(&maps);
858 157436 : FindHandlers(&handlers, static_cast<int>(maps.size()));
859 157481 : for (const Handle<Object>& maybe_code_handler : handlers) {
860 : // The first handler that isn't the slow handler will have the bits we need.
861 : Handle<Code> handler;
862 23780 : if (maybe_code_handler->IsTuple3()) {
863 : // Elements transition.
864 : Handle<Tuple3> data_handler = Handle<Tuple3>::cast(maybe_code_handler);
865 : handler = handle(Code::cast(data_handler->value2()));
866 23736 : } else if (maybe_code_handler->IsTuple2()) {
867 : // Element store with prototype chain check.
868 : Handle<Tuple2> data_handler = Handle<Tuple2>::cast(maybe_code_handler);
869 : handler = handle(Code::cast(data_handler->value2()));
870 748 : } else if (maybe_code_handler->IsSmi()) {
871 : // Skip proxy handlers.
872 : DCHECK_EQ(*maybe_code_handler, *StoreHandler::StoreProxy(GetIsolate()));
873 : continue;
874 : } else {
875 : // Element store without prototype chain check.
876 : handler = Handle<Code>::cast(maybe_code_handler);
877 729 : if (handler->is_builtin()) continue;
878 : }
879 : CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
880 : uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
881 23735 : CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
882 : major_key == CodeStub::StoreFastElement ||
883 : major_key == CodeStub::StoreSlowElement ||
884 : major_key == CodeStub::ElementsTransitionAndStore ||
885 : major_key == CodeStub::NoCache);
886 23735 : if (major_key != CodeStub::NoCache) {
887 : mode = CommonStoreModeBits::decode(minor_key);
888 : break;
889 : }
890 : }
891 :
892 78718 : return mode;
893 : }
894 :
895 17515 : IcCheckType KeyedLoadICNexus::GetKeyType() const {
896 17515 : Object* feedback = GetFeedback();
897 17515 : if (feedback == *FeedbackVector::MegamorphicSentinel(GetIsolate())) {
898 2466 : return static_cast<IcCheckType>(Smi::ToInt(GetFeedbackExtra()));
899 : }
900 16282 : return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
901 : }
902 :
903 89752 : IcCheckType KeyedStoreICNexus::GetKeyType() const {
904 89752 : Object* feedback = GetFeedback();
905 89752 : if (feedback == *FeedbackVector::MegamorphicSentinel(GetIsolate())) {
906 2312 : return static_cast<IcCheckType>(Smi::ToInt(GetFeedbackExtra()));
907 : }
908 88596 : return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
909 : }
910 :
911 285222 : InlineCacheState BinaryOpICNexus::StateFromFeedback() const {
912 : BinaryOperationHint hint = GetBinaryOperationFeedback();
913 285222 : if (hint == BinaryOperationHint::kNone) {
914 : return UNINITIALIZED;
915 271271 : } else if (hint == BinaryOperationHint::kAny) {
916 : return GENERIC;
917 : }
918 :
919 268208 : return MONOMORPHIC;
920 : }
921 :
922 148176 : InlineCacheState CompareICNexus::StateFromFeedback() const {
923 : CompareOperationHint hint = GetCompareOperationFeedback();
924 148176 : if (hint == CompareOperationHint::kNone) {
925 : return UNINITIALIZED;
926 131968 : } else if (hint == CompareOperationHint::kAny) {
927 : return GENERIC;
928 : }
929 :
930 98899 : return MONOMORPHIC;
931 : }
932 :
933 713244 : BinaryOperationHint BinaryOpICNexus::GetBinaryOperationFeedback() const {
934 998466 : int feedback = Smi::ToInt(GetFeedback());
935 713244 : return BinaryOperationHintFromFeedback(feedback);
936 : }
937 :
938 397244 : CompareOperationHint CompareICNexus::GetCompareOperationFeedback() const {
939 545420 : int feedback = Smi::ToInt(GetFeedback());
940 397244 : return CompareOperationHintFromFeedback(feedback);
941 : }
942 :
943 1206 : InlineCacheState ForInICNexus::StateFromFeedback() const {
944 : ForInHint hint = GetForInFeedback();
945 1206 : if (hint == ForInHint::kNone) {
946 : return UNINITIALIZED;
947 1170 : } else if (hint == ForInHint::kAny) {
948 : return GENERIC;
949 : }
950 516 : return MONOMORPHIC;
951 : }
952 :
953 3222 : ForInHint ForInICNexus::GetForInFeedback() const {
954 4428 : int feedback = Smi::ToInt(GetFeedback());
955 3222 : return ForInHintFromFeedback(feedback);
956 : }
957 :
958 847839 : InlineCacheState StoreDataPropertyInLiteralICNexus::StateFromFeedback() const {
959 : Isolate* isolate = GetIsolate();
960 847839 : Object* feedback = GetFeedback();
961 :
962 847839 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
963 : return UNINITIALIZED;
964 286165 : } else if (feedback->IsWeakCell()) {
965 : // Don't check if the map is cleared.
966 : return MONOMORPHIC;
967 : }
968 :
969 22196 : return MEGAMORPHIC;
970 : }
971 :
972 506444 : void StoreDataPropertyInLiteralICNexus::ConfigureMonomorphic(
973 : Handle<Name> name, Handle<Map> receiver_map) {
974 506444 : Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
975 :
976 506444 : SetFeedback(*cell);
977 506444 : SetFeedbackExtra(*name);
978 506444 : }
979 :
980 0 : InlineCacheState CollectTypeProfileNexus::StateFromFeedback() const {
981 : Isolate* isolate = GetIsolate();
982 0 : Object* const feedback = GetFeedback();
983 :
984 0 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
985 : return UNINITIALIZED;
986 : }
987 0 : return MONOMORPHIC;
988 : }
989 :
990 : namespace {
991 :
992 80 : bool InList(Handle<ArrayList> types, Handle<String> type) {
993 235 : for (int i = 0; i < types->Length(); i++) {
994 : Object* obj = types->Get(i);
995 95 : if (String::cast(obj)->Equals(*type)) {
996 : return true;
997 : }
998 : }
999 : return false;
1000 : }
1001 : } // anonymous namespace
1002 :
1003 285 : void CollectTypeProfileNexus::Collect(Handle<String> type, int position) {
1004 : DCHECK_GE(position, 0);
1005 : Isolate* isolate = GetIsolate();
1006 :
1007 285 : Object* const feedback = GetFeedback();
1008 :
1009 : // Map source position to collection of types
1010 : Handle<UnseededNumberDictionary> types;
1011 :
1012 285 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
1013 85 : types = UnseededNumberDictionary::New(isolate, 1);
1014 : } else {
1015 : types = handle(UnseededNumberDictionary::cast(feedback));
1016 : }
1017 :
1018 : Handle<ArrayList> position_specific_types;
1019 :
1020 285 : int entry = types->FindEntry(position);
1021 285 : if (entry == UnseededNumberDictionary::kNotFound) {
1022 205 : position_specific_types = ArrayList::New(isolate, 1);
1023 : types = UnseededNumberDictionary::Set(
1024 410 : types, position, ArrayList::Add(position_specific_types, type));
1025 : } else {
1026 : DCHECK(types->ValueAt(entry)->IsArrayList());
1027 160 : position_specific_types = handle(ArrayList::cast(types->ValueAt(entry)));
1028 80 : if (!InList(position_specific_types, type)) { // Add type
1029 : types = UnseededNumberDictionary::Set(
1030 120 : types, position, ArrayList::Add(position_specific_types, type));
1031 : }
1032 : }
1033 285 : SetFeedback(*types);
1034 285 : }
1035 :
1036 285 : void CollectTypeProfileNexus::Clear() {
1037 285 : SetFeedback(*FeedbackVector::UninitializedSentinel(GetIsolate()));
1038 285 : }
1039 :
1040 150 : std::vector<int> CollectTypeProfileNexus::GetSourcePositions() const {
1041 : std::vector<int> source_positions;
1042 : Isolate* isolate = GetIsolate();
1043 :
1044 150 : Object* const feedback = GetFeedback();
1045 :
1046 150 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
1047 : return source_positions;
1048 : }
1049 :
1050 : Handle<UnseededNumberDictionary> types = Handle<UnseededNumberDictionary>(
1051 : UnseededNumberDictionary::cast(feedback), isolate);
1052 :
1053 1040 : for (int index = UnseededNumberDictionary::kElementsStartIndex;
1054 : index < types->length(); index += UnseededNumberDictionary::kEntrySize) {
1055 : int key_index = index + UnseededNumberDictionary::kEntryKeyIndex;
1056 : Object* key = types->get(key_index);
1057 440 : if (key->IsSmi()) {
1058 185 : int position = Smi::cast(key)->value();
1059 185 : source_positions.push_back(position);
1060 : }
1061 : }
1062 : return source_positions;
1063 : }
1064 :
1065 185 : std::vector<Handle<String>> CollectTypeProfileNexus::GetTypesForSourcePositions(
1066 : uint32_t position) const {
1067 : Isolate* isolate = GetIsolate();
1068 :
1069 185 : Object* const feedback = GetFeedback();
1070 : std::vector<Handle<String>> types_for_position;
1071 185 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
1072 : return types_for_position;
1073 : }
1074 :
1075 : Handle<UnseededNumberDictionary> types = Handle<UnseededNumberDictionary>(
1076 : UnseededNumberDictionary::cast(feedback), isolate);
1077 :
1078 : int entry = types->FindEntry(position);
1079 185 : if (entry == UnseededNumberDictionary::kNotFound) {
1080 : return types_for_position;
1081 : }
1082 : DCHECK(types->ValueAt(entry)->IsArrayList());
1083 : Handle<ArrayList> position_specific_types =
1084 185 : Handle<ArrayList>(ArrayList::cast(types->ValueAt(entry)));
1085 615 : for (int i = 0; i < position_specific_types->Length(); i++) {
1086 : Object* t = position_specific_types->Get(i);
1087 245 : types_for_position.push_back(Handle<String>(String::cast(t), isolate));
1088 : }
1089 :
1090 : return types_for_position;
1091 : }
1092 :
1093 : namespace {
1094 :
1095 0 : Handle<JSObject> ConvertToJSObject(Isolate* isolate,
1096 : Handle<UnseededNumberDictionary> feedback) {
1097 : Handle<JSObject> type_profile =
1098 0 : isolate->factory()->NewJSObject(isolate->object_function());
1099 :
1100 0 : for (int index = UnseededNumberDictionary::kElementsStartIndex;
1101 : index < feedback->length();
1102 : index += UnseededNumberDictionary::kEntrySize) {
1103 : int key_index = index + UnseededNumberDictionary::kEntryKeyIndex;
1104 : Object* key = feedback->get(key_index);
1105 0 : if (key->IsSmi()) {
1106 0 : int value_index = index + UnseededNumberDictionary::kEntryValueIndex;
1107 :
1108 : Handle<ArrayList> position_specific_types(
1109 : ArrayList::cast(feedback->get(value_index)));
1110 :
1111 : int position = Smi::ToInt(key);
1112 : JSObject::AddDataElement(
1113 : type_profile, position,
1114 : isolate->factory()->NewJSArrayWithElements(
1115 : ArrayList::Elements(position_specific_types)),
1116 0 : PropertyAttributes::NONE)
1117 0 : .ToHandleChecked();
1118 : }
1119 : }
1120 0 : return type_profile;
1121 : }
1122 : } // namespace
1123 :
1124 0 : JSObject* CollectTypeProfileNexus::GetTypeProfile() const {
1125 : Isolate* isolate = GetIsolate();
1126 :
1127 0 : Object* const feedback = GetFeedback();
1128 :
1129 0 : if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
1130 0 : return *isolate->factory()->NewJSObject(isolate->object_function());
1131 : }
1132 :
1133 : return *ConvertToJSObject(isolate,
1134 0 : handle(UnseededNumberDictionary::cast(feedback)));
1135 : }
1136 :
1137 : } // namespace internal
1138 : } // namespace v8
|