blob: 4519bd65c2c2d79ae6989049d7f1d70070577f07 [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
40
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
42 FeedbackVectorSlotKind kind) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040043 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
44 int data = Smi::cast(get(index))->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040046 set(index, Smi::FromInt(new_data));
47}
48
49
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
51 Isolate* isolate, const StaticFeedbackVectorSpec* spec);
52template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
53 Isolate* isolate, const FeedbackVectorSpec* spec);
54
55
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000057template <typename Spec>
58Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
59 const Spec* spec) {
60 const int slot_count = spec->slots();
61 const int slot_kinds_length = VectorICComputer::word_count(slot_count);
62 const int length = slot_kinds_length + kReservedIndexCount;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040063 if (length == kReservedIndexCount) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 return Handle<TypeFeedbackMetadata>::cast(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040065 isolate->factory()->empty_fixed_array());
66 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067#ifdef DEBUG
68 for (int i = 0; i < slot_count;) {
69 FeedbackVectorSlotKind kind = spec->GetKind(i);
70 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
71 for (int j = 1; j < entry_size; j++) {
72 FeedbackVectorSlotKind kind = spec->GetKind(i + j);
73 DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind);
74 }
75 i += entry_size;
76 }
77#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040078
79 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080 array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
81 // Fill the bit-vector part with zeros.
82 for (int i = 0; i < slot_kinds_length; i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083 array->set(kReservedIndexCount + i, Smi::FromInt(0));
84 }
85
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086 Handle<TypeFeedbackMetadata> metadata =
87 Handle<TypeFeedbackMetadata>::cast(array);
88 for (int i = 0; i < slot_count; i++) {
89 metadata->SetKind(FeedbackVectorSlot(i), spec->GetKind(i));
90 }
91 return metadata;
92}
93
94
95bool TypeFeedbackMetadata::SpecDiffersFrom(
96 const FeedbackVectorSpec* other_spec) const {
97 if (other_spec->slots() != slot_count()) {
98 return true;
99 }
100
101 int slots = slot_count();
102 for (int i = 0; i < slots; i++) {
103 if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) {
104 return true;
105 }
106 }
107 return false;
108}
109
110
111const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) {
112 switch (kind) {
113 case FeedbackVectorSlotKind::INVALID:
114 return "INVALID";
115 case FeedbackVectorSlotKind::CALL_IC:
116 return "CALL_IC";
117 case FeedbackVectorSlotKind::LOAD_IC:
118 return "LOAD_IC";
119 case FeedbackVectorSlotKind::KEYED_LOAD_IC:
120 return "KEYED_LOAD_IC";
121 case FeedbackVectorSlotKind::STORE_IC:
122 return "STORE_IC";
123 case FeedbackVectorSlotKind::KEYED_STORE_IC:
124 return "KEYED_STORE_IC";
125 case FeedbackVectorSlotKind::GENERAL:
126 return "STUB";
127 case FeedbackVectorSlotKind::KINDS_NUMBER:
128 break;
129 }
130 UNREACHABLE();
131 return "?";
132}
133
134
135// static
136Handle<TypeFeedbackVector> TypeFeedbackVector::New(
137 Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) {
138 Factory* factory = isolate->factory();
139
140 const int slot_count = metadata->slot_count();
141 const int length = slot_count + kReservedIndexCount;
142 if (length == kReservedIndexCount) {
143 return Handle<TypeFeedbackVector>::cast(factory->empty_fixed_array());
144 }
145
146 Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
147 array->set(kMetadataIndex, *metadata);
148
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400149 // Ensure we can skip the write barrier
150 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel);
152 for (int i = kReservedIndexCount; i < length; i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400153 array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
154 }
155
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 return Handle<TypeFeedbackVector>::cast(array);
157}
158
159
160// static
161int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec,
162 FeedbackVectorSlot slot) {
163 return kReservedIndexCount + slot.ToInt();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400164}
165
166
167// static
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168Handle<TypeFeedbackVector> TypeFeedbackVector::Copy(
169 Isolate* isolate, Handle<TypeFeedbackVector> vector) {
170 Handle<TypeFeedbackVector> result;
171 result = Handle<TypeFeedbackVector>::cast(
172 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
173 return result;
174}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400175
176
177// This logic is copied from
178// StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179static bool ClearLogic(Isolate* isolate) {
180 return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400181}
182
183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
185 bool force_clear) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186 Isolate* isolate = GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187
188 if (!force_clear && !ClearLogic(isolate)) return;
189
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400190 Object* uninitialized_sentinel =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 TypeFeedbackVector::RawUninitializedSentinel(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 TypeFeedbackMetadataIterator iter(metadata());
194 while (iter.HasNext()) {
195 FeedbackVectorSlot slot = iter.Next();
196 FeedbackVectorSlotKind kind = iter.kind();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400197
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400198 Object* obj = Get(slot);
199 if (obj != uninitialized_sentinel) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 switch (kind) {
201 case FeedbackVectorSlotKind::CALL_IC: {
202 CallICNexus nexus(this, slot);
203 nexus.Clear(shared->code());
204 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400205 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 case FeedbackVectorSlotKind::LOAD_IC: {
207 LoadICNexus nexus(this, slot);
208 nexus.Clear(shared->code());
209 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400210 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
212 KeyedLoadICNexus nexus(this, slot);
213 nexus.Clear(shared->code());
214 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400215 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 case FeedbackVectorSlotKind::STORE_IC: {
217 StoreICNexus nexus(this, slot);
218 nexus.Clear(shared->code());
219 break;
220 }
221 case FeedbackVectorSlotKind::KEYED_STORE_IC: {
222 KeyedStoreICNexus nexus(this, slot);
223 nexus.Clear(shared->code());
224 break;
225 }
226 case FeedbackVectorSlotKind::GENERAL: {
227 if (obj->IsHeapObject()) {
228 InstanceType instance_type =
229 HeapObject::cast(obj)->map()->instance_type();
230 // AllocationSites are exempt from clearing. They don't store Maps
231 // or Code pointers which can cause memory leaks if not cleared
232 // regularly.
233 if (instance_type != ALLOCATION_SITE_TYPE) {
234 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER);
235 }
236 }
237 break;
238 }
239 case FeedbackVectorSlotKind::INVALID:
240 case FeedbackVectorSlotKind::KINDS_NUMBER:
241 UNREACHABLE();
242 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400243 }
244 }
245 }
246}
247
248
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249// static
250void TypeFeedbackVector::ClearAllKeyedStoreICs(Isolate* isolate) {
251 SharedFunctionInfo::Iterator iterator(isolate);
252 SharedFunctionInfo* shared;
253 while ((shared = iterator.Next())) {
254 TypeFeedbackVector* vector = shared->feedback_vector();
255 vector->ClearKeyedStoreICs(shared);
256 }
257}
258
259
260void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) {
261 Isolate* isolate = GetIsolate();
262
263 Code* host = shared->code();
264 Object* uninitialized_sentinel =
265 TypeFeedbackVector::RawUninitializedSentinel(isolate);
266
267 TypeFeedbackMetadataIterator iter(metadata());
268 while (iter.HasNext()) {
269 FeedbackVectorSlot slot = iter.Next();
270 FeedbackVectorSlotKind kind = iter.kind();
271 if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue;
272 Object* obj = Get(slot);
273 if (obj != uninitialized_sentinel) {
274 KeyedStoreICNexus nexus(this, slot);
275 nexus.Clear(host);
276 }
277 }
278}
279
280
281// static
282Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) {
283 return isolate->factory()->dummy_vector();
284}
285
286
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400287Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
288 Isolate* isolate = GetIsolate();
289 Handle<Object> feedback = handle(GetFeedback(), isolate);
290 if (!feedback->IsFixedArray() ||
291 FixedArray::cast(*feedback)->length() != length) {
292 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
293 SetFeedback(*array);
294 return array;
295 }
296 return Handle<FixedArray>::cast(feedback);
297}
298
299
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000300Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400301 Isolate* isolate = GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302 Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate);
303 if (!feedback_extra->IsFixedArray() ||
304 FixedArray::cast(*feedback_extra)->length() != length) {
305 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
306 SetFeedbackExtra(*array);
307 return array;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400308 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 return Handle<FixedArray>::cast(feedback_extra);
310}
311
312
313void FeedbackNexus::InstallHandlers(Handle<FixedArray> array,
314 MapHandleList* maps,
315 CodeHandleList* handlers) {
316 int receiver_count = maps->length();
317 for (int current = 0; current < receiver_count; ++current) {
318 Handle<Map> map = maps->at(current);
319 Handle<WeakCell> cell = Map::WeakCellForMap(map);
320 array->set(current * 2, *cell);
321 array->set(current * 2 + 1, *handlers->at(current));
322 }
323}
324
325
326void FeedbackNexus::ConfigureUninitialized() {
327 SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
328 SKIP_WRITE_BARRIER);
329 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
330 SKIP_WRITE_BARRIER);
331}
332
333
334void FeedbackNexus::ConfigurePremonomorphic() {
335 SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()),
336 SKIP_WRITE_BARRIER);
337 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
338 SKIP_WRITE_BARRIER);
339}
340
341
342void FeedbackNexus::ConfigureMegamorphic() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100343 // Keyed ICs must use ConfigureMegamorphicKeyed.
344 DCHECK_NE(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector()->GetKind(slot()));
345 DCHECK_NE(FeedbackVectorSlotKind::KEYED_STORE_IC, vector()->GetKind(slot()));
346
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347 Isolate* isolate = GetIsolate();
348 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
349 SKIP_WRITE_BARRIER);
350 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
351 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400352}
353
Ben Murdoch097c5b22016-05-18 11:27:45 +0100354void KeyedLoadICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) {
355 Isolate* isolate = GetIsolate();
356 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
357 SKIP_WRITE_BARRIER);
358 SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
359 SKIP_WRITE_BARRIER);
360}
361
362void KeyedStoreICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) {
363 Isolate* isolate = GetIsolate();
364 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
365 SKIP_WRITE_BARRIER);
366 SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
367 SKIP_WRITE_BARRIER);
368}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400369
370InlineCacheState LoadICNexus::StateFromFeedback() const {
371 Isolate* isolate = GetIsolate();
372 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373
374 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400375 return UNINITIALIZED;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000376 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400377 return MEGAMORPHIC;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000378 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400379 return PREMONOMORPHIC;
380 } else if (feedback->IsFixedArray()) {
381 // Determine state purely by our structure, don't check if the maps are
382 // cleared.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 return POLYMORPHIC;
384 } else if (feedback->IsWeakCell()) {
385 // Don't check if the map is cleared.
386 return MONOMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400387 }
388
389 return UNINITIALIZED;
390}
391
392
393InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
394 Isolate* isolate = GetIsolate();
395 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396
397 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400398 return UNINITIALIZED;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400400 return PREMONOMORPHIC;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
402 return MEGAMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400403 } else if (feedback->IsFixedArray()) {
404 // Determine state purely by our structure, don't check if the maps are
405 // cleared.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 return POLYMORPHIC;
407 } else if (feedback->IsWeakCell()) {
408 // Don't check if the map is cleared.
409 return MONOMORPHIC;
410 } else if (feedback->IsName()) {
411 Object* extra = GetFeedbackExtra();
412 FixedArray* extra_array = FixedArray::cast(extra);
413 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
414 }
415
416 return UNINITIALIZED;
417}
418
419
420InlineCacheState StoreICNexus::StateFromFeedback() const {
421 Isolate* isolate = GetIsolate();
422 Object* feedback = GetFeedback();
423
424 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
425 return UNINITIALIZED;
426 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
427 return MEGAMORPHIC;
428 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
429 return PREMONOMORPHIC;
430 } else if (feedback->IsFixedArray()) {
431 // Determine state purely by our structure, don't check if the maps are
432 // cleared.
433 return POLYMORPHIC;
434 } else if (feedback->IsWeakCell()) {
435 // Don't check if the map is cleared.
436 return MONOMORPHIC;
437 }
438
439 return UNINITIALIZED;
440}
441
442
443InlineCacheState KeyedStoreICNexus::StateFromFeedback() const {
444 Isolate* isolate = GetIsolate();
445 Object* feedback = GetFeedback();
446
447 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
448 return UNINITIALIZED;
449 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
450 return PREMONOMORPHIC;
451 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
452 return MEGAMORPHIC;
453 } else if (feedback->IsFixedArray()) {
454 // Determine state purely by our structure, don't check if the maps are
455 // cleared.
456 return POLYMORPHIC;
457 } else if (feedback->IsWeakCell()) {
458 // Don't check if the map is cleared.
459 return MONOMORPHIC;
460 } else if (feedback->IsName()) {
461 Object* extra = GetFeedbackExtra();
462 FixedArray* extra_array = FixedArray::cast(extra);
463 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400464 }
465
466 return UNINITIALIZED;
467}
468
469
470InlineCacheState CallICNexus::StateFromFeedback() const {
471 Isolate* isolate = GetIsolate();
472 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000473 DCHECK(GetFeedbackExtra() ==
474 *TypeFeedbackVector::UninitializedSentinel(isolate) ||
475 GetFeedbackExtra()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400476
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400478 return GENERIC;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479 } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400480 return MONOMORPHIC;
481 }
482
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483 CHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400484 return UNINITIALIZED;
485}
486
487
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488int CallICNexus::ExtractCallCount() {
489 Object* call_count = GetFeedbackExtra();
490 if (call_count->IsSmi()) {
491 int value = Smi::cast(call_count)->value() / 2;
492 return value;
493 }
494 return -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400495}
496
497
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000498void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
499
500
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400501void CallICNexus::ConfigureMonomorphicArray() {
502 Object* feedback = GetFeedback();
503 if (!feedback->IsAllocationSite()) {
504 Handle<AllocationSite> new_site =
505 GetIsolate()->factory()->NewAllocationSite();
506 SetFeedback(*new_site);
507 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400509}
510
511
512void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function);
514 SetFeedback(*new_cell);
515 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400516}
517
518
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519void CallICNexus::ConfigureMegamorphic() {
520 FeedbackNexus::ConfigureMegamorphic();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400521}
522
523
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000524void CallICNexus::ConfigureMegamorphic(int call_count) {
525 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400526 SKIP_WRITE_BARRIER);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 SetFeedbackExtra(Smi::FromInt(call_count * kCallCountIncrement),
528 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400529}
530
531
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400533 Handle<Code> handler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400534 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000535 SetFeedback(*cell);
536 SetFeedbackExtra(*handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400537}
538
539
540void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000541 Handle<Map> receiver_map,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400542 Handle<Code> handler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400543 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 if (name.is_null()) {
545 SetFeedback(*cell);
546 SetFeedbackExtra(*handler);
547 } else {
548 Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
549 SetFeedback(*name);
550 array->set(0, *cell);
551 array->set(1, *handler);
552 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400553}
554
555
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
557 Handle<Code> handler) {
558 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
559 SetFeedback(*cell);
560 SetFeedbackExtra(*handler);
561}
562
563
564void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name,
565 Handle<Map> receiver_map,
566 Handle<Code> handler) {
567 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
568 if (name.is_null()) {
569 SetFeedback(*cell);
570 SetFeedbackExtra(*handler);
571 } else {
572 Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
573 SetFeedback(*name);
574 array->set(0, *cell);
575 array->set(1, *handler);
576 }
577}
578
579
580void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400581 CodeHandleList* handlers) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 Isolate* isolate = GetIsolate();
583 int receiver_count = maps->length();
584 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
585 InstallHandlers(array, maps, handlers);
586 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
587 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400588}
589
590
591void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000592 MapHandleList* maps,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400593 CodeHandleList* handlers) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594 int receiver_count = maps->length();
595 DCHECK(receiver_count > 1);
596 Handle<FixedArray> array;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400597 if (name.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000598 array = EnsureArrayOfSize(receiver_count * 2);
599 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
600 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400601 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 array = EnsureExtraArrayOfSize(receiver_count * 2);
603 SetFeedback(*name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400604 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605
606 InstallHandlers(array, maps, handlers);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400607}
608
609
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
611 CodeHandleList* handlers) {
612 Isolate* isolate = GetIsolate();
613 int receiver_count = maps->length();
614 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
615 InstallHandlers(array, maps, handlers);
616 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
617 SKIP_WRITE_BARRIER);
618}
619
620
621void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
622 MapHandleList* maps,
623 CodeHandleList* handlers) {
624 int receiver_count = maps->length();
625 DCHECK(receiver_count > 1);
626 Handle<FixedArray> array;
627 if (name.is_null()) {
628 array = EnsureArrayOfSize(receiver_count * 2);
629 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
630 SKIP_WRITE_BARRIER);
631 } else {
632 array = EnsureExtraArrayOfSize(receiver_count * 2);
633 SetFeedback(*name);
634 }
635
636 InstallHandlers(array, maps, handlers);
637}
638
639
640void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
641 MapHandleList* transitioned_maps,
642 CodeHandleList* handlers) {
643 int receiver_count = maps->length();
644 DCHECK(receiver_count > 1);
645 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3);
646 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
647 SKIP_WRITE_BARRIER);
648
649 Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value();
650 for (int i = 0; i < receiver_count; ++i) {
651 Handle<Map> map = maps->at(i);
652 Handle<WeakCell> cell = Map::WeakCellForMap(map);
653 array->set(i * 3, *cell);
654 if (!transitioned_maps->at(i).is_null()) {
655 Handle<Map> transitioned_map = transitioned_maps->at(i);
656 cell = Map::WeakCellForMap(transitioned_map);
657 array->set((i * 3) + 1, *cell);
658 } else {
659 array->set((i * 3) + 1, *undefined_value);
660 }
661 array->set((i * 3) + 2, *handlers->at(i));
662 }
663}
664
665
666int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400667 Isolate* isolate = GetIsolate();
668 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669 bool is_named_feedback = IsPropertyNameFeedback(feedback);
670 if (feedback->IsFixedArray() || is_named_feedback) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400671 int found = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000672 if (is_named_feedback) {
673 feedback = GetFeedbackExtra();
674 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400675 FixedArray* array = FixedArray::cast(feedback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676 // The array should be of the form
677 // [map, handler, map, handler, ...]
678 // or
679 // [map, map, handler, map, map, handler, ...]
680 DCHECK(array->length() >= 2);
681 int increment = array->get(1)->IsCode() ? 2 : 3;
682 for (int i = 0; i < array->length(); i += increment) {
683 DCHECK(array->get(i)->IsWeakCell());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400684 WeakCell* cell = WeakCell::cast(array->get(i));
685 if (!cell->cleared()) {
686 Map* map = Map::cast(cell->value());
687 maps->Add(handle(map, isolate));
688 found++;
689 }
690 }
691 return found;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692 } else if (feedback->IsWeakCell()) {
693 WeakCell* cell = WeakCell::cast(feedback);
694 if (!cell->cleared()) {
695 Map* map = Map::cast(cell->value());
696 maps->Add(handle(map, isolate));
697 return 1;
698 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400699 }
700
701 return 0;
702}
703
704
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000705MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400706 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 bool is_named_feedback = IsPropertyNameFeedback(feedback);
708 if (feedback->IsFixedArray() || is_named_feedback) {
709 if (is_named_feedback) {
710 feedback = GetFeedbackExtra();
711 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400712 FixedArray* array = FixedArray::cast(feedback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713 DCHECK(array->length() >= 2);
714 int increment = array->get(1)->IsCode() ? 2 : 3;
715 for (int i = 0; i < array->length(); i += increment) {
716 DCHECK(array->get(i)->IsWeakCell());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400717 WeakCell* cell = WeakCell::cast(array->get(i));
718 if (!cell->cleared()) {
719 Map* array_map = Map::cast(cell->value());
720 if (array_map == *map) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 Code* code = Code::cast(array->get(i + increment - 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400722 DCHECK(code->kind() == Code::HANDLER);
723 return handle(code);
724 }
725 }
726 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000727 } else if (feedback->IsWeakCell()) {
728 WeakCell* cell = WeakCell::cast(feedback);
729 if (!cell->cleared()) {
730 Map* cell_map = Map::cast(cell->value());
731 if (cell_map == *map) {
732 Code* code = Code::cast(GetFeedbackExtra());
733 DCHECK(code->kind() == Code::HANDLER);
734 return handle(code);
735 }
736 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400737 }
738
739 return MaybeHandle<Code>();
740}
741
742
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400744 Object* feedback = GetFeedback();
745 int count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000746 bool is_named_feedback = IsPropertyNameFeedback(feedback);
747 if (feedback->IsFixedArray() || is_named_feedback) {
748 if (is_named_feedback) {
749 feedback = GetFeedbackExtra();
750 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400751 FixedArray* array = FixedArray::cast(feedback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000752 // The array should be of the form
753 // [map, handler, map, handler, ...]
754 // or
755 // [map, map, handler, map, map, handler, ...]
756 // Be sure to skip handlers whose maps have been cleared.
757 DCHECK(array->length() >= 2);
758 int increment = array->get(1)->IsCode() ? 2 : 3;
759 for (int i = 0; i < array->length(); i += increment) {
760 DCHECK(array->get(i)->IsWeakCell());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400761 WeakCell* cell = WeakCell::cast(array->get(i));
762 if (!cell->cleared()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000763 Code* code = Code::cast(array->get(i + increment - 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400764 DCHECK(code->kind() == Code::HANDLER);
765 code_list->Add(handle(code));
766 count++;
767 }
768 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000769 } else if (feedback->IsWeakCell()) {
770 WeakCell* cell = WeakCell::cast(feedback);
771 if (!cell->cleared()) {
772 Code* code = Code::cast(GetFeedbackExtra());
773 DCHECK(code->kind() == Code::HANDLER);
774 code_list->Add(handle(code));
775 count++;
776 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400777 }
778 return count == length;
779}
780
781
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400782void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
783
784
785void KeyedLoadICNexus::Clear(Code* host) {
786 KeyedLoadIC::Clear(GetIsolate(), host, this);
787}
788
789
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400790Name* KeyedLoadICNexus::FindFirstName() const {
791 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000792 if (IsPropertyNameFeedback(feedback)) {
793 return Name::cast(feedback);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400794 }
795 return NULL;
796}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797
798
799Name* KeyedStoreICNexus::FindFirstName() const {
800 Object* feedback = GetFeedback();
801 if (IsPropertyNameFeedback(feedback)) {
802 return Name::cast(feedback);
803 }
804 return NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000805}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806
807
808void StoreICNexus::Clear(Code* host) {
809 StoreIC::Clear(GetIsolate(), host, this);
810}
811
812
813void KeyedStoreICNexus::Clear(Code* host) {
814 KeyedStoreIC::Clear(GetIsolate(), host, this);
815}
816
817
818KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
819 KeyedAccessStoreMode mode = STANDARD_STORE;
820 MapHandleList maps;
821 CodeHandleList handlers;
822
823 if (GetKeyType() == PROPERTY) return mode;
824
825 ExtractMaps(&maps);
826 FindHandlers(&handlers, maps.length());
827 for (int i = 0; i < handlers.length(); i++) {
828 // The first handler that isn't the slow handler will have the bits we need.
829 Handle<Code> handler = handlers.at(i);
830 CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
831 uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
832 CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
833 major_key == CodeStub::StoreFastElement ||
834 major_key == CodeStub::StoreElement ||
835 major_key == CodeStub::ElementsTransitionAndStore ||
836 major_key == CodeStub::NoCache);
837 if (major_key != CodeStub::NoCache) {
838 mode = CommonStoreModeBits::decode(minor_key);
839 break;
840 }
841 }
842
843 return mode;
844}
845
Ben Murdoch097c5b22016-05-18 11:27:45 +0100846IcCheckType KeyedLoadICNexus::GetKeyType() const {
847 Object* feedback = GetFeedback();
848 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) {
849 return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value());
850 }
851 return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
852}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853
854IcCheckType KeyedStoreICNexus::GetKeyType() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100855 Object* feedback = GetFeedback();
856 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) {
857 return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value());
858 }
859 return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860}
861} // namespace internal
862} // namespace v8