OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 return; | 251 return; |
252 } | 252 } |
253 } | 253 } |
254 } | 254 } |
255 | 255 |
256 | 256 |
257 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 257 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
258 Handle<String> name) { | 258 Handle<String> name) { |
259 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; | 259 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; |
260 Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); | 260 Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); |
261 maybe_handler_ = target()->FindHandlerForMap(*receiver_map); | 261 if (UseVector()) { |
| 262 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map); |
| 263 } else { |
| 264 maybe_handler_ = target()->FindHandlerForMap(*receiver_map); |
| 265 } |
262 | 266 |
263 // The current map wasn't handled yet. There's no reason to stay monomorphic, | 267 // The current map wasn't handled yet. There's no reason to stay monomorphic, |
264 // *unless* we're moving from a deprecated map to its replacement, or | 268 // *unless* we're moving from a deprecated map to its replacement, or |
265 // to a more general elements kind. | 269 // to a more general elements kind. |
266 // TODO(verwaest): Check if the current map is actually what the old map | 270 // TODO(verwaest): Check if the current map is actually what the old map |
267 // would transition to. | 271 // would transition to. |
268 if (maybe_handler_.is_null()) { | 272 if (maybe_handler_.is_null()) { |
269 if (!receiver_map->IsJSObjectMap()) return false; | 273 if (!receiver_map->IsJSObjectMap()) return false; |
270 Map* first_map = FirstTargetMap(); | 274 Map* first_map = FirstTargetMap(); |
271 if (first_map == NULL) return false; | 275 if (first_map == NULL) return false; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 } | 307 } |
304 | 308 |
305 return true; | 309 return true; |
306 } | 310 } |
307 | 311 |
308 | 312 |
309 bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) { | 313 bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) { |
310 if (target()->is_keyed_stub()) { | 314 if (target()->is_keyed_stub()) { |
311 // Determine whether the failure is due to a name failure. | 315 // Determine whether the failure is due to a name failure. |
312 if (!name->IsName()) return false; | 316 if (!name->IsName()) return false; |
313 Name* stub_name = target()->FindFirstName(); | 317 Name* stub_name = |
| 318 UseVector() ? nexus()->FindFirstName() : target()->FindFirstName(); |
314 if (*name != stub_name) return false; | 319 if (*name != stub_name) return false; |
315 } | 320 } |
316 | 321 |
317 return true; | 322 return true; |
318 } | 323 } |
319 | 324 |
320 | 325 |
321 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { | 326 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { |
322 update_receiver_type(receiver); | 327 update_receiver_type(receiver); |
323 if (!name->IsString()) return; | 328 if (!name->IsString()) return; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 isolate->runtime_profiler()->NotifyICChanged(); | 450 isolate->runtime_profiler()->NotifyICChanged(); |
446 // TODO(2029): When an optimized function is patched, it would | 451 // TODO(2029): When an optimized function is patched, it would |
447 // be nice to propagate the corresponding type information to its | 452 // be nice to propagate the corresponding type information to its |
448 // unoptimized version for the benefit of later inlining. | 453 // unoptimized version for the benefit of later inlining. |
449 } | 454 } |
450 | 455 |
451 | 456 |
452 void IC::PostPatching(Address address, Code* target, Code* old_target) { | 457 void IC::PostPatching(Address address, Code* target, Code* old_target) { |
453 // Type vector based ICs update these statistics at a different time because | 458 // Type vector based ICs update these statistics at a different time because |
454 // they don't always patch on state change. | 459 // they don't always patch on state change. |
455 if (target->kind() == Code::CALL_IC) return; | 460 if (ICUseVector(target->kind())) return; |
456 | 461 |
457 Isolate* isolate = target->GetHeap()->isolate(); | 462 Isolate* isolate = target->GetHeap()->isolate(); |
458 State old_state = UNINITIALIZED; | 463 State old_state = UNINITIALIZED; |
459 State new_state = UNINITIALIZED; | 464 State new_state = UNINITIALIZED; |
460 bool target_remains_ic_stub = false; | 465 bool target_remains_ic_stub = false; |
461 if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) { | 466 if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) { |
462 old_state = old_target->ic_state(); | 467 old_state = old_target->ic_state(); |
463 new_state = target->ic_state(); | 468 new_state = target->ic_state(); |
464 target_remains_ic_stub = true; | 469 target_remains_ic_stub = true; |
465 } | 470 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 | 512 |
508 void IC::Clear(Isolate* isolate, Address address, | 513 void IC::Clear(Isolate* isolate, Address address, |
509 ConstantPoolArray* constant_pool) { | 514 ConstantPoolArray* constant_pool) { |
510 Code* target = GetTargetAtAddress(address, constant_pool); | 515 Code* target = GetTargetAtAddress(address, constant_pool); |
511 | 516 |
512 // Don't clear debug break inline cache as it will remove the break point. | 517 // Don't clear debug break inline cache as it will remove the break point. |
513 if (target->is_debug_stub()) return; | 518 if (target->is_debug_stub()) return; |
514 | 519 |
515 switch (target->kind()) { | 520 switch (target->kind()) { |
516 case Code::LOAD_IC: | 521 case Code::LOAD_IC: |
| 522 if (FLAG_vector_ics) return; |
517 return LoadIC::Clear(isolate, address, target, constant_pool); | 523 return LoadIC::Clear(isolate, address, target, constant_pool); |
518 case Code::KEYED_LOAD_IC: | 524 case Code::KEYED_LOAD_IC: |
| 525 if (FLAG_vector_ics) return; |
519 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); | 526 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); |
520 case Code::STORE_IC: | 527 case Code::STORE_IC: |
521 return StoreIC::Clear(isolate, address, target, constant_pool); | 528 return StoreIC::Clear(isolate, address, target, constant_pool); |
522 case Code::KEYED_STORE_IC: | 529 case Code::KEYED_STORE_IC: |
523 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); | 530 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); |
524 case Code::COMPARE_IC: | 531 case Code::COMPARE_IC: |
525 return CompareIC::Clear(isolate, address, target, constant_pool); | 532 return CompareIC::Clear(isolate, address, target, constant_pool); |
526 case Code::COMPARE_NIL_IC: | 533 case Code::COMPARE_NIL_IC: |
527 return CompareNilIC::Clear(address, target, constant_pool); | 534 return CompareNilIC::Clear(address, target, constant_pool); |
528 case Code::CALL_IC: // CallICs are vector-based and cleared differently. | 535 case Code::CALL_IC: // CallICs are vector-based and cleared differently. |
529 case Code::BINARY_OP_IC: | 536 case Code::BINARY_OP_IC: |
530 case Code::TO_BOOLEAN_IC: | 537 case Code::TO_BOOLEAN_IC: |
531 // Clearing these is tricky and does not | 538 // Clearing these is tricky and does not |
532 // make any performance difference. | 539 // make any performance difference. |
533 return; | 540 return; |
534 default: | 541 default: |
535 UNREACHABLE(); | 542 UNREACHABLE(); |
536 } | 543 } |
537 } | 544 } |
538 | 545 |
539 | 546 |
540 template <class Nexus> | |
541 void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host, Nexus* nexus) { | |
542 switch (kind) { | |
543 case Code::CALL_IC: | |
544 return CallIC::Clear(isolate, host, nexus); | |
545 default: | |
546 UNREACHABLE(); | |
547 } | |
548 } | |
549 | |
550 | |
551 // Force instantiation of template instances for vector-based IC clearing. | |
552 template void IC::Clear(Isolate*, Code::Kind, Code*, CallICNexus*); | |
553 | |
554 | |
555 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, | 547 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, |
556 ConstantPoolArray* constant_pool) { | 548 ConstantPoolArray* constant_pool) { |
| 549 DCHECK(!FLAG_vector_ics); |
557 if (IsCleared(target)) return; | 550 if (IsCleared(target)) return; |
558 | 551 |
559 // Make sure to also clear the map used in inline fast cases. If we | 552 // Make sure to also clear the map used in inline fast cases. If we |
560 // do not clear these maps, cached code can keep objects alive | 553 // do not clear these maps, cached code can keep objects alive |
561 // through the embedded maps. | 554 // through the embedded maps. |
562 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | 555 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); |
563 } | 556 } |
564 | 557 |
565 | 558 |
| 559 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { |
| 560 if (IsCleared(nexus)) return; |
| 561 // Make sure to also clear the map used in inline fast cases. If we |
| 562 // do not clear these maps, cached code can keep objects alive |
| 563 // through the embedded maps. |
| 564 State state = nexus->StateFromFeedback(); |
| 565 nexus->ConfigurePremonomorphic(); |
| 566 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); |
| 567 } |
| 568 |
| 569 |
566 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { | 570 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { |
567 // Determine our state. | 571 // Determine our state. |
568 Object* feedback = nexus->vector()->Get(nexus->slot()); | 572 Object* feedback = nexus->vector()->Get(nexus->slot()); |
569 State state = nexus->StateFromFeedback(); | 573 State state = nexus->StateFromFeedback(); |
570 | 574 |
571 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { | 575 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { |
572 nexus->ConfigureUninitialized(); | 576 nexus->ConfigureUninitialized(); |
573 // The change in state must be processed. | 577 // The change in state must be processed. |
574 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); | 578 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); |
575 } | 579 } |
576 } | 580 } |
577 | 581 |
578 | 582 |
579 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, | 583 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, |
580 ConstantPoolArray* constant_pool) { | 584 ConstantPoolArray* constant_pool) { |
| 585 DCHECK(!FLAG_vector_ics); |
581 if (IsCleared(target)) return; | 586 if (IsCleared(target)) return; |
582 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, | 587 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, |
583 target->extra_ic_state()); | 588 target->extra_ic_state()); |
584 SetTargetAtAddress(address, code, constant_pool); | 589 SetTargetAtAddress(address, code, constant_pool); |
585 } | 590 } |
586 | 591 |
587 | 592 |
| 593 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { |
| 594 if (IsCleared(nexus)) return; |
| 595 State state = nexus->StateFromFeedback(); |
| 596 nexus->ConfigurePremonomorphic(); |
| 597 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); |
| 598 } |
| 599 |
| 600 |
588 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, | 601 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, |
589 ConstantPoolArray* constant_pool) { | 602 ConstantPoolArray* constant_pool) { |
590 if (IsCleared(target)) return; | 603 if (IsCleared(target)) return; |
591 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, | 604 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, |
592 target->extra_ic_state()); | 605 target->extra_ic_state()); |
593 SetTargetAtAddress(address, code, constant_pool); | 606 SetTargetAtAddress(address, code, constant_pool); |
594 } | 607 } |
595 | 608 |
596 | 609 |
597 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, | 610 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, |
(...skipping 30 matching lines...) Expand all Loading... |
628 | 641 |
629 static bool MigrateDeprecated(Handle<Object> object) { | 642 static bool MigrateDeprecated(Handle<Object> object) { |
630 if (!object->IsJSObject()) return false; | 643 if (!object->IsJSObject()) return false; |
631 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 644 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
632 if (!receiver->map()->is_deprecated()) return false; | 645 if (!receiver->map()->is_deprecated()) return false; |
633 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 646 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
634 return true; | 647 return true; |
635 } | 648 } |
636 | 649 |
637 | 650 |
| 651 void IC::ConfigureVectorState(IC::State new_state) { |
| 652 DCHECK(UseVector()); |
| 653 if (kind() == Code::LOAD_IC) { |
| 654 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 655 if (new_state == PREMONOMORPHIC) { |
| 656 nexus->ConfigurePremonomorphic(); |
| 657 } else if (new_state == MEGAMORPHIC) { |
| 658 nexus->ConfigureMegamorphic(); |
| 659 } else { |
| 660 UNREACHABLE(); |
| 661 } |
| 662 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 663 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 664 if (new_state == GENERIC) { |
| 665 nexus->ConfigureGeneric(); |
| 666 } else if (new_state == PREMONOMORPHIC) { |
| 667 nexus->ConfigurePremonomorphic(); |
| 668 } else if (new_state == MEGAMORPHIC) { |
| 669 nexus->ConfigureMegamorphic(); |
| 670 } else { |
| 671 UNREACHABLE(); |
| 672 } |
| 673 } else { |
| 674 UNREACHABLE(); |
| 675 } |
| 676 |
| 677 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
| 678 new_state); |
| 679 } |
| 680 |
| 681 |
| 682 void IC::ConfigureVectorState(Handle<Name> name, Handle<HeapType> type, |
| 683 Handle<Code> handler) { |
| 684 DCHECK(UseVector()); |
| 685 if (kind() == Code::LOAD_IC) { |
| 686 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 687 nexus->ConfigureMonomorphic(type, handler); |
| 688 } else { |
| 689 DCHECK(kind() == Code::KEYED_LOAD_IC); |
| 690 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 691 nexus->ConfigureMonomorphic(name, type, handler); |
| 692 } |
| 693 |
| 694 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
| 695 MONOMORPHIC); |
| 696 } |
| 697 |
| 698 |
| 699 void IC::ConfigureVectorState(Handle<Name> name, TypeHandleList* types, |
| 700 CodeHandleList* handlers) { |
| 701 DCHECK(UseVector()); |
| 702 if (kind() == Code::LOAD_IC) { |
| 703 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 704 nexus->ConfigurePolymorphic(types, handlers); |
| 705 } else { |
| 706 DCHECK(kind() == Code::KEYED_LOAD_IC); |
| 707 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 708 nexus->ConfigurePolymorphic(name, types, handlers); |
| 709 } |
| 710 |
| 711 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
| 712 POLYMORPHIC); |
| 713 } |
| 714 |
| 715 |
638 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { | 716 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { |
639 // If the object is undefined or null it's illegal to try to get any | 717 // If the object is undefined or null it's illegal to try to get any |
640 // of its properties; throw a TypeError in that case. | 718 // of its properties; throw a TypeError in that case. |
641 if (object->IsUndefined() || object->IsNull()) { | 719 if (object->IsUndefined() || object->IsNull()) { |
642 return TypeError("non_object_property_load", object, name); | 720 return TypeError("non_object_property_load", object, name); |
643 } | 721 } |
644 | 722 |
645 // Check if the name is trivially convertible to an index and get | 723 // Check if the name is trivially convertible to an index and get |
646 // the element or char if so. | 724 // the element or char if so. |
647 uint32_t index; | 725 uint32_t index; |
648 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 726 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
649 // Rewrite to the generic keyed load stub. | 727 // Rewrite to the generic keyed load stub. |
650 if (FLAG_use_ic) { | 728 if (FLAG_use_ic) { |
651 set_target(*KeyedLoadIC::generic_stub(isolate())); | 729 if (UseVector()) { |
| 730 ConfigureVectorState(GENERIC); |
| 731 } else { |
| 732 set_target(*KeyedLoadIC::generic_stub(isolate())); |
| 733 } |
652 TRACE_IC("LoadIC", name); | 734 TRACE_IC("LoadIC", name); |
653 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 735 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
654 } | 736 } |
655 Handle<Object> result; | 737 Handle<Object> result; |
656 ASSIGN_RETURN_ON_EXCEPTION( | 738 ASSIGN_RETURN_ON_EXCEPTION( |
657 isolate(), result, | 739 isolate(), result, |
658 Runtime::GetElementOrCharAt(isolate(), object, index), Object); | 740 Runtime::GetElementOrCharAt(isolate(), object, index), Object); |
659 return result; | 741 return result; |
660 } | 742 } |
661 | 743 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 *type->AsClass()->Map())) { | 828 *type->AsClass()->Map())) { |
747 handler_to_overwrite = i; | 829 handler_to_overwrite = i; |
748 } | 830 } |
749 } | 831 } |
750 | 832 |
751 int number_of_valid_types = | 833 int number_of_valid_types = |
752 number_of_types - deprecated_types - (handler_to_overwrite != -1); | 834 number_of_types - deprecated_types - (handler_to_overwrite != -1); |
753 | 835 |
754 if (number_of_valid_types >= 4) return false; | 836 if (number_of_valid_types >= 4) return false; |
755 if (number_of_types == 0) return false; | 837 if (number_of_types == 0) return false; |
756 if (!target()->FindHandlers(&handlers, types.length())) return false; | 838 if (UseVector()) { |
| 839 if (!nexus()->FindHandlers(&handlers, types.length())) return false; |
| 840 } else { |
| 841 if (!target()->FindHandlers(&handlers, types.length())) return false; |
| 842 } |
757 | 843 |
758 number_of_valid_types++; | 844 number_of_valid_types++; |
759 if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false; | 845 if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false; |
760 Handle<Code> ic; | 846 Handle<Code> ic; |
761 if (number_of_valid_types == 1) { | 847 if (number_of_valid_types == 1) { |
762 ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code, | 848 if (UseVector()) { |
763 extra_ic_state()); | 849 ConfigureVectorState(name, receiver_type(), code); |
| 850 } else { |
| 851 ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code, |
| 852 extra_ic_state()); |
| 853 } |
764 } else { | 854 } else { |
765 if (handler_to_overwrite >= 0) { | 855 if (handler_to_overwrite >= 0) { |
766 handlers.Set(handler_to_overwrite, code); | 856 handlers.Set(handler_to_overwrite, code); |
767 if (!type->NowIs(types.at(handler_to_overwrite))) { | 857 if (!type->NowIs(types.at(handler_to_overwrite))) { |
768 types.Set(handler_to_overwrite, type); | 858 types.Set(handler_to_overwrite, type); |
769 } | 859 } |
770 } else { | 860 } else { |
771 types.Add(type); | 861 types.Add(type); |
772 handlers.Add(code); | 862 handlers.Add(code); |
773 } | 863 } |
774 ic = PropertyICCompiler::ComputePolymorphic(kind(), &types, &handlers, | 864 |
775 number_of_valid_types, name, | 865 if (UseVector()) { |
776 extra_ic_state()); | 866 ConfigureVectorState(name, &types, &handlers); |
| 867 } else { |
| 868 ic = PropertyICCompiler::ComputePolymorphic(kind(), &types, &handlers, |
| 869 number_of_valid_types, name, |
| 870 extra_ic_state()); |
| 871 } |
777 } | 872 } |
778 set_target(*ic); | 873 |
| 874 if (!UseVector()) set_target(*ic); |
779 return true; | 875 return true; |
780 } | 876 } |
781 | 877 |
782 | 878 |
783 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { | 879 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { |
784 return object->IsJSGlobalObject() | 880 return object->IsJSGlobalObject() |
785 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate) | 881 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate) |
786 : HeapType::NowOf(object, isolate); | 882 : HeapType::NowOf(object, isolate); |
787 } | 883 } |
788 | 884 |
(...skipping 27 matching lines...) Expand all Loading... |
816 | 912 |
817 template Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone); | 913 template Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone); |
818 | 914 |
819 | 915 |
820 template Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, | 916 template Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, |
821 Isolate* region); | 917 Isolate* region); |
822 | 918 |
823 | 919 |
824 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { | 920 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { |
825 DCHECK(handler->is_handler()); | 921 DCHECK(handler->is_handler()); |
826 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( | 922 if (UseVector()) { |
827 kind(), name, receiver_type(), handler, extra_ic_state()); | 923 ConfigureVectorState(name, receiver_type(), handler); |
828 set_target(*ic); | 924 } else { |
| 925 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( |
| 926 kind(), name, receiver_type(), handler, extra_ic_state()); |
| 927 set_target(*ic); |
| 928 } |
829 } | 929 } |
830 | 930 |
831 | 931 |
832 void IC::CopyICToMegamorphicCache(Handle<Name> name) { | 932 void IC::CopyICToMegamorphicCache(Handle<Name> name) { |
833 TypeHandleList types; | 933 TypeHandleList types; |
834 CodeHandleList handlers; | 934 CodeHandleList handlers; |
835 TargetTypes(&types); | 935 TargetTypes(&types); |
836 if (!target()->FindHandlers(&handlers, types.length())) return; | 936 if (!target()->FindHandlers(&handlers, types.length())) return; |
837 for (int i = 0; i < types.length(); i++) { | 937 for (int i = 0; i < types.length(); i++) { |
838 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); | 938 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); |
(...skipping 24 matching lines...) Expand all Loading... |
863 break; | 963 break; |
864 case PROTOTYPE_FAILURE: | 964 case PROTOTYPE_FAILURE: |
865 case MONOMORPHIC: | 965 case MONOMORPHIC: |
866 case POLYMORPHIC: | 966 case POLYMORPHIC: |
867 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { | 967 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { |
868 if (UpdatePolymorphicIC(name, code)) break; | 968 if (UpdatePolymorphicIC(name, code)) break; |
869 // For keyed stubs, we can't know whether old handlers were for the | 969 // For keyed stubs, we can't know whether old handlers were for the |
870 // same key. | 970 // same key. |
871 CopyICToMegamorphicCache(name); | 971 CopyICToMegamorphicCache(name); |
872 } | 972 } |
873 set_target(*megamorphic_stub()); | 973 if (UseVector()) { |
| 974 ConfigureVectorState(MEGAMORPHIC); |
| 975 } else { |
| 976 set_target(*megamorphic_stub()); |
| 977 } |
874 // Fall through. | 978 // Fall through. |
875 case MEGAMORPHIC: | 979 case MEGAMORPHIC: |
876 UpdateMegamorphicCache(*receiver_type(), *name, *code); | 980 UpdateMegamorphicCache(*receiver_type(), *name, *code); |
877 // Indicate that we've handled this case. | 981 // Indicate that we've handled this case. |
878 target_set_ = true; | 982 target_set_ = true; |
879 break; | 983 break; |
880 case DEBUG_STUB: | 984 case DEBUG_STUB: |
881 break; | 985 break; |
882 case DEFAULT: | 986 case DEFAULT: |
883 UNREACHABLE(); | 987 UNREACHABLE(); |
884 break; | 988 break; |
885 case GENERIC: | 989 case GENERIC: |
886 // The generic keyed store stub re-uses store handlers, which can miss. | 990 // The generic keyed store stub re-uses store handlers, which can miss. |
887 // That's ok, no reason to do anything. | 991 // That's ok, no reason to do anything. |
888 DCHECK(target()->kind() == Code::KEYED_STORE_IC); | 992 DCHECK(target()->kind() == Code::KEYED_STORE_IC); |
889 break; | 993 break; |
890 } | 994 } |
891 } | 995 } |
892 | 996 |
893 | 997 |
894 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, | 998 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, |
895 ExtraICState extra_state) { | 999 ExtraICState extra_state) { |
| 1000 if (FLAG_vector_ics) { |
| 1001 return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); |
| 1002 } |
| 1003 |
896 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); | 1004 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); |
897 } | 1005 } |
898 | 1006 |
899 | 1007 |
900 Handle<Code> LoadIC::initialize_stub_in_optimized_code( | 1008 Handle<Code> LoadIC::initialize_stub_in_optimized_code( |
901 Isolate* isolate, ExtraICState extra_state) { | 1009 Isolate* isolate, ExtraICState extra_state) { |
902 if (FLAG_vector_ics) { | 1010 if (FLAG_vector_ics) { |
903 return VectorLoadStub(isolate, LoadICState(extra_state)).GetCode(); | 1011 return VectorLoadStub(isolate, LoadICState(extra_state)).GetCode(); |
904 } | 1012 } |
905 return initialize_stub(isolate, extra_state); | 1013 return initialize_stub(isolate, extra_state); |
(...skipping 23 matching lines...) Expand all Loading... |
929 return stub.GetCode(); | 1037 return stub.GetCode(); |
930 } else { | 1038 } else { |
931 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | 1039 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
932 return KeyedLoadIC::generic_stub(isolate()); | 1040 return KeyedLoadIC::generic_stub(isolate()); |
933 } | 1041 } |
934 } | 1042 } |
935 | 1043 |
936 | 1044 |
937 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 1045 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
938 ExtraICState extra_state) { | 1046 ExtraICState extra_state) { |
| 1047 DCHECK(!FLAG_vector_ics); |
939 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); | 1048 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); |
940 } | 1049 } |
941 | 1050 |
942 | 1051 |
943 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { | 1052 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { |
944 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); | 1053 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); |
945 } | 1054 } |
946 | 1055 |
947 | 1056 |
948 Handle<Code> LoadIC::pre_monomorphic_stub() const { | 1057 Handle<Code> LoadIC::pre_monomorphic_stub() const { |
949 if (kind() == Code::LOAD_IC) { | 1058 if (kind() == Code::LOAD_IC) { |
950 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); | 1059 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); |
951 } else { | 1060 } else { |
952 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | 1061 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
953 return KeyedLoadIC::pre_monomorphic_stub(isolate()); | 1062 return KeyedLoadIC::pre_monomorphic_stub(isolate()); |
954 } | 1063 } |
955 } | 1064 } |
956 | 1065 |
957 | 1066 |
958 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { | 1067 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { |
959 LoadFieldStub stub(isolate(), index); | 1068 LoadFieldStub stub(isolate(), index); |
960 return stub.GetCode(); | 1069 return stub.GetCode(); |
961 } | 1070 } |
962 | 1071 |
963 | 1072 |
964 void LoadIC::UpdateCaches(LookupIterator* lookup) { | 1073 void LoadIC::UpdateCaches(LookupIterator* lookup) { |
965 if (state() == UNINITIALIZED) { | 1074 if (state() == UNINITIALIZED) { |
966 // This is the first time we execute this inline cache. Set the target to | 1075 // This is the first time we execute this inline cache. Set the target to |
967 // the pre monomorphic stub to delay setting the monomorphic state. | 1076 // the pre monomorphic stub to delay setting the monomorphic state. |
968 set_target(*pre_monomorphic_stub()); | 1077 if (UseVector()) { |
| 1078 ConfigureVectorState(PREMONOMORPHIC); |
| 1079 } else { |
| 1080 set_target(*pre_monomorphic_stub()); |
| 1081 } |
969 TRACE_IC("LoadIC", lookup->name()); | 1082 TRACE_IC("LoadIC", lookup->name()); |
970 return; | 1083 return; |
971 } | 1084 } |
972 | 1085 |
973 Handle<Code> code; | 1086 Handle<Code> code; |
974 if (lookup->state() == LookupIterator::JSPROXY || | 1087 if (lookup->state() == LookupIterator::JSPROXY || |
975 lookup->state() == LookupIterator::ACCESS_CHECK) { | 1088 lookup->state() == LookupIterator::ACCESS_CHECK) { |
976 code = slow_stub(); | 1089 code = slow_stub(); |
977 } else if (!lookup->IsFound()) { | 1090 } else if (!lookup->IsFound()) { |
978 if (kind() == Code::LOAD_IC) { | 1091 if (kind() == Code::LOAD_IC) { |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1221 } | 1334 } |
1222 } | 1335 } |
1223 } else if (key->IsUndefined()) { | 1336 } else if (key->IsUndefined()) { |
1224 key = isolate->factory()->undefined_string(); | 1337 key = isolate->factory()->undefined_string(); |
1225 } | 1338 } |
1226 return key; | 1339 return key; |
1227 } | 1340 } |
1228 | 1341 |
1229 | 1342 |
1230 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { | 1343 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { |
| 1344 Handle<Code> null_handle; |
1231 Handle<Map> receiver_map(receiver->map(), isolate()); | 1345 Handle<Map> receiver_map(receiver->map(), isolate()); |
1232 MapHandleList target_receiver_maps; | 1346 MapHandleList target_receiver_maps; |
1233 TargetMaps(&target_receiver_maps); | 1347 TargetMaps(&target_receiver_maps); |
1234 | 1348 |
| 1349 |
1235 if (target_receiver_maps.length() == 0) { | 1350 if (target_receiver_maps.length() == 0) { |
| 1351 if (FLAG_vector_ics) { |
| 1352 Handle<Code> handler = |
| 1353 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); |
| 1354 ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler); |
| 1355 return null_handle; |
| 1356 } |
1236 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 1357 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
1237 } | 1358 } |
1238 | 1359 |
1239 // The first time a receiver is seen that is a transitioned version of the | 1360 // The first time a receiver is seen that is a transitioned version of the |
1240 // previous monomorphic receiver type, assume the new ElementsKind is the | 1361 // previous monomorphic receiver type, assume the new ElementsKind is the |
1241 // monomorphic type. This benefits global arrays that only transition | 1362 // monomorphic type. This benefits global arrays that only transition |
1242 // once, and all call sites accessing them are faster if they remain | 1363 // once, and all call sites accessing them are faster if they remain |
1243 // monomorphic. If this optimistic assumption is not true, the IC will | 1364 // monomorphic. If this optimistic assumption is not true, the IC will |
1244 // miss again and it will become polymorphic and support both the | 1365 // miss again and it will become polymorphic and support both the |
1245 // untransitioned and transitioned maps. | 1366 // untransitioned and transitioned maps. |
1246 if (state() == MONOMORPHIC && !receiver->IsString() && | 1367 if (state() == MONOMORPHIC && !receiver->IsString() && |
1247 IsMoreGeneralElementsKindTransition( | 1368 IsMoreGeneralElementsKindTransition( |
1248 target_receiver_maps.at(0)->elements_kind(), | 1369 target_receiver_maps.at(0)->elements_kind(), |
1249 Handle<JSObject>::cast(receiver)->GetElementsKind())) { | 1370 Handle<JSObject>::cast(receiver)->GetElementsKind())) { |
| 1371 if (FLAG_vector_ics) { |
| 1372 Handle<Code> handler = |
| 1373 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); |
| 1374 ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler); |
| 1375 return null_handle; |
| 1376 } |
1250 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 1377 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
1251 } | 1378 } |
1252 | 1379 |
1253 DCHECK(state() != GENERIC); | 1380 DCHECK(state() != GENERIC); |
1254 | 1381 |
1255 // Determine the list of receiver maps that this call site has seen, | 1382 // Determine the list of receiver maps that this call site has seen, |
1256 // adding the map that was just encountered. | 1383 // adding the map that was just encountered. |
1257 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1384 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
1258 // If the miss wasn't due to an unseen map, a polymorphic stub | 1385 // If the miss wasn't due to an unseen map, a polymorphic stub |
1259 // won't help, use the generic stub. | 1386 // won't help, use the generic stub. |
1260 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); | 1387 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); |
| 1388 if (FLAG_vector_ics) { |
| 1389 ConfigureVectorState(GENERIC); |
| 1390 return null_handle; |
| 1391 } |
1261 return generic_stub(); | 1392 return generic_stub(); |
1262 } | 1393 } |
1263 | 1394 |
1264 // If the maximum number of receiver maps has been exceeded, use the generic | 1395 // If the maximum number of receiver maps has been exceeded, use the generic |
1265 // version of the IC. | 1396 // version of the IC. |
1266 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1397 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1267 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1398 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
| 1399 if (FLAG_vector_ics) { |
| 1400 ConfigureVectorState(GENERIC); |
| 1401 return null_handle; |
| 1402 } |
1268 return generic_stub(); | 1403 return generic_stub(); |
1269 } | 1404 } |
1270 | 1405 |
| 1406 if (FLAG_vector_ics) { |
| 1407 CodeHandleList handlers(target_receiver_maps.length()); |
| 1408 ElementHandlerCompiler compiler(isolate()); |
| 1409 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); |
| 1410 TypeHandleList types(target_receiver_maps.length()); |
| 1411 for (int i = 0; i < target_receiver_maps.length(); i++) { |
| 1412 types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); |
| 1413 } |
| 1414 ConfigureVectorState(Handle<Name>::null(), &types, &handlers); |
| 1415 return null_handle; |
| 1416 } |
| 1417 |
1271 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); | 1418 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); |
1272 } | 1419 } |
1273 | 1420 |
1274 | 1421 |
1275 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1422 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
1276 Handle<Object> key) { | 1423 Handle<Object> key) { |
1277 if (MigrateDeprecated(object)) { | 1424 if (MigrateDeprecated(object)) { |
1278 Handle<Object> result; | 1425 Handle<Object> result; |
1279 ASSIGN_RETURN_ON_EXCEPTION( | 1426 ASSIGN_RETURN_ON_EXCEPTION( |
1280 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), | 1427 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), |
(...skipping 15 matching lines...) Expand all Loading... |
1296 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1443 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
1297 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { | 1444 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { |
1298 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1445 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
1299 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { | 1446 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { |
1300 stub = LoadElementStub(receiver); | 1447 stub = LoadElementStub(receiver); |
1301 } | 1448 } |
1302 } | 1449 } |
1303 } | 1450 } |
1304 | 1451 |
1305 if (!is_target_set()) { | 1452 if (!is_target_set()) { |
1306 Code* generic = *generic_stub(); | 1453 if (!FLAG_vector_ics) { |
1307 if (*stub == generic) { | 1454 Code* generic = *generic_stub(); |
1308 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1455 if (*stub == generic) { |
| 1456 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1457 } |
| 1458 |
| 1459 set_target(*stub); |
1309 } | 1460 } |
1310 set_target(*stub); | |
1311 TRACE_IC("LoadIC", key); | 1461 TRACE_IC("LoadIC", key); |
1312 } | 1462 } |
1313 | 1463 |
1314 if (!load_handle.is_null()) return load_handle; | 1464 if (!load_handle.is_null()) return load_handle; |
1315 Handle<Object> result; | 1465 Handle<Object> result; |
1316 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, | 1466 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
1317 Runtime::GetObjectProperty(isolate(), object, key), | 1467 Runtime::GetObjectProperty(isolate(), object, key), |
1318 Object); | 1468 Object); |
1319 return result; | 1469 return result; |
1320 } | 1470 } |
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2151 CallIC ic(isolate, &nexus); | 2301 CallIC ic(isolate, &nexus); |
2152 ic.PatchMegamorphic(function); | 2302 ic.PatchMegamorphic(function); |
2153 return *function; | 2303 return *function; |
2154 } | 2304 } |
2155 | 2305 |
2156 | 2306 |
2157 // Used from ic-<arch>.cc. | 2307 // Used from ic-<arch>.cc. |
2158 RUNTIME_FUNCTION(LoadIC_Miss) { | 2308 RUNTIME_FUNCTION(LoadIC_Miss) { |
2159 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2309 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2160 HandleScope scope(isolate); | 2310 HandleScope scope(isolate); |
2161 DCHECK(args.length() == 2); | |
2162 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | |
2163 Handle<Object> receiver = args.at<Object>(0); | 2311 Handle<Object> receiver = args.at<Object>(0); |
2164 Handle<Name> key = args.at<Name>(1); | 2312 Handle<Name> key = args.at<Name>(1); |
2165 ic.UpdateState(receiver, key); | |
2166 Handle<Object> result; | 2313 Handle<Object> result; |
2167 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2314 |
| 2315 if (FLAG_vector_ics) { |
| 2316 DCHECK(args.length() == 4); |
| 2317 Handle<Smi> slot = args.at<Smi>(2); |
| 2318 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
| 2319 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2320 LoadICNexus nexus(vector, vector_slot); |
| 2321 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2322 ic.UpdateState(receiver, key); |
| 2323 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2324 } else { |
| 2325 DCHECK(args.length() == 2); |
| 2326 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2327 ic.UpdateState(receiver, key); |
| 2328 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2329 } |
2168 return *result; | 2330 return *result; |
2169 } | 2331 } |
2170 | 2332 |
2171 | 2333 |
2172 // Used from ic-<arch>.cc | 2334 // Used from ic-<arch>.cc |
2173 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { | 2335 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { |
2174 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2336 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2175 HandleScope scope(isolate); | 2337 HandleScope scope(isolate); |
2176 DCHECK(args.length() == 2); | |
2177 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | |
2178 Handle<Object> receiver = args.at<Object>(0); | 2338 Handle<Object> receiver = args.at<Object>(0); |
2179 Handle<Object> key = args.at<Object>(1); | 2339 Handle<Object> key = args.at<Object>(1); |
2180 ic.UpdateState(receiver, key); | |
2181 Handle<Object> result; | 2340 Handle<Object> result; |
2182 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2341 |
| 2342 if (FLAG_vector_ics) { |
| 2343 DCHECK(args.length() == 4); |
| 2344 Handle<Smi> slot = args.at<Smi>(2); |
| 2345 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
| 2346 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2347 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2348 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2349 ic.UpdateState(receiver, key); |
| 2350 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2351 } else { |
| 2352 DCHECK(args.length() == 2); |
| 2353 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2354 ic.UpdateState(receiver, key); |
| 2355 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2356 } |
| 2357 |
2183 return *result; | 2358 return *result; |
2184 } | 2359 } |
2185 | 2360 |
2186 | 2361 |
2187 RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { | 2362 RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { |
2188 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2363 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2189 HandleScope scope(isolate); | 2364 HandleScope scope(isolate); |
2190 DCHECK(args.length() == 2); | |
2191 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
2192 Handle<Object> receiver = args.at<Object>(0); | 2365 Handle<Object> receiver = args.at<Object>(0); |
2193 Handle<Object> key = args.at<Object>(1); | 2366 Handle<Object> key = args.at<Object>(1); |
2194 ic.UpdateState(receiver, key); | |
2195 Handle<Object> result; | 2367 Handle<Object> result; |
2196 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2368 |
| 2369 if (FLAG_vector_ics) { |
| 2370 DCHECK(args.length() == 4); |
| 2371 Handle<Smi> slot = args.at<Smi>(2); |
| 2372 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
| 2373 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2374 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2375 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2376 ic.UpdateState(receiver, key); |
| 2377 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2378 } else { |
| 2379 DCHECK(args.length() == 2); |
| 2380 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2381 ic.UpdateState(receiver, key); |
| 2382 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2383 } |
| 2384 |
2197 return *result; | 2385 return *result; |
2198 } | 2386 } |
2199 | 2387 |
2200 | 2388 |
2201 // Used from ic-<arch>.cc. | 2389 // Used from ic-<arch>.cc. |
2202 RUNTIME_FUNCTION(StoreIC_Miss) { | 2390 RUNTIME_FUNCTION(StoreIC_Miss) { |
2203 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2391 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2204 HandleScope scope(isolate); | 2392 HandleScope scope(isolate); |
2205 DCHECK(args.length() == 3); | 2393 DCHECK(args.length() == 3); |
2206 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2394 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2678 } | 2866 } |
2679 | 2867 |
2680 return isolate->heap()->no_interceptor_result_sentinel(); | 2868 return isolate->heap()->no_interceptor_result_sentinel(); |
2681 } | 2869 } |
2682 | 2870 |
2683 | 2871 |
2684 static Object* ThrowReferenceError(Isolate* isolate, Name* name) { | 2872 static Object* ThrowReferenceError(Isolate* isolate, Name* name) { |
2685 // If the load is non-contextual, just return the undefined result. | 2873 // If the load is non-contextual, just return the undefined result. |
2686 // Note that both keyed and non-keyed loads may end up here. | 2874 // Note that both keyed and non-keyed loads may end up here. |
2687 HandleScope scope(isolate); | 2875 HandleScope scope(isolate); |
2688 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2876 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, true); |
2689 if (ic.contextual_mode() != CONTEXTUAL) { | 2877 if (ic.contextual_mode() != CONTEXTUAL) { |
2690 return isolate->heap()->undefined_value(); | 2878 return isolate->heap()->undefined_value(); |
2691 } | 2879 } |
2692 | 2880 |
2693 // Throw a reference error. | 2881 // Throw a reference error. |
2694 Handle<Name> name_handle(name); | 2882 Handle<Name> name_handle(name); |
2695 THROW_NEW_ERROR_RETURN_FAILURE( | 2883 THROW_NEW_ERROR_RETURN_FAILURE( |
2696 isolate, NewReferenceError("not_defined", HandleVector(&name_handle, 1))); | 2884 isolate, NewReferenceError("not_defined", HandleVector(&name_handle, 1))); |
2697 } | 2885 } |
2698 | 2886 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2760 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2948 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2761 isolate, result, | 2949 isolate, result, |
2762 JSObject::GetElementWithInterceptor(receiver, receiver, index)); | 2950 JSObject::GetElementWithInterceptor(receiver, receiver, index)); |
2763 return *result; | 2951 return *result; |
2764 } | 2952 } |
2765 | 2953 |
2766 | 2954 |
2767 RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) { | 2955 RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) { |
2768 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2956 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2769 HandleScope scope(isolate); | 2957 HandleScope scope(isolate); |
2770 DCHECK(args.length() == 2); | |
2771 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
2772 Handle<Object> receiver = args.at<Object>(0); | 2958 Handle<Object> receiver = args.at<Object>(0); |
2773 Handle<Name> key = args.at<Name>(1); | 2959 Handle<Name> key = args.at<Name>(1); |
2774 ic.UpdateState(receiver, key); | |
2775 Handle<Object> result; | 2960 Handle<Object> result; |
2776 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2961 |
| 2962 if (FLAG_vector_ics) { |
| 2963 DCHECK(args.length() == 4); |
| 2964 Handle<Smi> slot = args.at<Smi>(2); |
| 2965 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
| 2966 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2967 LoadICNexus nexus(vector, vector_slot); |
| 2968 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2969 ic.UpdateState(receiver, key); |
| 2970 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2971 } else { |
| 2972 DCHECK(args.length() == 2); |
| 2973 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2974 ic.UpdateState(receiver, key); |
| 2975 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2976 } |
| 2977 |
2777 return *result; | 2978 return *result; |
2778 } | 2979 } |
2779 | 2980 |
2780 | 2981 |
2781 static const Address IC_utilities[] = { | 2982 static const Address IC_utilities[] = { |
2782 #define ADDR(name) FUNCTION_ADDR(name), | 2983 #define ADDR(name) FUNCTION_ADDR(name), |
2783 IC_UTIL_LIST(ADDR) NULL | 2984 IC_UTIL_LIST(ADDR) NULL |
2784 #undef ADDR | 2985 #undef ADDR |
2785 }; | 2986 }; |
2786 | 2987 |
2787 | 2988 |
2788 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2989 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
2789 } | 2990 } |
2790 } // namespace v8::internal | 2991 } // namespace v8::internal |
OLD | NEW |