1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/type-feedback-vector.h" 6 7 #include "src/code-stubs.h" 8 #include "src/ic/ic.h" 9 #include "src/ic/ic-state.h" 10 #include "src/objects.h" 11 #include "src/type-feedback-vector-inl.h" 12 13 namespace v8 { 14 namespace internal { 15 16 17 static bool IsPropertyNameFeedback(Object* feedback) { 18 return feedback->IsString() || 19 (feedback->IsSymbol() && !Symbol::cast(feedback)->is_private()); 20 } 21 22 23 std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) { 24 return os << TypeFeedbackMetadata::Kind2String(kind); 25 } 26 27 28 FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind( 29 FeedbackVectorSlot slot) const { 30 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); 31 int data = Smi::cast(get(index))->value(); 32 return VectorICComputer::decode(data, slot.ToInt()); 33 } 34 35 36 void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot, 37 FeedbackVectorSlotKind kind) { 38 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); 39 int data = Smi::cast(get(index))->value(); 40 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind); 41 set(index, Smi::FromInt(new_data)); 42 } 43 44 45 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( 46 Isolate* isolate, const StaticFeedbackVectorSpec* spec); 47 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( 48 Isolate* isolate, const FeedbackVectorSpec* spec); 49 50 51 // static 52 template <typename Spec> 53 Handle<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; 58 if (length == kReservedIndexCount) { 59 return Handle<TypeFeedbackMetadata>::cast( 60 isolate->factory()->empty_fixed_array()); 61 } 62 #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 73 74 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED); 75 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++) { 78 array->set(kReservedIndexCount + i, Smi::FromInt(0)); 79 } 80 81 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 90 bool 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 106 const 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 131 Handle<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 144 // Ensure we can skip the write barrier 145 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); 146 DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel); 147 for (int i = kReservedIndexCount; i < length; i++) { 148 array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER); 149 } 150 151 return Handle<TypeFeedbackVector>::cast(array); 152 } 153 154 155 // static 156 int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec, 157 FeedbackVectorSlot slot) { 158 return kReservedIndexCount + slot.ToInt(); 159 } 160 161 162 // static 163 Handle<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 } 170 171 172 // This logic is copied from 173 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. 174 static bool ClearLogic(Isolate* isolate) { 175 return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled(); 176 } 177 178 179 void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared, 180 bool force_clear) { 181 Isolate* isolate = GetIsolate(); 182 183 if (!force_clear && !ClearLogic(isolate)) return; 184 185 Object* uninitialized_sentinel = 186 TypeFeedbackVector::RawUninitializedSentinel(isolate); 187 188 TypeFeedbackMetadataIterator iter(metadata()); 189 while (iter.HasNext()) { 190 FeedbackVectorSlot slot = iter.Next(); 191 FeedbackVectorSlotKind kind = iter.kind(); 192 193 Object* obj = Get(slot); 194 if (obj != uninitialized_sentinel) { 195 switch (kind) { 196 case FeedbackVectorSlotKind::CALL_IC: { 197 CallICNexus nexus(this, slot); 198 nexus.Clear(shared->code()); 199 break; 200 } 201 case FeedbackVectorSlotKind::LOAD_IC: { 202 LoadICNexus nexus(this, slot); 203 nexus.Clear(shared->code()); 204 break; 205 } 206 case FeedbackVectorSlotKind::KEYED_LOAD_IC: { 207 KeyedLoadICNexus nexus(this, slot); 208 nexus.Clear(shared->code()); 209 break; 210 } 211 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; 238 } 239 } 240 } 241 } 242 243 244 // static 245 void 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 255 void 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 277 Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) { 278 return isolate->factory()->dummy_vector(); 279 } 280 281 282 Handle<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 295 Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) { 296 Isolate* isolate = GetIsolate(); 297 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; 303 } 304 return Handle<FixedArray>::cast(feedback_extra); 305 } 306 307 308 void 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 321 void FeedbackNexus::ConfigureUninitialized() { 322 SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), 323 SKIP_WRITE_BARRIER); 324 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), 325 SKIP_WRITE_BARRIER); 326 } 327 328 329 void FeedbackNexus::ConfigurePremonomorphic() { 330 SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()), 331 SKIP_WRITE_BARRIER); 332 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), 333 SKIP_WRITE_BARRIER); 334 } 335 336 337 void FeedbackNexus::ConfigureMegamorphic() { 338 Isolate* isolate = GetIsolate(); 339 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate), 340 SKIP_WRITE_BARRIER); 341 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), 342 SKIP_WRITE_BARRIER); 343 } 344 345 346 InlineCacheState LoadICNexus::StateFromFeedback() const { 347 Isolate* isolate = GetIsolate(); 348 Object* feedback = GetFeedback(); 349 350 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { 351 return UNINITIALIZED; 352 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { 353 return MEGAMORPHIC; 354 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { 355 return PREMONOMORPHIC; 356 } else if (feedback->IsFixedArray()) { 357 // Determine state purely by our structure, don't check if the maps are 358 // cleared. 359 return POLYMORPHIC; 360 } else if (feedback->IsWeakCell()) { 361 // Don't check if the map is cleared. 362 return MONOMORPHIC; 363 } 364 365 return UNINITIALIZED; 366 } 367 368 369 InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { 370 Isolate* isolate = GetIsolate(); 371 Object* feedback = GetFeedback(); 372 373 if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { 374 return UNINITIALIZED; 375 } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { 376 return PREMONOMORPHIC; 377 } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { 378 return MEGAMORPHIC; 379 } else if (feedback->IsFixedArray()) { 380 // Determine state purely by our structure, don't check if the maps are 381 // cleared. 382 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 396 InlineCacheState 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 419 InlineCacheState 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; 440 } 441 442 return UNINITIALIZED; 443 } 444 445 446 InlineCacheState CallICNexus::StateFromFeedback() const { 447 Isolate* isolate = GetIsolate(); 448 Object* feedback = GetFeedback(); 449 DCHECK(GetFeedbackExtra() == 450 *TypeFeedbackVector::UninitializedSentinel(isolate) || 451 GetFeedbackExtra()->IsSmi()); 452 453 if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { 454 return GENERIC; 455 } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) { 456 return MONOMORPHIC; 457 } 458 459 CHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)); 460 return UNINITIALIZED; 461 } 462 463 464 int 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; 471 } 472 473 474 void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } 475 476 477 void CallICNexus::ConfigureMonomorphicArray() { 478 Object* feedback = GetFeedback(); 479 if (!feedback->IsAllocationSite()) { 480 Handle<AllocationSite> new_site = 481 GetIsolate()->factory()->NewAllocationSite(); 482 SetFeedback(*new_site); 483 } 484 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER); 485 } 486 487 488 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { 489 Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function); 490 SetFeedback(*new_cell); 491 SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER); 492 } 493 494 495 void CallICNexus::ConfigureMegamorphic() { 496 FeedbackNexus::ConfigureMegamorphic(); 497 } 498 499 500 void CallICNexus::ConfigureMegamorphic(int call_count) { 501 SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()), 502 SKIP_WRITE_BARRIER); 503 SetFeedbackExtra(Smi::FromInt(call_count * kCallCountIncrement), 504 SKIP_WRITE_BARRIER); 505 } 506 507 508 void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map, 509 Handle<Code> handler) { 510 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); 511 SetFeedback(*cell); 512 SetFeedbackExtra(*handler); 513 } 514 515 516 void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name, 517 Handle<Map> receiver_map, 518 Handle<Code> handler) { 519 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); 520 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 } 529 } 530 531 532 void 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 540 void 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 556 void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps, 557 CodeHandleList* handlers) { 558 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); 564 } 565 566 567 void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name, 568 MapHandleList* maps, 569 CodeHandleList* handlers) { 570 int receiver_count = maps->length(); 571 DCHECK(receiver_count > 1); 572 Handle<FixedArray> array; 573 if (name.is_null()) { 574 array = EnsureArrayOfSize(receiver_count * 2); 575 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), 576 SKIP_WRITE_BARRIER); 577 } else { 578 array = EnsureExtraArrayOfSize(receiver_count * 2); 579 SetFeedback(*name); 580 } 581 582 InstallHandlers(array, maps, handlers); 583 } 584 585 586 void 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 597 void 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 616 void 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 642 int FeedbackNexus::ExtractMaps(MapHandleList* maps) const { 643 Isolate* isolate = GetIsolate(); 644 Object* feedback = GetFeedback(); 645 bool is_named_feedback = IsPropertyNameFeedback(feedback); 646 if (feedback->IsFixedArray() || is_named_feedback) { 647 int found = 0; 648 if (is_named_feedback) { 649 feedback = GetFeedbackExtra(); 650 } 651 FixedArray* array = FixedArray::cast(feedback); 652 // 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()); 660 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; 668 } 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 } 675 } 676 677 return 0; 678 } 679 680 681 MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const { 682 Object* feedback = GetFeedback(); 683 bool is_named_feedback = IsPropertyNameFeedback(feedback); 684 if (feedback->IsFixedArray() || is_named_feedback) { 685 if (is_named_feedback) { 686 feedback = GetFeedbackExtra(); 687 } 688 FixedArray* array = FixedArray::cast(feedback); 689 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()); 693 WeakCell* cell = WeakCell::cast(array->get(i)); 694 if (!cell->cleared()) { 695 Map* array_map = Map::cast(cell->value()); 696 if (array_map == *map) { 697 Code* code = Code::cast(array->get(i + increment - 1)); 698 DCHECK(code->kind() == Code::HANDLER); 699 return handle(code); 700 } 701 } 702 } 703 } 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 } 713 } 714 715 return MaybeHandle<Code>(); 716 } 717 718 719 bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const { 720 Object* feedback = GetFeedback(); 721 int count = 0; 722 bool is_named_feedback = IsPropertyNameFeedback(feedback); 723 if (feedback->IsFixedArray() || is_named_feedback) { 724 if (is_named_feedback) { 725 feedback = GetFeedbackExtra(); 726 } 727 FixedArray* array = FixedArray::cast(feedback); 728 // 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()); 737 WeakCell* cell = WeakCell::cast(array->get(i)); 738 if (!cell->cleared()) { 739 Code* code = Code::cast(array->get(i + increment - 1)); 740 DCHECK(code->kind() == Code::HANDLER); 741 code_list->Add(handle(code)); 742 count++; 743 } 744 } 745 } 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 } 753 } 754 return count == length; 755 } 756 757 758 void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); } 759 760 761 void KeyedLoadICNexus::Clear(Code* host) { 762 KeyedLoadIC::Clear(GetIsolate(), host, this); 763 } 764 765 766 Name* KeyedLoadICNexus::FindFirstName() const { 767 Object* feedback = GetFeedback(); 768 if (IsPropertyNameFeedback(feedback)) { 769 return Name::cast(feedback); 770 } 771 return NULL; 772 } 773 774 775 Name* KeyedStoreICNexus::FindFirstName() const { 776 Object* feedback = GetFeedback(); 777 if (IsPropertyNameFeedback(feedback)) { 778 return Name::cast(feedback); 779 } 780 return NULL; 781 } 782 783 784 void StoreICNexus::Clear(Code* host) { 785 StoreIC::Clear(GetIsolate(), host, this); 786 } 787 788 789 void KeyedStoreICNexus::Clear(Code* host) { 790 KeyedStoreIC::Clear(GetIsolate(), host, this); 791 } 792 793 794 KeyedAccessStoreMode 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 823 IcCheckType 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 829