blob: bc2f1c288bce149d7c9bb705fe74a714d5a07671 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/type-feedback-vector.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/code-stubs.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008#include "src/ic/ic.h"
9#include "src/ic/ic-state.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/objects.h"
11#include "src/type-feedback-vector-inl.h"
12
13namespace v8 {
14namespace internal {
15
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017static bool IsPropertyNameFeedback(Object* feedback) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010018 if (feedback->IsString()) return true;
19 if (!feedback->IsSymbol()) return false;
20 Symbol* symbol = Symbol::cast(feedback);
21 Heap* heap = symbol->GetHeap();
22 return symbol != heap->uninitialized_symbol() &&
23 symbol != heap->premonomorphic_symbol() &&
24 symbol != heap->megamorphic_symbol();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040025}
26
27
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) {
29 return os << TypeFeedbackMetadata::Kind2String(kind);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040030}
31
32
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind(
34 FeedbackVectorSlot slot) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040035 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
36 int data = Smi::cast(get(index))->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037 return VectorICComputer::decode(data, slot.ToInt());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040038}
39
Ben Murdoch61f157c2016-09-16 13:49:30 +010040String* TypeFeedbackMetadata::GetName(FeedbackVectorSlot slot) const {
41 DCHECK(SlotRequiresName(GetKind(slot)));
42 FixedArray* names = FixedArray::cast(get(kNamesTableIndex));
43 // TODO(ishell): consider using binary search here or even Dictionary when we
44 // have more ICs with names.
45 Smi* key = Smi::FromInt(slot.ToInt());
46 for (int entry = 0; entry < names->length(); entry += kNameTableEntrySize) {
47 Object* current_key = names->get(entry + kNameTableSlotIndex);
48 if (current_key == key) {
49 Object* name = names->get(entry + kNameTableNameIndex);
50 DCHECK(name->IsString());
51 return String::cast(name);
52 }
53 }
54 UNREACHABLE();
55 return nullptr;
56}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040057
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
59 FeedbackVectorSlotKind kind) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040060 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
61 int data = Smi::cast(get(index))->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040063 set(index, Smi::FromInt(new_data));
64}
65
66
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
68 Isolate* isolate, const StaticFeedbackVectorSpec* spec);
69template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
70 Isolate* isolate, const FeedbackVectorSpec* spec);
71
72
Emily Bernierd0a1eb72015-03-24 16:35:39 -040073// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074template <typename Spec>
75Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
76 const Spec* spec) {
Ben Murdoch61f157c2016-09-16 13:49:30 +010077 Factory* factory = isolate->factory();
78
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000079 const int slot_count = spec->slots();
80 const int slot_kinds_length = VectorICComputer::word_count(slot_count);
81 const int length = slot_kinds_length + kReservedIndexCount;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082 if (length == kReservedIndexCount) {
Ben Murdoch61f157c2016-09-16 13:49:30 +010083 return Handle<TypeFeedbackMetadata>::cast(factory->empty_fixed_array());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040084 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085#ifdef DEBUG
86 for (int i = 0; i < slot_count;) {
87 FeedbackVectorSlotKind kind = spec->GetKind(i);
88 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
89 for (int j = 1; j < entry_size; j++) {
90 FeedbackVectorSlotKind kind = spec->GetKind(i + j);
91 DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind);
92 }
93 i += entry_size;
94 }
95#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096
Ben Murdoch61f157c2016-09-16 13:49:30 +010097 Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
99 // Fill the bit-vector part with zeros.
100 for (int i = 0; i < slot_kinds_length; i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400101 array->set(kReservedIndexCount + i, Smi::FromInt(0));
102 }
103
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104 Handle<TypeFeedbackMetadata> metadata =
105 Handle<TypeFeedbackMetadata>::cast(array);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100106
107 // Add names to NamesTable.
108 const int name_count = spec->name_count();
109
110 Handle<FixedArray> names =
111 name_count == 0
112 ? factory->empty_fixed_array()
113 : factory->NewFixedArray(name_count * kNameTableEntrySize);
114 int name_index = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 for (int i = 0; i < slot_count; i++) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100116 FeedbackVectorSlotKind kind = spec->GetKind(i);
117 metadata->SetKind(FeedbackVectorSlot(i), kind);
118 if (SlotRequiresName(kind)) {
119 Handle<String> name = spec->GetName(name_index);
120 DCHECK(!name.is_null());
121 int entry = name_index * kNameTableEntrySize;
122 names->set(entry + kNameTableSlotIndex, Smi::FromInt(i));
123 names->set(entry + kNameTableNameIndex, *name);
124 name_index++;
125 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100127 DCHECK_EQ(name_count, name_index);
128 metadata->set(kNamesTableIndex, *names);
129
130 // It's important that the TypeFeedbackMetadata have a COW map, since it's
131 // pointed to by both a SharedFunctionInfo and indirectly by closures through
132 // the TypeFeedbackVector. The serializer uses the COW map type to decide
133 // this object belongs in the startup snapshot and not the partial
134 // snapshot(s).
135 metadata->set_map(isolate->heap()->fixed_cow_array_map());
136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137 return metadata;
138}
139
140
141bool TypeFeedbackMetadata::SpecDiffersFrom(
142 const FeedbackVectorSpec* other_spec) const {
143 if (other_spec->slots() != slot_count()) {
144 return true;
145 }
146
147 int slots = slot_count();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100148 int name_index = 0;
149 for (int i = 0; i < slots;) {
150 FeedbackVectorSlot slot(i);
151 FeedbackVectorSlotKind kind = GetKind(slot);
152 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
153
154 if (kind != other_spec->GetKind(i)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 return true;
156 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100157 if (SlotRequiresName(kind)) {
158 String* name = GetName(slot);
159 DCHECK(name != GetHeap()->empty_string());
160 String* other_name = *other_spec->GetName(name_index++);
161 if (name != other_name) {
162 return true;
163 }
164 }
165 i += entry_size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166 }
167 return false;
168}
169
Ben Murdoch61f157c2016-09-16 13:49:30 +0100170bool TypeFeedbackMetadata::DiffersFrom(
171 const TypeFeedbackMetadata* other_metadata) const {
172 if (other_metadata->slot_count() != slot_count()) {
173 return true;
174 }
175
176 int slots = slot_count();
177 for (int i = 0; i < slots;) {
178 FeedbackVectorSlot slot(i);
179 FeedbackVectorSlotKind kind = GetKind(slot);
180 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
181 if (GetKind(slot) != other_metadata->GetKind(slot)) {
182 return true;
183 }
184 if (SlotRequiresName(kind)) {
185 if (GetName(slot) != other_metadata->GetName(slot)) {
186 return true;
187 }
188 }
189 i += entry_size;
190 }
191 return false;
192}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193
194const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) {
195 switch (kind) {
196 case FeedbackVectorSlotKind::INVALID:
197 return "INVALID";
198 case FeedbackVectorSlotKind::CALL_IC:
199 return "CALL_IC";
200 case FeedbackVectorSlotKind::LOAD_IC:
201 return "LOAD_IC";
Ben Murdoch61f157c2016-09-16 13:49:30 +0100202 case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
203 return "LOAD_GLOBAL_IC";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 case FeedbackVectorSlotKind::KEYED_LOAD_IC:
205 return "KEYED_LOAD_IC";
206 case FeedbackVectorSlotKind::STORE_IC:
207 return "STORE_IC";
208 case FeedbackVectorSlotKind::KEYED_STORE_IC:
209 return "KEYED_STORE_IC";
210 case FeedbackVectorSlotKind::GENERAL:
211 return "STUB";
212 case FeedbackVectorSlotKind::KINDS_NUMBER:
213 break;
214 }
215 UNREACHABLE();
216 return "?";
217}
218
Ben Murdoch61f157c2016-09-16 13:49:30 +0100219FeedbackVectorSlotKind TypeFeedbackVector::GetKind(
220 FeedbackVectorSlot slot) const {
221 DCHECK(!is_empty());
222 return metadata()->GetKind(slot);
223}
224
225String* TypeFeedbackVector::GetName(FeedbackVectorSlot slot) const {
226 DCHECK(!is_empty());
227 return metadata()->GetName(slot);
228}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229
230// static
231Handle<TypeFeedbackVector> TypeFeedbackVector::New(
232 Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) {
233 Factory* factory = isolate->factory();
234
235 const int slot_count = metadata->slot_count();
236 const int length = slot_count + kReservedIndexCount;
237 if (length == kReservedIndexCount) {
238 return Handle<TypeFeedbackVector>::cast(factory->empty_fixed_array());
239 }
240
241 Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
242 array->set(kMetadataIndex, *metadata);
243
Ben Murdoch61f157c2016-09-16 13:49:30 +0100244 DisallowHeapAllocation no_gc;
245
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400246 // Ensure we can skip the write barrier
247 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100249 for (int i = 0; i < slot_count;) {
250 FeedbackVectorSlot slot(i);
251 FeedbackVectorSlotKind kind = metadata->GetKind(slot);
252 int index = TypeFeedbackVector::GetIndex(slot);
253 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400254
Ben Murdoch61f157c2016-09-16 13:49:30 +0100255 Object* value;
256 if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) {
257 value = *factory->empty_weak_cell();
258 } else {
259 value = *uninitialized_sentinel;
260 }
261 array->set(index, value, SKIP_WRITE_BARRIER);
262 for (int j = 1; j < entry_size; j++) {
263 array->set(index + j, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
264 }
265 i += entry_size;
266 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 return Handle<TypeFeedbackVector>::cast(array);
268}
269
270
271// static
272int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec,
273 FeedbackVectorSlot slot) {
274 return kReservedIndexCount + slot.ToInt();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400275}
276
277
278// static
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279Handle<TypeFeedbackVector> TypeFeedbackVector::Copy(
280 Isolate* isolate, Handle<TypeFeedbackVector> vector) {
281 Handle<TypeFeedbackVector> result;
282 result = Handle<TypeFeedbackVector>::cast(
283 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
284 return result;
285}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400286
287
288// This logic is copied from
289// StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290static bool ClearLogic(Isolate* isolate) {
291 return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400292}
293
294
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
296 bool force_clear) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400297 Isolate* isolate = GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298
299 if (!force_clear && !ClearLogic(isolate)) return;
300
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400301 Object* uninitialized_sentinel =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302 TypeFeedbackVector::RawUninitializedSentinel(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400303
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 TypeFeedbackMetadataIterator iter(metadata());
305 while (iter.HasNext()) {
306 FeedbackVectorSlot slot = iter.Next();
307 FeedbackVectorSlotKind kind = iter.kind();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400308
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400309 Object* obj = Get(slot);
310 if (obj != uninitialized_sentinel) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 switch (kind) {
312 case FeedbackVectorSlotKind::CALL_IC: {
313 CallICNexus nexus(this, slot);
314 nexus.Clear(shared->code());
315 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400316 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 case FeedbackVectorSlotKind::LOAD_IC: {
318 LoadICNexus nexus(this, slot);
319 nexus.Clear(shared->code());
320 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400321 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100322 case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: {
323 LoadGlobalICNexus nexus(this, slot);
324 nexus.Clear(shared->code());
325 break;
326 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
328 KeyedLoadICNexus nexus(this, slot);
329 nexus.Clear(shared->code());
330 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400331 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332 case FeedbackVectorSlotKind::STORE_IC: {
333 StoreICNexus nexus(this, slot);
334 nexus.Clear(shared->code());
335 break;
336 }
337 case FeedbackVectorSlotKind::KEYED_STORE_IC: {
338 KeyedStoreICNexus nexus(this, slot);
339 nexus.Clear(shared->code());
340 break;
341 }
342 case FeedbackVectorSlotKind::GENERAL: {
343 if (obj->IsHeapObject()) {
344 InstanceType instance_type =
345 HeapObject::cast(obj)->map()->instance_type();
346 // AllocationSites are exempt from clearing. They don't store Maps
347 // or Code pointers which can cause memory leaks if not cleared
348 // regularly.
349 if (instance_type != ALLOCATION_SITE_TYPE) {
350 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER);
351 }
352 }
353 break;
354 }
355 case FeedbackVectorSlotKind::INVALID:
356 case FeedbackVectorSlotKind::KINDS_NUMBER:
357 UNREACHABLE();
358 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400359 }
360 }
361 }
362}
363
364
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000365// static
366void TypeFeedbackVector::ClearAllKeyedStoreICs(Isolate* isolate) {
367 SharedFunctionInfo::Iterator iterator(isolate);
368 SharedFunctionInfo* shared;
369 while ((shared = iterator.Next())) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100370 if (!shared->OptimizedCodeMapIsCleared()) {
371 FixedArray* optimized_code_map = shared->optimized_code_map();
372 int length = optimized_code_map->length();
373 for (int i = SharedFunctionInfo::kEntriesStart; i < length;
374 i += SharedFunctionInfo::kEntryLength) {
375 Object* lits =
376 optimized_code_map->get(i + SharedFunctionInfo::kLiteralsOffset);
377 TypeFeedbackVector* vector = nullptr;
378 if (lits->IsWeakCell()) {
379 WeakCell* cell = WeakCell::cast(lits);
380 if (cell->value()->IsLiteralsArray()) {
381 vector = LiteralsArray::cast(cell->value())->feedback_vector();
382 }
383 } else {
384 DCHECK(lits->IsLiteralsArray());
385 vector = LiteralsArray::cast(lits)->feedback_vector();
386 }
387 if (vector != nullptr) {
388 vector->ClearKeyedStoreICs(shared);
389 }
390 }
391 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 }
393}
394
395
396void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) {
397 Isolate* isolate = GetIsolate();
398
399 Code* host = shared->code();
400 Object* uninitialized_sentinel =
401 TypeFeedbackVector::RawUninitializedSentinel(isolate);
402
403 TypeFeedbackMetadataIterator iter(metadata());
404 while (iter.HasNext()) {
405 FeedbackVectorSlot slot = iter.Next();
406 FeedbackVectorSlotKind kind = iter.kind();
407 if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue;
408 Object* obj = Get(slot);
409 if (obj != uninitialized_sentinel) {
410 KeyedStoreICNexus nexus(this, slot);
411 nexus.Clear(host);
412 }
413 }
414}
415
416
417// static
418Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) {
419 return isolate->factory()->dummy_vector();
420}
421
422
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400423Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
424 Isolate* isolate = GetIsolate();
425 Handle<Object> feedback = handle(GetFeedback(), isolate);
426 if (!feedback->IsFixedArray() ||
427 FixedArray::cast(*feedback)->length() != length) {
428 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
429 SetFeedback(*array);
430 return array;
431 }
432 return Handle<FixedArray>::cast(feedback);
433}
434
435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400437 Isolate* isolate = GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438 Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate);
439 if (!feedback_extra->IsFixedArray() ||
440 FixedArray::cast(*feedback_extra)->length() != length) {
441 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
442 SetFeedbackExtra(*array);
443 return array;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400444 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445 return Handle<FixedArray>::cast(feedback_extra);
446}
447
448
449void FeedbackNexus::InstallHandlers(Handle<FixedArray> array,
450 MapHandleList* maps,
451 CodeHandleList* handlers) {
452 int receiver_count = maps->length();
453 for (int current = 0; current < receiver_count; ++current) {
454 Handle<Map> map = maps->at(current);
455 Handle<WeakCell> cell = Map::WeakCellForMap(map);
456 array->set(current * 2, *cell);
457 array->set(current * 2 + 1, *handlers->at(current));
458 }
459}
460
461
462void FeedbackNexus::ConfigureUninitialized() {
463 SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
464 SKIP_WRITE_BARRIER);
465 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
466 SKIP_WRITE_BARRIER);
467}
468
469
470void FeedbackNexus::ConfigurePremonomorphic() {
471 SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()),
472 SKIP_WRITE_BARRIER);
473 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
474 SKIP_WRITE_BARRIER);
475}
476
477
478void FeedbackNexus::ConfigureMegamorphic() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100479 // Keyed ICs must use ConfigureMegamorphicKeyed.
480 DCHECK_NE(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector()->GetKind(slot()));
481 DCHECK_NE(FeedbackVectorSlotKind::KEYED_STORE_IC, vector()->GetKind(slot()));
482
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483 Isolate* isolate = GetIsolate();
484 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
485 SKIP_WRITE_BARRIER);
486 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
487 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400488}
489
Ben Murdoch097c5b22016-05-18 11:27:45 +0100490void KeyedLoadICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) {
491 Isolate* isolate = GetIsolate();
492 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
493 SKIP_WRITE_BARRIER);
494 SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
495 SKIP_WRITE_BARRIER);
496}
497
498void KeyedStoreICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) {
499 Isolate* isolate = GetIsolate();
500 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
501 SKIP_WRITE_BARRIER);
502 SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
503 SKIP_WRITE_BARRIER);
504}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400505
506InlineCacheState LoadICNexus::StateFromFeedback() const {
507 Isolate* isolate = GetIsolate();
508 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509
510 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400511 return UNINITIALIZED;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400513 return MEGAMORPHIC;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000514 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400515 return PREMONOMORPHIC;
516 } else if (feedback->IsFixedArray()) {
517 // Determine state purely by our structure, don't check if the maps are
518 // cleared.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519 return POLYMORPHIC;
520 } else if (feedback->IsWeakCell()) {
521 // Don't check if the map is cleared.
522 return MONOMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400523 }
524
525 return UNINITIALIZED;
526}
527
Ben Murdoch61f157c2016-09-16 13:49:30 +0100528InlineCacheState LoadGlobalICNexus::StateFromFeedback() const {
529 Isolate* isolate = GetIsolate();
530 Object* feedback = GetFeedback();
531
532 Object* extra = GetFeedbackExtra();
533 if (!WeakCell::cast(feedback)->cleared() ||
534 extra != *TypeFeedbackVector::UninitializedSentinel(isolate)) {
535 return MONOMORPHIC;
536 }
537 return UNINITIALIZED;
538}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400539
540InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
541 Isolate* isolate = GetIsolate();
542 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000543
544 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400545 return UNINITIALIZED;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400547 return PREMONOMORPHIC;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000548 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
549 return MEGAMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400550 } else if (feedback->IsFixedArray()) {
551 // Determine state purely by our structure, don't check if the maps are
552 // cleared.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000553 return POLYMORPHIC;
554 } else if (feedback->IsWeakCell()) {
555 // Don't check if the map is cleared.
556 return MONOMORPHIC;
557 } else if (feedback->IsName()) {
558 Object* extra = GetFeedbackExtra();
559 FixedArray* extra_array = FixedArray::cast(extra);
560 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
561 }
562
563 return UNINITIALIZED;
564}
565
566
567InlineCacheState StoreICNexus::StateFromFeedback() const {
568 Isolate* isolate = GetIsolate();
569 Object* feedback = GetFeedback();
570
571 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
572 return UNINITIALIZED;
573 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
574 return MEGAMORPHIC;
575 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
576 return PREMONOMORPHIC;
577 } else if (feedback->IsFixedArray()) {
578 // Determine state purely by our structure, don't check if the maps are
579 // cleared.
580 return POLYMORPHIC;
581 } else if (feedback->IsWeakCell()) {
582 // Don't check if the map is cleared.
583 return MONOMORPHIC;
584 }
585
586 return UNINITIALIZED;
587}
588
589
590InlineCacheState KeyedStoreICNexus::StateFromFeedback() const {
591 Isolate* isolate = GetIsolate();
592 Object* feedback = GetFeedback();
593
594 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
595 return UNINITIALIZED;
596 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
597 return PREMONOMORPHIC;
598 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
599 return MEGAMORPHIC;
600 } else if (feedback->IsFixedArray()) {
601 // Determine state purely by our structure, don't check if the maps are
602 // cleared.
603 return POLYMORPHIC;
604 } else if (feedback->IsWeakCell()) {
605 // Don't check if the map is cleared.
606 return MONOMORPHIC;
607 } else if (feedback->IsName()) {
608 Object* extra = GetFeedbackExtra();
609 FixedArray* extra_array = FixedArray::cast(extra);
610 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400611 }
612
613 return UNINITIALIZED;
614}
615
616
617InlineCacheState CallICNexus::StateFromFeedback() const {
618 Isolate* isolate = GetIsolate();
619 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 DCHECK(GetFeedbackExtra() ==
621 *TypeFeedbackVector::UninitializedSentinel(isolate) ||
622 GetFeedbackExtra()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400623
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400625 return GENERIC;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000626 } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400627 return MONOMORPHIC;
628 }
629
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630 CHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400631 return UNINITIALIZED;
632}
633
634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635int CallICNexus::ExtractCallCount() {
636 Object* call_count = GetFeedbackExtra();
637 if (call_count->IsSmi()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100638 int value = Smi::cast(call_count)->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000639 return value;
640 }
641 return -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400642}
643
644
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
646
647
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400648void CallICNexus::ConfigureMonomorphicArray() {
649 Object* feedback = GetFeedback();
650 if (!feedback->IsAllocationSite()) {
651 Handle<AllocationSite> new_site =
652 GetIsolate()->factory()->NewAllocationSite();
653 SetFeedback(*new_site);
654 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100655 SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400656}
657
658
659void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000660 Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function);
661 SetFeedback(*new_cell);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100662 SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400663}
664
665
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666void CallICNexus::ConfigureMegamorphic() {
667 FeedbackNexus::ConfigureMegamorphic();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400668}
669
670
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000671void CallICNexus::ConfigureMegamorphic(int call_count) {
672 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400673 SKIP_WRITE_BARRIER);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100674 SetFeedbackExtra(Smi::FromInt(call_count), SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400675}
676
677
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000678void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400679 Handle<Code> handler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400680 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000681 SetFeedback(*cell);
682 SetFeedbackExtra(*handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400683}
684
Ben Murdoch61f157c2016-09-16 13:49:30 +0100685void LoadGlobalICNexus::ConfigureUninitialized() {
686 Isolate* isolate = GetIsolate();
687 SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER);
688 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
689 SKIP_WRITE_BARRIER);
690}
691
692void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
693 Isolate* isolate = GetIsolate();
694 SetFeedback(*isolate->factory()->NewWeakCell(cell));
695 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
696 SKIP_WRITE_BARRIER);
697}
698
699void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Code> handler) {
700 SetFeedback(GetIsolate()->heap()->empty_weak_cell());
701 SetFeedbackExtra(*handler);
702}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703
704void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000705 Handle<Map> receiver_map,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400706 Handle<Code> handler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400707 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000708 if (name.is_null()) {
709 SetFeedback(*cell);
710 SetFeedbackExtra(*handler);
711 } else {
712 Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
713 SetFeedback(*name);
714 array->set(0, *cell);
715 array->set(1, *handler);
716 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400717}
718
719
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
721 Handle<Code> handler) {
722 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
723 SetFeedback(*cell);
724 SetFeedbackExtra(*handler);
725}
726
727
728void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name,
729 Handle<Map> receiver_map,
730 Handle<Code> handler) {
731 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
732 if (name.is_null()) {
733 SetFeedback(*cell);
734 SetFeedbackExtra(*handler);
735 } else {
736 Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
737 SetFeedback(*name);
738 array->set(0, *cell);
739 array->set(1, *handler);
740 }
741}
742
743
744void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400745 CodeHandleList* handlers) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000746 Isolate* isolate = GetIsolate();
747 int receiver_count = maps->length();
748 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
749 InstallHandlers(array, maps, handlers);
750 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
751 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400752}
753
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400754void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000755 MapHandleList* maps,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400756 CodeHandleList* handlers) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 int receiver_count = maps->length();
758 DCHECK(receiver_count > 1);
759 Handle<FixedArray> array;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400760 if (name.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000761 array = EnsureArrayOfSize(receiver_count * 2);
762 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
763 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400764 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765 array = EnsureExtraArrayOfSize(receiver_count * 2);
766 SetFeedback(*name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400767 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768
769 InstallHandlers(array, maps, handlers);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400770}
771
772
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
774 CodeHandleList* handlers) {
775 Isolate* isolate = GetIsolate();
776 int receiver_count = maps->length();
777 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
778 InstallHandlers(array, maps, handlers);
779 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
780 SKIP_WRITE_BARRIER);
781}
782
783
784void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
785 MapHandleList* maps,
786 CodeHandleList* handlers) {
787 int receiver_count = maps->length();
788 DCHECK(receiver_count > 1);
789 Handle<FixedArray> array;
790 if (name.is_null()) {
791 array = EnsureArrayOfSize(receiver_count * 2);
792 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
793 SKIP_WRITE_BARRIER);
794 } else {
795 array = EnsureExtraArrayOfSize(receiver_count * 2);
796 SetFeedback(*name);
797 }
798
799 InstallHandlers(array, maps, handlers);
800}
801
802
803void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
804 MapHandleList* transitioned_maps,
805 CodeHandleList* handlers) {
806 int receiver_count = maps->length();
807 DCHECK(receiver_count > 1);
808 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3);
809 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
810 SKIP_WRITE_BARRIER);
811
812 Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value();
813 for (int i = 0; i < receiver_count; ++i) {
814 Handle<Map> map = maps->at(i);
815 Handle<WeakCell> cell = Map::WeakCellForMap(map);
816 array->set(i * 3, *cell);
817 if (!transitioned_maps->at(i).is_null()) {
818 Handle<Map> transitioned_map = transitioned_maps->at(i);
819 cell = Map::WeakCellForMap(transitioned_map);
820 array->set((i * 3) + 1, *cell);
821 } else {
822 array->set((i * 3) + 1, *undefined_value);
823 }
824 array->set((i * 3) + 2, *handlers->at(i));
825 }
826}
827
828
829int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400830 Isolate* isolate = GetIsolate();
831 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000832 bool is_named_feedback = IsPropertyNameFeedback(feedback);
833 if (feedback->IsFixedArray() || is_named_feedback) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400834 int found = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 if (is_named_feedback) {
836 feedback = GetFeedbackExtra();
837 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400838 FixedArray* array = FixedArray::cast(feedback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000839 // The array should be of the form
840 // [map, handler, map, handler, ...]
841 // or
842 // [map, map, handler, map, map, handler, ...]
843 DCHECK(array->length() >= 2);
844 int increment = array->get(1)->IsCode() ? 2 : 3;
845 for (int i = 0; i < array->length(); i += increment) {
846 DCHECK(array->get(i)->IsWeakCell());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400847 WeakCell* cell = WeakCell::cast(array->get(i));
848 if (!cell->cleared()) {
849 Map* map = Map::cast(cell->value());
850 maps->Add(handle(map, isolate));
851 found++;
852 }
853 }
854 return found;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000855 } else if (feedback->IsWeakCell()) {
856 WeakCell* cell = WeakCell::cast(feedback);
857 if (!cell->cleared()) {
858 Map* map = Map::cast(cell->value());
859 maps->Add(handle(map, isolate));
860 return 1;
861 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400862 }
863
864 return 0;
865}
866
867
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000868MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400869 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 bool is_named_feedback = IsPropertyNameFeedback(feedback);
871 if (feedback->IsFixedArray() || is_named_feedback) {
872 if (is_named_feedback) {
873 feedback = GetFeedbackExtra();
874 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400875 FixedArray* array = FixedArray::cast(feedback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 DCHECK(array->length() >= 2);
877 int increment = array->get(1)->IsCode() ? 2 : 3;
878 for (int i = 0; i < array->length(); i += increment) {
879 DCHECK(array->get(i)->IsWeakCell());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400880 WeakCell* cell = WeakCell::cast(array->get(i));
881 if (!cell->cleared()) {
882 Map* array_map = Map::cast(cell->value());
883 if (array_map == *map) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884 Code* code = Code::cast(array->get(i + increment - 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400885 DCHECK(code->kind() == Code::HANDLER);
886 return handle(code);
887 }
888 }
889 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000890 } else if (feedback->IsWeakCell()) {
891 WeakCell* cell = WeakCell::cast(feedback);
892 if (!cell->cleared()) {
893 Map* cell_map = Map::cast(cell->value());
894 if (cell_map == *map) {
895 Code* code = Code::cast(GetFeedbackExtra());
896 DCHECK(code->kind() == Code::HANDLER);
897 return handle(code);
898 }
899 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400900 }
901
902 return MaybeHandle<Code>();
903}
904
905
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400907 Object* feedback = GetFeedback();
908 int count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000909 bool is_named_feedback = IsPropertyNameFeedback(feedback);
910 if (feedback->IsFixedArray() || is_named_feedback) {
911 if (is_named_feedback) {
912 feedback = GetFeedbackExtra();
913 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400914 FixedArray* array = FixedArray::cast(feedback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000915 // The array should be of the form
916 // [map, handler, map, handler, ...]
917 // or
918 // [map, map, handler, map, map, handler, ...]
919 // Be sure to skip handlers whose maps have been cleared.
920 DCHECK(array->length() >= 2);
921 int increment = array->get(1)->IsCode() ? 2 : 3;
922 for (int i = 0; i < array->length(); i += increment) {
923 DCHECK(array->get(i)->IsWeakCell());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400924 WeakCell* cell = WeakCell::cast(array->get(i));
925 if (!cell->cleared()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926 Code* code = Code::cast(array->get(i + increment - 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400927 DCHECK(code->kind() == Code::HANDLER);
928 code_list->Add(handle(code));
929 count++;
930 }
931 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 } else if (feedback->IsWeakCell()) {
933 WeakCell* cell = WeakCell::cast(feedback);
934 if (!cell->cleared()) {
935 Code* code = Code::cast(GetFeedbackExtra());
936 DCHECK(code->kind() == Code::HANDLER);
937 code_list->Add(handle(code));
938 count++;
939 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400940 }
941 return count == length;
942}
943
944
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400945void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
946
Ben Murdoch61f157c2016-09-16 13:49:30 +0100947void LoadGlobalICNexus::Clear(Code* host) {
948 LoadGlobalIC::Clear(GetIsolate(), host, this);
949}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400950
951void KeyedLoadICNexus::Clear(Code* host) {
952 KeyedLoadIC::Clear(GetIsolate(), host, this);
953}
954
955
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400956Name* KeyedLoadICNexus::FindFirstName() const {
957 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000958 if (IsPropertyNameFeedback(feedback)) {
959 return Name::cast(feedback);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400960 }
961 return NULL;
962}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000963
964
965Name* KeyedStoreICNexus::FindFirstName() const {
966 Object* feedback = GetFeedback();
967 if (IsPropertyNameFeedback(feedback)) {
968 return Name::cast(feedback);
969 }
970 return NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000971}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972
973
974void StoreICNexus::Clear(Code* host) {
975 StoreIC::Clear(GetIsolate(), host, this);
976}
977
978
979void KeyedStoreICNexus::Clear(Code* host) {
980 KeyedStoreIC::Clear(GetIsolate(), host, this);
981}
982
983
984KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
985 KeyedAccessStoreMode mode = STANDARD_STORE;
986 MapHandleList maps;
987 CodeHandleList handlers;
988
989 if (GetKeyType() == PROPERTY) return mode;
990
991 ExtractMaps(&maps);
992 FindHandlers(&handlers, maps.length());
993 for (int i = 0; i < handlers.length(); i++) {
994 // The first handler that isn't the slow handler will have the bits we need.
995 Handle<Code> handler = handlers.at(i);
996 CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
997 uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
998 CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
999 major_key == CodeStub::StoreFastElement ||
1000 major_key == CodeStub::StoreElement ||
1001 major_key == CodeStub::ElementsTransitionAndStore ||
1002 major_key == CodeStub::NoCache);
1003 if (major_key != CodeStub::NoCache) {
1004 mode = CommonStoreModeBits::decode(minor_key);
1005 break;
1006 }
1007 }
1008
1009 return mode;
1010}
1011
Ben Murdoch097c5b22016-05-18 11:27:45 +01001012IcCheckType KeyedLoadICNexus::GetKeyType() const {
1013 Object* feedback = GetFeedback();
1014 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) {
1015 return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value());
1016 }
1017 return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
1018}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019
1020IcCheckType KeyedStoreICNexus::GetKeyType() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001021 Object* feedback = GetFeedback();
1022 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) {
1023 return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value());
1024 }
1025 return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001026}
1027} // namespace internal
1028} // namespace v8