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/ic/ic.h" | 5 #include "src/ic/ic.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api-arguments-inl.h" | 8 #include "src/api-arguments-inl.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 } | 270 } |
271 | 271 |
272 bool IC::ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name) { | 272 bool IC::ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name) { |
273 if (!RecomputeHandlerForName(name)) return false; | 273 if (!RecomputeHandlerForName(name)) return false; |
274 | 274 |
275 DCHECK(UseVector()); | 275 DCHECK(UseVector()); |
276 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map()); | 276 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map()); |
277 | 277 |
278 // This is a contextual access, always just update the handler and stay | 278 // This is a contextual access, always just update the handler and stay |
279 // monomorphic. | 279 // monomorphic. |
280 if (receiver->IsJSGlobalObject()) return true; | 280 if (kind() == Code::LOAD_GLOBAL_IC) return true; |
281 | 281 |
282 // The current map wasn't handled yet. There's no reason to stay monomorphic, | 282 // The current map wasn't handled yet. There's no reason to stay monomorphic, |
283 // *unless* we're moving from a deprecated map to its replacement, or | 283 // *unless* we're moving from a deprecated map to its replacement, or |
284 // to a more general elements kind. | 284 // to a more general elements kind. |
285 // TODO(verwaest): Check if the current map is actually what the old map | 285 // TODO(verwaest): Check if the current map is actually what the old map |
286 // would transition to. | 286 // would transition to. |
287 if (maybe_handler_.is_null()) { | 287 if (maybe_handler_.is_null()) { |
288 if (!receiver_map()->IsJSObjectMap()) return false; | 288 if (!receiver_map()->IsJSObjectMap()) return false; |
289 Map* first_map = FirstTargetMap(); | 289 Map* first_map = FirstTargetMap(); |
290 if (first_map == NULL) return false; | 290 if (first_map == NULL) return false; |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 } | 457 } |
458 } | 458 } |
459 | 459 |
460 | 460 |
461 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { | 461 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { |
462 if (IsCleared(nexus)) return; | 462 if (IsCleared(nexus)) return; |
463 nexus->ConfigurePremonomorphic(); | 463 nexus->ConfigurePremonomorphic(); |
464 OnTypeFeedbackChanged(isolate, host); | 464 OnTypeFeedbackChanged(isolate, host); |
465 } | 465 } |
466 | 466 |
| 467 void LoadGlobalIC::Clear(Isolate* isolate, Code* host, |
| 468 LoadGlobalICNexus* nexus) { |
| 469 if (IsCleared(nexus)) return; |
| 470 nexus->ConfigureUninitialized(); |
| 471 OnTypeFeedbackChanged(isolate, host); |
| 472 } |
467 | 473 |
468 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) { | 474 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) { |
469 if (IsCleared(nexus)) return; | 475 if (IsCleared(nexus)) return; |
470 nexus->ConfigurePremonomorphic(); | 476 nexus->ConfigurePremonomorphic(); |
471 OnTypeFeedbackChanged(isolate, host); | 477 OnTypeFeedbackChanged(isolate, host); |
472 } | 478 } |
473 | 479 |
474 | 480 |
475 void KeyedStoreIC::Clear(Isolate* isolate, Code* host, | 481 void KeyedStoreIC::Clear(Isolate* isolate, Code* host, |
476 KeyedStoreICNexus* nexus) { | 482 KeyedStoreICNexus* nexus) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 if (!receiver->map()->is_deprecated()) return false; | 515 if (!receiver->map()->is_deprecated()) return false; |
510 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 516 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
511 return true; | 517 return true; |
512 } | 518 } |
513 | 519 |
514 void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) { | 520 void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) { |
515 DCHECK(UseVector()); | 521 DCHECK(UseVector()); |
516 if (new_state == PREMONOMORPHIC) { | 522 if (new_state == PREMONOMORPHIC) { |
517 nexus()->ConfigurePremonomorphic(); | 523 nexus()->ConfigurePremonomorphic(); |
518 } else if (new_state == MEGAMORPHIC) { | 524 } else if (new_state == MEGAMORPHIC) { |
519 if (kind() == Code::LOAD_IC || kind() == Code::STORE_IC) { | 525 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || |
| 526 kind() == Code::STORE_IC) { |
520 nexus()->ConfigureMegamorphic(); | 527 nexus()->ConfigureMegamorphic(); |
521 } else if (kind() == Code::KEYED_LOAD_IC) { | 528 } else if (kind() == Code::KEYED_LOAD_IC) { |
522 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 529 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
523 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); | 530 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); |
524 } else { | 531 } else { |
525 DCHECK(kind() == Code::KEYED_STORE_IC); | 532 DCHECK(kind() == Code::KEYED_STORE_IC); |
526 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 533 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
527 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); | 534 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); |
528 } | 535 } |
529 } else { | 536 } else { |
530 UNREACHABLE(); | 537 UNREACHABLE(); |
531 } | 538 } |
532 | 539 |
533 vector_set_ = true; | 540 vector_set_ = true; |
534 OnTypeFeedbackChanged(isolate(), get_host()); | 541 OnTypeFeedbackChanged(isolate(), get_host()); |
535 } | 542 } |
536 | 543 |
537 | 544 |
538 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, | 545 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, |
539 Handle<Code> handler) { | 546 Handle<Code> handler) { |
540 DCHECK(UseVector()); | 547 DCHECK(UseVector()); |
541 if (kind() == Code::LOAD_IC) { | 548 if (kind() == Code::LOAD_IC) { |
542 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 549 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
543 nexus->ConfigureMonomorphic(map, handler); | 550 nexus->ConfigureMonomorphic(map, handler); |
| 551 } else if (kind() == Code::LOAD_GLOBAL_IC) { |
| 552 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); |
| 553 nexus->ConfigureMonomorphic(map, handler); |
544 } else if (kind() == Code::KEYED_LOAD_IC) { | 554 } else if (kind() == Code::KEYED_LOAD_IC) { |
545 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 555 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
546 nexus->ConfigureMonomorphic(name, map, handler); | 556 nexus->ConfigureMonomorphic(name, map, handler); |
547 } else if (kind() == Code::STORE_IC) { | 557 } else if (kind() == Code::STORE_IC) { |
548 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 558 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
549 nexus->ConfigureMonomorphic(map, handler); | 559 nexus->ConfigureMonomorphic(map, handler); |
550 } else { | 560 } else { |
551 DCHECK(kind() == Code::KEYED_STORE_IC); | 561 DCHECK(kind() == Code::KEYED_STORE_IC); |
552 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 562 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
553 nexus->ConfigureMonomorphic(name, map, handler); | 563 nexus->ConfigureMonomorphic(name, map, handler); |
554 } | 564 } |
555 | 565 |
556 vector_set_ = true; | 566 vector_set_ = true; |
557 OnTypeFeedbackChanged(isolate(), get_host()); | 567 OnTypeFeedbackChanged(isolate(), get_host()); |
558 } | 568 } |
559 | 569 |
560 | 570 |
561 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, | 571 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, |
562 CodeHandleList* handlers) { | 572 CodeHandleList* handlers) { |
563 DCHECK(UseVector()); | 573 DCHECK(UseVector()); |
564 if (kind() == Code::LOAD_IC) { | 574 if (kind() == Code::LOAD_IC) { |
565 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 575 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
566 nexus->ConfigurePolymorphic(maps, handlers); | 576 nexus->ConfigurePolymorphic(maps, handlers); |
| 577 } else if (kind() == Code::LOAD_GLOBAL_IC) { |
| 578 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); |
| 579 nexus->ConfigurePolymorphic(maps, handlers); |
567 } else if (kind() == Code::KEYED_LOAD_IC) { | 580 } else if (kind() == Code::KEYED_LOAD_IC) { |
568 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 581 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
569 nexus->ConfigurePolymorphic(name, maps, handlers); | 582 nexus->ConfigurePolymorphic(name, maps, handlers); |
570 } else if (kind() == Code::STORE_IC) { | 583 } else if (kind() == Code::STORE_IC) { |
571 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 584 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
572 nexus->ConfigurePolymorphic(maps, handlers); | 585 nexus->ConfigurePolymorphic(maps, handlers); |
573 } else { | 586 } else { |
574 DCHECK(kind() == Code::KEYED_STORE_IC); | 587 DCHECK(kind() == Code::KEYED_STORE_IC); |
575 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 588 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
576 nexus->ConfigurePolymorphic(name, maps, handlers); | 589 nexus->ConfigurePolymorphic(name, maps, handlers); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 } | 627 } |
615 Handle<Object> result; | 628 Handle<Object> result; |
616 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, | 629 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
617 Object::GetElement(isolate(), object, index), | 630 Object::GetElement(isolate(), object, index), |
618 Object); | 631 Object); |
619 return result; | 632 return result; |
620 } | 633 } |
621 | 634 |
622 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; | 635 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; |
623 | 636 |
624 if (object->IsJSGlobalObject() && name->IsString()) { | |
625 // Look up in script context table. | |
626 Handle<String> str_name = Handle<String>::cast(name); | |
627 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object); | |
628 Handle<ScriptContextTable> script_contexts( | |
629 global->native_context()->script_context_table()); | |
630 | |
631 ScriptContextTable::LookupResult lookup_result; | |
632 if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) { | |
633 Handle<Object> result = | |
634 FixedArray::get(*ScriptContextTable::GetContext( | |
635 script_contexts, lookup_result.context_index), | |
636 lookup_result.slot_index, isolate()); | |
637 if (result->IsTheHole(isolate())) { | |
638 // Do not install stubs and stay pre-monomorphic for | |
639 // uninitialized accesses. | |
640 return ReferenceError(name); | |
641 } | |
642 | |
643 if (use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) { | |
644 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub); | |
645 LoadScriptContextFieldStub stub(isolate(), &lookup_result); | |
646 PatchCache(name, stub.GetCode()); | |
647 } | |
648 return result; | |
649 } | |
650 } | |
651 | |
652 if (state() != UNINITIALIZED) { | 637 if (state() != UNINITIALIZED) { |
653 JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate()); | 638 JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate()); |
654 update_receiver_map(object); | 639 update_receiver_map(object); |
655 } | 640 } |
656 // Named lookup in the object. | 641 // Named lookup in the object. |
657 LookupIterator it(object, name); | 642 LookupIterator it(object, name); |
658 LookupForRead(&it); | 643 LookupForRead(&it); |
659 | 644 |
660 if (it.IsFound() || !ShouldThrowReferenceError(object)) { | 645 if (it.IsFound() || !ShouldThrowReferenceError()) { |
661 // Update inline cache and stub cache. | 646 // Update inline cache and stub cache. |
662 if (use_ic) UpdateCaches(&it); | 647 if (use_ic) UpdateCaches(&it); |
663 | 648 |
664 // Get the property. | 649 // Get the property. |
665 Handle<Object> result; | 650 Handle<Object> result; |
666 | 651 |
667 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it), | 652 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it), |
668 Object); | 653 Object); |
669 if (it.IsFound()) { | 654 if (it.IsFound()) { |
670 return result; | 655 return result; |
671 } else if (!ShouldThrowReferenceError(object)) { | 656 } else if (!ShouldThrowReferenceError()) { |
672 LOG(isolate(), SuspectReadEvent(*name, *object)); | 657 LOG(isolate(), SuspectReadEvent(*name, *object)); |
673 return result; | 658 return result; |
674 } | 659 } |
675 } | 660 } |
676 return ReferenceError(name); | 661 return ReferenceError(name); |
677 } | 662 } |
678 | 663 |
| 664 MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) { |
| 665 Handle<JSGlobalObject> global = isolate()->global_object(); |
| 666 |
| 667 if (name->IsString()) { |
| 668 // Look up in script context table. |
| 669 Handle<String> str_name = Handle<String>::cast(name); |
| 670 Handle<ScriptContextTable> script_contexts( |
| 671 global->native_context()->script_context_table()); |
| 672 |
| 673 ScriptContextTable::LookupResult lookup_result; |
| 674 if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) { |
| 675 Handle<Object> result = |
| 676 FixedArray::get(*ScriptContextTable::GetContext( |
| 677 script_contexts, lookup_result.context_index), |
| 678 lookup_result.slot_index, isolate()); |
| 679 if (result->IsTheHole(isolate())) { |
| 680 // Do not install stubs and stay pre-monomorphic for |
| 681 // uninitialized accesses. |
| 682 return ReferenceError(name); |
| 683 } |
| 684 |
| 685 if (FLAG_use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) { |
| 686 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub); |
| 687 LoadScriptContextFieldStub stub(isolate(), &lookup_result); |
| 688 PatchCache(name, stub.GetCode()); |
| 689 TRACE_IC("LoadGlobalIC", name); |
| 690 } |
| 691 return result; |
| 692 } |
| 693 } |
| 694 return LoadIC::Load(global, name); |
| 695 } |
679 | 696 |
680 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 697 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, |
681 Handle<Map> new_receiver_map) { | 698 Handle<Map> new_receiver_map) { |
682 DCHECK(!new_receiver_map.is_null()); | 699 DCHECK(!new_receiver_map.is_null()); |
683 for (int current = 0; current < receiver_maps->length(); ++current) { | 700 for (int current = 0; current < receiver_maps->length(); ++current) { |
684 if (!receiver_maps->at(current).is_null() && | 701 if (!receiver_maps->at(current).is_null() && |
685 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 702 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
686 return false; | 703 return false; |
687 } | 704 } |
688 } | 705 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 } | 833 } |
817 | 834 |
818 Handle<Code> LoadIC::initialize_stub_in_optimized_code( | 835 Handle<Code> LoadIC::initialize_stub_in_optimized_code( |
819 Isolate* isolate, ExtraICState extra_state) { | 836 Isolate* isolate, ExtraICState extra_state) { |
820 if (FLAG_tf_load_ic_stub) { | 837 if (FLAG_tf_load_ic_stub) { |
821 return LoadICTFStub(isolate, LoadICState(extra_state)).GetCode(); | 838 return LoadICTFStub(isolate, LoadICState(extra_state)).GetCode(); |
822 } | 839 } |
823 return LoadICStub(isolate, LoadICState(extra_state)).GetCode(); | 840 return LoadICStub(isolate, LoadICState(extra_state)).GetCode(); |
824 } | 841 } |
825 | 842 |
| 843 Handle<Code> LoadGlobalIC::initialize_stub_in_optimized_code( |
| 844 Isolate* isolate, ExtraICState extra_state) { |
| 845 return LoadGlobalICStub(isolate, LoadICState(extra_state)).GetCode(); |
| 846 } |
| 847 |
826 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code( | 848 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code( |
827 Isolate* isolate, ExtraICState extra_state) { | 849 Isolate* isolate, ExtraICState extra_state) { |
828 return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode(); | 850 return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode(); |
829 } | 851 } |
830 | 852 |
831 Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code( | 853 Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code( |
832 Isolate* isolate, LanguageMode language_mode) { | 854 Isolate* isolate, LanguageMode language_mode) { |
833 StoreICState state = StoreICState(language_mode); | 855 StoreICState state = StoreICState(language_mode); |
834 return VectorKeyedStoreICStub(isolate, state).GetCode(); | 856 return VectorKeyedStoreICStub(isolate, state).GetCode(); |
835 } | 857 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 919 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
898 TRACE_IC("LoadIC", lookup->name()); | 920 TRACE_IC("LoadIC", lookup->name()); |
899 return; | 921 return; |
900 } | 922 } |
901 | 923 |
902 Handle<Code> code; | 924 Handle<Code> code; |
903 if (lookup->state() == LookupIterator::JSPROXY || | 925 if (lookup->state() == LookupIterator::JSPROXY || |
904 lookup->state() == LookupIterator::ACCESS_CHECK) { | 926 lookup->state() == LookupIterator::ACCESS_CHECK) { |
905 code = slow_stub(); | 927 code = slow_stub(); |
906 } else if (!lookup->IsFound()) { | 928 } else if (!lookup->IsFound()) { |
907 if (kind() == Code::LOAD_IC) { | 929 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) { |
908 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), | 930 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), |
909 receiver_map()); | 931 receiver_map()); |
910 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. | 932 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. |
911 if (code.is_null()) code = slow_stub(); | 933 if (code.is_null()) code = slow_stub(); |
912 } else { | 934 } else { |
913 code = slow_stub(); | 935 code = slow_stub(); |
914 } | 936 } |
915 } else { | 937 } else { |
916 if (lookup->state() == LookupIterator::ACCESSOR) { | 938 if (lookup->state() == LookupIterator::ACCESSOR) { |
917 if (!IsCompatibleReceiver(lookup, receiver_map())) { | 939 if (!IsCompatibleReceiver(lookup, receiver_map())) { |
(...skipping 29 matching lines...) Expand all Loading... |
947 // Try to find a globally shared handler stub. | 969 // Try to find a globally shared handler stub. |
948 Handle<Code> code = GetMapIndependentHandler(lookup); | 970 Handle<Code> code = GetMapIndependentHandler(lookup); |
949 if (!code.is_null()) return code; | 971 if (!code.is_null()) return code; |
950 | 972 |
951 // Otherwise check the map's handler cache for a map-specific handler, and | 973 // Otherwise check the map's handler cache for a map-specific handler, and |
952 // compile one if the cache comes up empty. | 974 // compile one if the cache comes up empty. |
953 bool receiver_is_holder = | 975 bool receiver_is_holder = |
954 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); | 976 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); |
955 CacheHolderFlag flag; | 977 CacheHolderFlag flag; |
956 Handle<Map> stub_holder_map; | 978 Handle<Map> stub_holder_map; |
957 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) { | 979 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || |
| 980 kind() == Code::KEYED_LOAD_IC) { |
958 stub_holder_map = IC::GetHandlerCacheHolder( | 981 stub_holder_map = IC::GetHandlerCacheHolder( |
959 receiver_map(), receiver_is_holder, isolate(), &flag); | 982 receiver_map(), receiver_is_holder, isolate(), &flag); |
960 } else { | 983 } else { |
961 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); | 984 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); |
962 // Store handlers cannot be cached on prototypes. | 985 // Store handlers cannot be cached on prototypes. |
963 flag = kCacheOnReceiver; | 986 flag = kCacheOnReceiver; |
964 stub_holder_map = receiver_map(); | 987 stub_holder_map = receiver_map(); |
965 } | 988 } |
966 | 989 |
967 code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(), | 990 code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(), |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 } | 1105 } |
1083 break; // Custom-compiled handler. | 1106 break; // Custom-compiled handler. |
1084 } | 1107 } |
1085 } | 1108 } |
1086 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); | 1109 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
1087 return slow_stub(); | 1110 return slow_stub(); |
1088 } | 1111 } |
1089 | 1112 |
1090 case LookupIterator::DATA: { | 1113 case LookupIterator::DATA: { |
1091 if (lookup->is_dictionary_holder()) { | 1114 if (lookup->is_dictionary_holder()) { |
1092 if (kind() != Code::LOAD_IC) { | 1115 if (kind() != Code::LOAD_IC && kind() != Code::LOAD_GLOBAL_IC) { |
1093 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); | 1116 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
1094 return slow_stub(); | 1117 return slow_stub(); |
1095 } | 1118 } |
1096 if (holder->IsJSGlobalObject()) { | 1119 if (holder->IsJSGlobalObject()) { |
1097 break; // Custom-compiled handler. | 1120 break; // Custom-compiled handler. |
1098 } | 1121 } |
1099 // There is only one shared stub for loading normalized | 1122 // There is only one shared stub for loading normalized |
1100 // properties. It does not traverse the prototype chain, so the | 1123 // properties. It does not traverse the prototype chain, so the |
1101 // property must be found in the object for the stub to be | 1124 // property must be found in the object for the stub to be |
1102 // applicable. | 1125 // applicable. |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1219 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1242 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
1220 Handle<Code> code = compiler.CompileLoadCallback(lookup->name(), info); | 1243 Handle<Code> code = compiler.CompileLoadCallback(lookup->name(), info); |
1221 if (FLAG_runtime_call_stats) return slow_stub(); | 1244 if (FLAG_runtime_call_stats) return slow_stub(); |
1222 return code; | 1245 return code; |
1223 } | 1246 } |
1224 UNREACHABLE(); | 1247 UNREACHABLE(); |
1225 } | 1248 } |
1226 | 1249 |
1227 case LookupIterator::DATA: { | 1250 case LookupIterator::DATA: { |
1228 if (lookup->is_dictionary_holder()) { | 1251 if (lookup->is_dictionary_holder()) { |
1229 DCHECK(kind() == Code::LOAD_IC); | 1252 DCHECK(kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC); |
1230 DCHECK(holder->IsJSGlobalObject()); | 1253 DCHECK(holder->IsJSGlobalObject()); |
1231 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal); | 1254 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal); |
1232 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1255 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
1233 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | 1256 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
1234 Handle<Code> code = compiler.CompileLoadGlobal( | 1257 Handle<Code> code = compiler.CompileLoadGlobal( |
1235 cell, lookup->name(), lookup->IsConfigurable()); | 1258 cell, lookup->name(), lookup->IsConfigurable()); |
1236 return code; | 1259 return code; |
1237 } | 1260 } |
1238 | 1261 |
1239 // -------------- Fields -------------- | 1262 // -------------- Fields -------------- |
(...skipping 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2261 Handle<Object> receiver = args.at<Object>(0); | 2284 Handle<Object> receiver = args.at<Object>(0); |
2262 Handle<Name> key = args.at<Name>(1); | 2285 Handle<Name> key = args.at<Name>(1); |
2263 | 2286 |
2264 DCHECK_EQ(4, args.length()); | 2287 DCHECK_EQ(4, args.length()); |
2265 Handle<Smi> slot = args.at<Smi>(2); | 2288 Handle<Smi> slot = args.at<Smi>(2); |
2266 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 2289 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
2267 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); | 2290 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); |
2268 // A monomorphic or polymorphic KeyedLoadIC with a string key can call the | 2291 // A monomorphic or polymorphic KeyedLoadIC with a string key can call the |
2269 // LoadIC miss handler if the handler misses. Since the vector Nexus is | 2292 // LoadIC miss handler if the handler misses. Since the vector Nexus is |
2270 // set up outside the IC, handle that here. | 2293 // set up outside the IC, handle that here. |
2271 if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::LOAD_IC) { | 2294 FeedbackVectorSlotKind kind = vector->GetKind(vector_slot); |
| 2295 if (kind == FeedbackVectorSlotKind::LOAD_IC) { |
2272 LoadICNexus nexus(vector, vector_slot); | 2296 LoadICNexus nexus(vector, vector_slot); |
2273 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2297 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
2274 ic.UpdateState(receiver, key); | 2298 ic.UpdateState(receiver, key); |
2275 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); | 2299 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); |
| 2300 |
| 2301 } else if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) { |
| 2302 DCHECK_EQ(*isolate->global_object(), *receiver); |
| 2303 LoadGlobalICNexus nexus(vector, vector_slot); |
| 2304 LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2305 ic.UpdateState(receiver, key); |
| 2306 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key)); |
| 2307 |
2276 } else { | 2308 } else { |
2277 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, | 2309 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, kind); |
2278 vector->GetKind(vector_slot)); | |
2279 KeyedLoadICNexus nexus(vector, vector_slot); | 2310 KeyedLoadICNexus nexus(vector, vector_slot); |
2280 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2311 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
2281 ic.UpdateState(receiver, key); | 2312 ic.UpdateState(receiver, key); |
2282 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); | 2313 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); |
2283 } | 2314 } |
2284 } | 2315 } |
2285 | 2316 |
| 2317 // Used from ic-<arch>.cc. |
| 2318 RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) { |
| 2319 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2320 HandleScope scope(isolate); |
| 2321 DCHECK_EQ(3, args.length()); |
| 2322 Handle<JSGlobalObject> global = isolate->global_object(); |
| 2323 Handle<Name> name = args.at<Name>(0); |
| 2324 Handle<Smi> slot = args.at<Smi>(1); |
| 2325 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); |
| 2326 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); |
| 2327 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, |
| 2328 vector->GetKind(vector_slot)); |
| 2329 |
| 2330 LoadGlobalICNexus nexus(vector, vector_slot); |
| 2331 LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2332 ic.UpdateState(global, name); |
| 2333 |
| 2334 Handle<Object> result; |
| 2335 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(name)); |
| 2336 return *result; |
| 2337 } |
2286 | 2338 |
2287 // Used from ic-<arch>.cc | 2339 // Used from ic-<arch>.cc |
2288 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) { | 2340 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) { |
2289 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2341 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2290 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss"); | 2342 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss"); |
2291 HandleScope scope(isolate); | 2343 HandleScope scope(isolate); |
2292 Handle<Object> receiver = args.at<Object>(0); | 2344 Handle<Object> receiver = args.at<Object>(0); |
2293 Handle<Object> key = args.at<Object>(1); | 2345 Handle<Object> key = args.at<Object>(1); |
2294 | 2346 |
2295 DCHECK(args.length() == 4); | 2347 DCHECK(args.length() == 4); |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2843 it.Next(); | 2895 it.Next(); |
2844 } | 2896 } |
2845 // Skip past the interceptor. | 2897 // Skip past the interceptor. |
2846 it.Next(); | 2898 it.Next(); |
2847 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it)); | 2899 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it)); |
2848 | 2900 |
2849 if (it.IsFound()) return *result; | 2901 if (it.IsFound()) return *result; |
2850 | 2902 |
2851 LoadICNexus nexus(isolate); | 2903 LoadICNexus nexus(isolate); |
2852 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2904 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
2853 if (!ic.ShouldThrowReferenceError(it.GetReceiver())) { | 2905 // It could actually be any kind of LoadICs here but the predicate handles |
| 2906 // all the cases properly. |
| 2907 if (!ic.ShouldThrowReferenceError()) { |
2854 return isolate->heap()->undefined_value(); | 2908 return isolate->heap()->undefined_value(); |
2855 } | 2909 } |
2856 | 2910 |
2857 // Throw a reference error. | 2911 // Throw a reference error. |
2858 THROW_NEW_ERROR_RETURN_FAILURE( | 2912 THROW_NEW_ERROR_RETURN_FAILURE( |
2859 isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name())); | 2913 isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name())); |
2860 } | 2914 } |
2861 | 2915 |
2862 | 2916 |
2863 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) { | 2917 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2951 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, | 3005 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, |
2952 vector->GetKind(vector_slot)); | 3006 vector->GetKind(vector_slot)); |
2953 KeyedLoadICNexus nexus(vector, vector_slot); | 3007 KeyedLoadICNexus nexus(vector, vector_slot); |
2954 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 3008 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
2955 ic.UpdateState(receiver, key); | 3009 ic.UpdateState(receiver, key); |
2956 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); | 3010 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); |
2957 } | 3011 } |
2958 } | 3012 } |
2959 } // namespace internal | 3013 } // namespace internal |
2960 } // namespace v8 | 3014 } // namespace v8 |
OLD | NEW |