blob: 698f2a6d17380d6e0771c5194e2259819b864542 [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) {
18 return feedback->IsString() ||
19 (feedback->IsSymbol() && !Symbol::cast(feedback)->is_private());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020}
21
22
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) {
24 return os << TypeFeedbackMetadata::Kind2String(kind);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040025}
26
27
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind(
29 FeedbackVectorSlot slot) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040030 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
31 int data = Smi::cast(get(index))->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 return VectorICComputer::decode(data, slot.ToInt());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040033}
34
35
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
37 FeedbackVectorSlotKind kind) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040038 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
39 int data = Smi::cast(get(index))->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041 set(index, Smi::FromInt(new_data));
42}
43
44
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
46 Isolate* isolate, const StaticFeedbackVectorSpec* spec);
47template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
48 Isolate* isolate, const FeedbackVectorSpec* spec);
49
50
Emily Bernierd0a1eb72015-03-24 16:35:39 -040051// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052template <typename Spec>
53Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
54 const Spec* spec) {
55 const int slot_count = spec->slots();
56 const int slot_kinds_length = VectorICComputer::word_count(slot_count);
57 const int length = slot_kinds_length + kReservedIndexCount;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040058 if (length == kReservedIndexCount) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059 return Handle<TypeFeedbackMetadata>::cast(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040060 isolate->factory()->empty_fixed_array());
61 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062#ifdef DEBUG
63 for (int i = 0; i < slot_count;) {
64 FeedbackVectorSlotKind kind = spec->GetKind(i);
65 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
66 for (int j = 1; j < entry_size; j++) {
67 FeedbackVectorSlotKind kind = spec->GetKind(i + j);
68 DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind);
69 }
70 i += entry_size;
71 }
72#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040073
74 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
76 // Fill the bit-vector part with zeros.
77 for (int i = 0; i < slot_kinds_length; i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040078 array->set(kReservedIndexCount + i, Smi::FromInt(0));
79 }
80
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 Handle<TypeFeedbackMetadata> metadata =
82 Handle<TypeFeedbackMetadata>::cast(array);
83 for (int i = 0; i < slot_count; i++) {
84 metadata->SetKind(FeedbackVectorSlot(i), spec->GetKind(i));
85 }
86 return metadata;
87}
88
89
90bool TypeFeedbackMetadata::SpecDiffersFrom(
91 const FeedbackVectorSpec* other_spec) const {
92 if (other_spec->slots() != slot_count()) {
93 return true;
94 }
95
96 int slots = slot_count();
97 for (int i = 0; i < slots; i++) {
98 if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) {
99 return true;
100 }
101 }
102 return false;
103}
104
105
106const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) {
107 switch (kind) {
108 case FeedbackVectorSlotKind::INVALID:
109 return "INVALID";
110 case FeedbackVectorSlotKind::CALL_IC:
111 return "CALL_IC";
112 case FeedbackVectorSlotKind::LOAD_IC:
113 return "LOAD_IC";
114 case FeedbackVectorSlotKind::KEYED_LOAD_IC:
115 return "KEYED_LOAD_IC";
116 case FeedbackVectorSlotKind::STORE_IC:
117 return "STORE_IC";
118 case FeedbackVectorSlotKind::KEYED_STORE_IC:
119 return "KEYED_STORE_IC";
120 case FeedbackVectorSlotKind::GENERAL:
121 return "STUB";
122 case FeedbackVectorSlotKind::KINDS_NUMBER:
123 break;
124 }
125 UNREACHABLE();
126 return "?";
127}
128
129
130// static
131Handle<TypeFeedbackVector> TypeFeedbackVector::New(
132 Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) {
133 Factory* factory = isolate->factory();
134
135 const int slot_count = metadata->slot_count();
136 const int length = slot_count + kReservedIndexCount;
137 if (length == kReservedIndexCount) {
138 return Handle<TypeFeedbackVector>::cast(factory->empty_fixed_array());
139 }
140
141 Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
142 array->set(kMetadataIndex, *metadata);
143
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144 // Ensure we can skip the write barrier
145 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000146 DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel);
147 for (int i = kReservedIndexCount; i < length; i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400148 array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
149 }
150
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 return Handle<TypeFeedbackVector>::cast(array);
152}
153
154
155// static
156int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec,
157 FeedbackVectorSlot slot) {
158 return kReservedIndexCount + slot.ToInt();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400159}
160
161
162// static
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163Handle<TypeFeedbackVector> TypeFeedbackVector::Copy(
164 Isolate* isolate, Handle<TypeFeedbackVector> vector) {
165 Handle<TypeFeedbackVector> result;
166 result = Handle<TypeFeedbackVector>::cast(
167 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
168 return result;
169}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400170
171
172// This logic is copied from
173// StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174static bool ClearLogic(Isolate* isolate) {
175 return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400176}
177
178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
180 bool force_clear) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400181 Isolate* isolate = GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182
183 if (!force_clear && !ClearLogic(isolate)) return;
184
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185 Object* uninitialized_sentinel =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 TypeFeedbackVector::RawUninitializedSentinel(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 TypeFeedbackMetadataIterator iter(metadata());
189 while (iter.HasNext()) {
190 FeedbackVectorSlot slot = iter.Next();
191 FeedbackVectorSlotKind kind = iter.kind();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400193 Object* obj = Get(slot);
194 if (obj != uninitialized_sentinel) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 switch (kind) {
196 case FeedbackVectorSlotKind::CALL_IC: {
197 CallICNexus nexus(this, slot);
198 nexus.Clear(shared->code());
199 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400200 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 case FeedbackVectorSlotKind::LOAD_IC: {
202 LoadICNexus 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::KEYED_LOAD_IC: {
207 KeyedLoadICNexus 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::STORE_IC: {
212 StoreICNexus nexus(this, slot);
213 nexus.Clear(shared->code());
214 break;
215 }
216 case FeedbackVectorSlotKind::KEYED_STORE_IC: {
217 KeyedStoreICNexus nexus(this, slot);
218 nexus.Clear(shared->code());
219 break;
220 }
221 case FeedbackVectorSlotKind::GENERAL: {
222 if (obj->IsHeapObject()) {
223 InstanceType instance_type =
224 HeapObject::cast(obj)->map()->instance_type();
225 // AllocationSites are exempt from clearing. They don't store Maps
226 // or Code pointers which can cause memory leaks if not cleared
227 // regularly.
228 if (instance_type != ALLOCATION_SITE_TYPE) {
229 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER);
230 }
231 }
232 break;
233 }
234 case FeedbackVectorSlotKind::INVALID:
235 case FeedbackVectorSlotKind::KINDS_NUMBER:
236 UNREACHABLE();
237 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400238 }
239 }
240 }
241}
242
243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244// static
245void TypeFeedbackVector::ClearAllKeyedStoreICs(Isolate* isolate) {
246 SharedFunctionInfo::Iterator iterator(isolate);
247 SharedFunctionInfo* shared;
248 while ((shared = iterator.Next())) {
249 TypeFeedbackVector* vector = shared->feedback_vector();
250 vector->ClearKeyedStoreICs(shared);
251 }
252}
253
254
255void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) {
256 Isolate* isolate = GetIsolate();
257
258 Code* host = shared->code();
259 Object* uninitialized_sentinel =
260 TypeFeedbackVector::RawUninitializedSentinel(isolate);
261
262 TypeFeedbackMetadataIterator iter(metadata());
263 while (iter.HasNext()) {
264 FeedbackVectorSlot slot = iter.Next();
265 FeedbackVectorSlotKind kind = iter.kind();
266 if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue;
267 Object* obj = Get(slot);
268 if (obj != uninitialized_sentinel) {
269 KeyedStoreICNexus nexus(this, slot);
270 nexus.Clear(host);
271 }
272 }
273}
274
275
276// static
277Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) {
278 return isolate->factory()->dummy_vector();
279}
280
281
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400282Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
283 Isolate* isolate = GetIsolate();
284 Handle<Object> feedback = handle(GetFeedback(), isolate);
285 if (!feedback->IsFixedArray() ||
286 FixedArray::cast(*feedback)->length() != length) {
287 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
288 SetFeedback(*array);
289 return array;
290 }
291 return Handle<FixedArray>::cast(feedback);
292}
293
294
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400296 Isolate* isolate = GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate);
298 if (!feedback_extra->IsFixedArray() ||
299 FixedArray::cast(*feedback_extra)->length() != length) {
300 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
301 SetFeedbackExtra(*array);
302 return array;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400303 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 return Handle<FixedArray>::cast(feedback_extra);
305}
306
307
308void FeedbackNexus::InstallHandlers(Handle<FixedArray> array,
309 MapHandleList* maps,
310 CodeHandleList* handlers) {
311 int receiver_count = maps->length();
312 for (int current = 0; current < receiver_count; ++current) {
313 Handle<Map> map = maps->at(current);
314 Handle<WeakCell> cell = Map::WeakCellForMap(map);
315 array->set(current * 2, *cell);
316 array->set(current * 2 + 1, *handlers->at(current));
317 }
318}
319
320
321void FeedbackNexus::ConfigureUninitialized() {
322 SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
323 SKIP_WRITE_BARRIER);
324 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
325 SKIP_WRITE_BARRIER);
326}
327
328
329void FeedbackNexus::ConfigurePremonomorphic() {
330 SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()),
331 SKIP_WRITE_BARRIER);
332 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
333 SKIP_WRITE_BARRIER);
334}
335
336
337void FeedbackNexus::ConfigureMegamorphic() {
338 Isolate* isolate = GetIsolate();
339 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
340 SKIP_WRITE_BARRIER);
341 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
342 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400343}
344
345
346InlineCacheState LoadICNexus::StateFromFeedback() const {
347 Isolate* isolate = GetIsolate();
348 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349
350 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400351 return UNINITIALIZED;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400353 return MEGAMORPHIC;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400355 return PREMONOMORPHIC;
356 } else if (feedback->IsFixedArray()) {
357 // Determine state purely by our structure, don't check if the maps are
358 // cleared.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 return POLYMORPHIC;
360 } else if (feedback->IsWeakCell()) {
361 // Don't check if the map is cleared.
362 return MONOMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400363 }
364
365 return UNINITIALIZED;
366}
367
368
369InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
370 Isolate* isolate = GetIsolate();
371 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372
373 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400374 return UNINITIALIZED;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400376 return PREMONOMORPHIC;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000377 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
378 return MEGAMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400379 } else if (feedback->IsFixedArray()) {
380 // Determine state purely by our structure, don't check if the maps are
381 // cleared.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 return POLYMORPHIC;
383 } else if (feedback->IsWeakCell()) {
384 // Don't check if the map is cleared.
385 return MONOMORPHIC;
386 } else if (feedback->IsName()) {
387 Object* extra = GetFeedbackExtra();
388 FixedArray* extra_array = FixedArray::cast(extra);
389 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
390 }
391
392 return UNINITIALIZED;
393}
394
395
396InlineCacheState StoreICNexus::StateFromFeedback() const {
397 Isolate* isolate = GetIsolate();
398 Object* feedback = GetFeedback();
399
400 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
401 return UNINITIALIZED;
402 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
403 return MEGAMORPHIC;
404 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
405 return PREMONOMORPHIC;
406 } else if (feedback->IsFixedArray()) {
407 // Determine state purely by our structure, don't check if the maps are
408 // cleared.
409 return POLYMORPHIC;
410 } else if (feedback->IsWeakCell()) {
411 // Don't check if the map is cleared.
412 return MONOMORPHIC;
413 }
414
415 return UNINITIALIZED;
416}
417
418
419InlineCacheState KeyedStoreICNexus::StateFromFeedback() const {
420 Isolate* isolate = GetIsolate();
421 Object* feedback = GetFeedback();
422
423 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
424 return UNINITIALIZED;
425 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
426 return PREMONOMORPHIC;
427 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
428 return MEGAMORPHIC;
429 } else if (feedback->IsFixedArray()) {
430 // Determine state purely by our structure, don't check if the maps are
431 // cleared.
432 return POLYMORPHIC;
433 } else if (feedback->IsWeakCell()) {
434 // Don't check if the map is cleared.
435 return MONOMORPHIC;
436 } else if (feedback->IsName()) {
437 Object* extra = GetFeedbackExtra();
438 FixedArray* extra_array = FixedArray::cast(extra);
439 return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400440 }
441
442 return UNINITIALIZED;
443}
444
445
446InlineCacheState CallICNexus::StateFromFeedback() const {
447 Isolate* isolate = GetIsolate();
448 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000449 DCHECK(GetFeedbackExtra() ==
450 *TypeFeedbackVector::UninitializedSentinel(isolate) ||
451 GetFeedbackExtra()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400452
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400454 return GENERIC;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400456 return MONOMORPHIC;
457 }
458
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000459 CHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400460 return UNINITIALIZED;
461}
462
463
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464int CallICNexus::ExtractCallCount() {
465 Object* call_count = GetFeedbackExtra();
466 if (call_count->IsSmi()) {
467 int value = Smi::cast(call_count)->value() / 2;
468 return value;
469 }
470 return -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400471}
472
473
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000474void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
475
476
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400477void CallICNexus::ConfigureMonomorphicArray() {
478 Object* feedback = GetFeedback();
479 if (!feedback->IsAllocationSite()) {
480 Handle<AllocationSite> new_site =
481 GetIsolate()->factory()->NewAllocationSite();
482 SetFeedback(*new_site);
483 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400485}
486
487
488void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000489 Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function);
490 SetFeedback(*new_cell);
491 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400492}
493
494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495void CallICNexus::ConfigureMegamorphic() {
496 FeedbackNexus::ConfigureMegamorphic();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400497}
498
499
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500void CallICNexus::ConfigureMegamorphic(int call_count) {
501 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400502 SKIP_WRITE_BARRIER);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 SetFeedbackExtra(Smi::FromInt(call_count * kCallCountIncrement),
504 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400505}
506
507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400509 Handle<Code> handler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400510 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511 SetFeedback(*cell);
512 SetFeedbackExtra(*handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400513}
514
515
516void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000517 Handle<Map> receiver_map,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400518 Handle<Code> handler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400519 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520 if (name.is_null()) {
521 SetFeedback(*cell);
522 SetFeedbackExtra(*handler);
523 } else {
524 Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
525 SetFeedback(*name);
526 array->set(0, *cell);
527 array->set(1, *handler);
528 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400529}
530
531
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
533 Handle<Code> handler) {
534 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
535 SetFeedback(*cell);
536 SetFeedbackExtra(*handler);
537}
538
539
540void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name,
541 Handle<Map> receiver_map,
542 Handle<Code> handler) {
543 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
544 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 }
553}
554
555
556void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400557 CodeHandleList* handlers) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 Isolate* isolate = GetIsolate();
559 int receiver_count = maps->length();
560 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
561 InstallHandlers(array, maps, handlers);
562 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
563 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400564}
565
566
567void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 MapHandleList* maps,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400569 CodeHandleList* handlers) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 int receiver_count = maps->length();
571 DCHECK(receiver_count > 1);
572 Handle<FixedArray> array;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400573 if (name.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 array = EnsureArrayOfSize(receiver_count * 2);
575 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
576 SKIP_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400577 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 array = EnsureExtraArrayOfSize(receiver_count * 2);
579 SetFeedback(*name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400580 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581
582 InstallHandlers(array, maps, handlers);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400583}
584
585
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000586void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
587 CodeHandleList* handlers) {
588 Isolate* isolate = GetIsolate();
589 int receiver_count = maps->length();
590 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
591 InstallHandlers(array, maps, handlers);
592 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
593 SKIP_WRITE_BARRIER);
594}
595
596
597void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
598 MapHandleList* maps,
599 CodeHandleList* handlers) {
600 int receiver_count = maps->length();
601 DCHECK(receiver_count > 1);
602 Handle<FixedArray> array;
603 if (name.is_null()) {
604 array = EnsureArrayOfSize(receiver_count * 2);
605 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
606 SKIP_WRITE_BARRIER);
607 } else {
608 array = EnsureExtraArrayOfSize(receiver_count * 2);
609 SetFeedback(*name);
610 }
611
612 InstallHandlers(array, maps, handlers);
613}
614
615
616void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
617 MapHandleList* transitioned_maps,
618 CodeHandleList* handlers) {
619 int receiver_count = maps->length();
620 DCHECK(receiver_count > 1);
621 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3);
622 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
623 SKIP_WRITE_BARRIER);
624
625 Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value();
626 for (int i = 0; i < receiver_count; ++i) {
627 Handle<Map> map = maps->at(i);
628 Handle<WeakCell> cell = Map::WeakCellForMap(map);
629 array->set(i * 3, *cell);
630 if (!transitioned_maps->at(i).is_null()) {
631 Handle<Map> transitioned_map = transitioned_maps->at(i);
632 cell = Map::WeakCellForMap(transitioned_map);
633 array->set((i * 3) + 1, *cell);
634 } else {
635 array->set((i * 3) + 1, *undefined_value);
636 }
637 array->set((i * 3) + 2, *handlers->at(i));
638 }
639}
640
641
642int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400643 Isolate* isolate = GetIsolate();
644 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645 bool is_named_feedback = IsPropertyNameFeedback(feedback);
646 if (feedback->IsFixedArray() || is_named_feedback) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400647 int found = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648 if (is_named_feedback) {
649 feedback = GetFeedbackExtra();
650 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400651 FixedArray* array = FixedArray::cast(feedback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652 // The array should be of the form
653 // [map, handler, map, handler, ...]
654 // or
655 // [map, map, handler, map, map, handler, ...]
656 DCHECK(array->length() >= 2);
657 int increment = array->get(1)->IsCode() ? 2 : 3;
658 for (int i = 0; i < array->length(); i += increment) {
659 DCHECK(array->get(i)->IsWeakCell());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400660 WeakCell* cell = WeakCell::cast(array->get(i));
661 if (!cell->cleared()) {
662 Map* map = Map::cast(cell->value());
663 maps->Add(handle(map, isolate));
664 found++;
665 }
666 }
667 return found;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 } else if (feedback->IsWeakCell()) {
669 WeakCell* cell = WeakCell::cast(feedback);
670 if (!cell->cleared()) {
671 Map* map = Map::cast(cell->value());
672 maps->Add(handle(map, isolate));
673 return 1;
674 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400675 }
676
677 return 0;
678}
679
680
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000681MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400682 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 bool is_named_feedback = IsPropertyNameFeedback(feedback);
684 if (feedback->IsFixedArray() || is_named_feedback) {
685 if (is_named_feedback) {
686 feedback = GetFeedbackExtra();
687 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400688 FixedArray* array = FixedArray::cast(feedback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000689 DCHECK(array->length() >= 2);
690 int increment = array->get(1)->IsCode() ? 2 : 3;
691 for (int i = 0; i < array->length(); i += increment) {
692 DCHECK(array->get(i)->IsWeakCell());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400693 WeakCell* cell = WeakCell::cast(array->get(i));
694 if (!cell->cleared()) {
695 Map* array_map = Map::cast(cell->value());
696 if (array_map == *map) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 Code* code = Code::cast(array->get(i + increment - 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400698 DCHECK(code->kind() == Code::HANDLER);
699 return handle(code);
700 }
701 }
702 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000703 } else if (feedback->IsWeakCell()) {
704 WeakCell* cell = WeakCell::cast(feedback);
705 if (!cell->cleared()) {
706 Map* cell_map = Map::cast(cell->value());
707 if (cell_map == *map) {
708 Code* code = Code::cast(GetFeedbackExtra());
709 DCHECK(code->kind() == Code::HANDLER);
710 return handle(code);
711 }
712 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400713 }
714
715 return MaybeHandle<Code>();
716}
717
718
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000719bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400720 Object* feedback = GetFeedback();
721 int count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000722 bool is_named_feedback = IsPropertyNameFeedback(feedback);
723 if (feedback->IsFixedArray() || is_named_feedback) {
724 if (is_named_feedback) {
725 feedback = GetFeedbackExtra();
726 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400727 FixedArray* array = FixedArray::cast(feedback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000728 // The array should be of the form
729 // [map, handler, map, handler, ...]
730 // or
731 // [map, map, handler, map, map, handler, ...]
732 // Be sure to skip handlers whose maps have been cleared.
733 DCHECK(array->length() >= 2);
734 int increment = array->get(1)->IsCode() ? 2 : 3;
735 for (int i = 0; i < array->length(); i += increment) {
736 DCHECK(array->get(i)->IsWeakCell());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400737 WeakCell* cell = WeakCell::cast(array->get(i));
738 if (!cell->cleared()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000739 Code* code = Code::cast(array->get(i + increment - 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400740 DCHECK(code->kind() == Code::HANDLER);
741 code_list->Add(handle(code));
742 count++;
743 }
744 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000745 } else if (feedback->IsWeakCell()) {
746 WeakCell* cell = WeakCell::cast(feedback);
747 if (!cell->cleared()) {
748 Code* code = Code::cast(GetFeedbackExtra());
749 DCHECK(code->kind() == Code::HANDLER);
750 code_list->Add(handle(code));
751 count++;
752 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400753 }
754 return count == length;
755}
756
757
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400758void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
759
760
761void KeyedLoadICNexus::Clear(Code* host) {
762 KeyedLoadIC::Clear(GetIsolate(), host, this);
763}
764
765
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400766Name* KeyedLoadICNexus::FindFirstName() const {
767 Object* feedback = GetFeedback();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768 if (IsPropertyNameFeedback(feedback)) {
769 return Name::cast(feedback);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400770 }
771 return NULL;
772}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773
774
775Name* KeyedStoreICNexus::FindFirstName() const {
776 Object* feedback = GetFeedback();
777 if (IsPropertyNameFeedback(feedback)) {
778 return Name::cast(feedback);
779 }
780 return NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782
783
784void StoreICNexus::Clear(Code* host) {
785 StoreIC::Clear(GetIsolate(), host, this);
786}
787
788
789void KeyedStoreICNexus::Clear(Code* host) {
790 KeyedStoreIC::Clear(GetIsolate(), host, this);
791}
792
793
794KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
795 KeyedAccessStoreMode mode = STANDARD_STORE;
796 MapHandleList maps;
797 CodeHandleList handlers;
798
799 if (GetKeyType() == PROPERTY) return mode;
800
801 ExtractMaps(&maps);
802 FindHandlers(&handlers, maps.length());
803 for (int i = 0; i < handlers.length(); i++) {
804 // The first handler that isn't the slow handler will have the bits we need.
805 Handle<Code> handler = handlers.at(i);
806 CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
807 uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
808 CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
809 major_key == CodeStub::StoreFastElement ||
810 major_key == CodeStub::StoreElement ||
811 major_key == CodeStub::ElementsTransitionAndStore ||
812 major_key == CodeStub::NoCache);
813 if (major_key != CodeStub::NoCache) {
814 mode = CommonStoreModeBits::decode(minor_key);
815 break;
816 }
817 }
818
819 return mode;
820}
821
822
823IcCheckType KeyedStoreICNexus::GetKeyType() const {
824 // The structure of the vector slots tells us the type.
825 return GetFeedback()->IsName() ? PROPERTY : ELEMENT;
826}
827} // namespace internal
828} // namespace v8