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