| 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 OnTypeFeedbackChanged(isolate(), get_host()); | 540 OnTypeFeedbackChanged(isolate(), get_host()); |
| 535 } | 541 } |
| 536 | 542 |
| 537 | 543 |
| 538 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, | 544 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, |
| 539 Handle<Code> handler) { | 545 Handle<Code> handler) { |
| 540 DCHECK(UseVector()); | 546 DCHECK(UseVector()); |
| 541 if (kind() == Code::LOAD_IC) { | 547 if (kind() == Code::LOAD_IC) { |
| 542 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 548 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 543 nexus->ConfigureMonomorphic(map, handler); | 549 nexus->ConfigureMonomorphic(map, handler); |
| 550 } else if (kind() == Code::LOAD_GLOBAL_IC) { |
| 551 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); |
| 552 nexus->ConfigureMonomorphic(map, handler); |
| 544 } else if (kind() == Code::KEYED_LOAD_IC) { | 553 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 545 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 554 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 546 nexus->ConfigureMonomorphic(name, map, handler); | 555 nexus->ConfigureMonomorphic(name, map, handler); |
| 547 } else if (kind() == Code::STORE_IC) { | 556 } else if (kind() == Code::STORE_IC) { |
| 548 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 557 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
| 549 nexus->ConfigureMonomorphic(map, handler); | 558 nexus->ConfigureMonomorphic(map, handler); |
| 550 } else { | 559 } else { |
| 551 DCHECK(kind() == Code::KEYED_STORE_IC); | 560 DCHECK(kind() == Code::KEYED_STORE_IC); |
| 552 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 561 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
| 553 nexus->ConfigureMonomorphic(name, map, handler); | 562 nexus->ConfigureMonomorphic(name, map, handler); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 } | 623 } |
| 615 Handle<Object> result; | 624 Handle<Object> result; |
| 616 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, | 625 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
| 617 Object::GetElement(isolate(), object, index), | 626 Object::GetElement(isolate(), object, index), |
| 618 Object); | 627 Object); |
| 619 return result; | 628 return result; |
| 620 } | 629 } |
| 621 | 630 |
| 622 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; | 631 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; |
| 623 | 632 |
| 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) { | 633 if (state() != UNINITIALIZED) { |
| 653 JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate()); | 634 JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate()); |
| 654 update_receiver_map(object); | 635 update_receiver_map(object); |
| 655 } | 636 } |
| 656 // Named lookup in the object. | 637 // Named lookup in the object. |
| 657 LookupIterator it(object, name); | 638 LookupIterator it(object, name); |
| 658 LookupForRead(&it); | 639 LookupForRead(&it); |
| 659 | 640 |
| 660 if (it.IsFound() || !ShouldThrowReferenceError(object)) { | 641 if (it.IsFound() || !ShouldThrowReferenceError()) { |
| 661 // Update inline cache and stub cache. | 642 // Update inline cache and stub cache. |
| 662 if (use_ic) UpdateCaches(&it); | 643 if (use_ic) UpdateCaches(&it); |
| 663 | 644 |
| 664 // Get the property. | 645 // Get the property. |
| 665 Handle<Object> result; | 646 Handle<Object> result; |
| 666 | 647 |
| 667 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it), | 648 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it), |
| 668 Object); | 649 Object); |
| 669 if (it.IsFound()) { | 650 if (it.IsFound()) { |
| 670 return result; | 651 return result; |
| 671 } else if (!ShouldThrowReferenceError(object)) { | 652 } else if (!ShouldThrowReferenceError()) { |
| 672 LOG(isolate(), SuspectReadEvent(*name, *object)); | 653 LOG(isolate(), SuspectReadEvent(*name, *object)); |
| 673 return result; | 654 return result; |
| 674 } | 655 } |
| 675 } | 656 } |
| 676 return ReferenceError(name); | 657 return ReferenceError(name); |
| 677 } | 658 } |
| 678 | 659 |
| 660 MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) { |
| 661 Handle<JSGlobalObject> global = isolate()->global_object(); |
| 662 |
| 663 if (name->IsString()) { |
| 664 // Look up in script context table. |
| 665 Handle<String> str_name = Handle<String>::cast(name); |
| 666 Handle<ScriptContextTable> script_contexts( |
| 667 global->native_context()->script_context_table()); |
| 668 |
| 669 ScriptContextTable::LookupResult lookup_result; |
| 670 if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) { |
| 671 Handle<Object> result = |
| 672 FixedArray::get(*ScriptContextTable::GetContext( |
| 673 script_contexts, lookup_result.context_index), |
| 674 lookup_result.slot_index, isolate()); |
| 675 if (result->IsTheHole(isolate())) { |
| 676 // Do not install stubs and stay pre-monomorphic for |
| 677 // uninitialized accesses. |
| 678 return ReferenceError(name); |
| 679 } |
| 680 |
| 681 if (FLAG_use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) { |
| 682 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub); |
| 683 LoadScriptContextFieldStub stub(isolate(), &lookup_result); |
| 684 PatchCache(name, stub.GetCode()); |
| 685 TRACE_IC("LoadGlobalIC", name); |
| 686 } |
| 687 return result; |
| 688 } |
| 689 } |
| 690 return LoadIC::Load(global, name); |
| 691 } |
| 679 | 692 |
| 680 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 693 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, |
| 681 Handle<Map> new_receiver_map) { | 694 Handle<Map> new_receiver_map) { |
| 682 DCHECK(!new_receiver_map.is_null()); | 695 DCHECK(!new_receiver_map.is_null()); |
| 683 for (int current = 0; current < receiver_maps->length(); ++current) { | 696 for (int current = 0; current < receiver_maps->length(); ++current) { |
| 684 if (!receiver_maps->at(current).is_null() && | 697 if (!receiver_maps->at(current).is_null() && |
| 685 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 698 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
| 686 return false; | 699 return false; |
| 687 } | 700 } |
| 688 } | 701 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 | 799 |
| 787 | 800 |
| 788 void IC::PatchCache(Handle<Name> name, Handle<Code> code) { | 801 void IC::PatchCache(Handle<Name> name, Handle<Code> code) { |
| 789 switch (state()) { | 802 switch (state()) { |
| 790 case UNINITIALIZED: | 803 case UNINITIALIZED: |
| 791 case PREMONOMORPHIC: | 804 case PREMONOMORPHIC: |
| 792 UpdateMonomorphicIC(code, name); | 805 UpdateMonomorphicIC(code, name); |
| 793 break; | 806 break; |
| 794 case RECOMPUTE_HANDLER: | 807 case RECOMPUTE_HANDLER: |
| 795 case MONOMORPHIC: | 808 case MONOMORPHIC: |
| 809 if (kind() == Code::LOAD_GLOBAL_IC) { |
| 810 UpdateMonomorphicIC(code, name); |
| 811 break; |
| 812 } |
| 813 // Fall through. |
| 796 case POLYMORPHIC: | 814 case POLYMORPHIC: |
| 797 if (!is_keyed() || state() == RECOMPUTE_HANDLER) { | 815 if (!is_keyed() || state() == RECOMPUTE_HANDLER) { |
| 798 if (UpdatePolymorphicIC(name, code)) break; | 816 if (UpdatePolymorphicIC(name, code)) break; |
| 799 // For keyed stubs, we can't know whether old handlers were for the | 817 // For keyed stubs, we can't know whether old handlers were for the |
| 800 // same key. | 818 // same key. |
| 801 CopyICToMegamorphicCache(name); | 819 CopyICToMegamorphicCache(name); |
| 802 } | 820 } |
| 803 DCHECK(UseVector()); | 821 DCHECK(UseVector()); |
| 804 ConfigureVectorState(MEGAMORPHIC, name); | 822 ConfigureVectorState(MEGAMORPHIC, name); |
| 805 // Fall through. | 823 // Fall through. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 816 } | 834 } |
| 817 | 835 |
| 818 Handle<Code> LoadIC::initialize_stub_in_optimized_code( | 836 Handle<Code> LoadIC::initialize_stub_in_optimized_code( |
| 819 Isolate* isolate, ExtraICState extra_state) { | 837 Isolate* isolate, ExtraICState extra_state) { |
| 820 if (FLAG_tf_load_ic_stub) { | 838 if (FLAG_tf_load_ic_stub) { |
| 821 return LoadICTFStub(isolate, LoadICState(extra_state)).GetCode(); | 839 return LoadICTFStub(isolate, LoadICState(extra_state)).GetCode(); |
| 822 } | 840 } |
| 823 return LoadICStub(isolate, LoadICState(extra_state)).GetCode(); | 841 return LoadICStub(isolate, LoadICState(extra_state)).GetCode(); |
| 824 } | 842 } |
| 825 | 843 |
| 844 Handle<Code> LoadGlobalIC::initialize_stub_in_optimized_code( |
| 845 Isolate* isolate, ExtraICState extra_state) { |
| 846 return LoadGlobalICStub(isolate, LoadICState(extra_state)).GetCode(); |
| 847 } |
| 848 |
| 826 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code( | 849 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code( |
| 827 Isolate* isolate, ExtraICState extra_state) { | 850 Isolate* isolate, ExtraICState extra_state) { |
| 828 return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode(); | 851 return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode(); |
| 829 } | 852 } |
| 830 | 853 |
| 831 Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code( | 854 Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code( |
| 832 Isolate* isolate, LanguageMode language_mode) { | 855 Isolate* isolate, LanguageMode language_mode) { |
| 833 StoreICState state = StoreICState(language_mode); | 856 StoreICState state = StoreICState(language_mode); |
| 834 return VectorKeyedStoreICStub(isolate, state).GetCode(); | 857 return VectorKeyedStoreICStub(isolate, state).GetCode(); |
| 835 } | 858 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 920 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
| 898 TRACE_IC("LoadIC", lookup->name()); | 921 TRACE_IC("LoadIC", lookup->name()); |
| 899 return; | 922 return; |
| 900 } | 923 } |
| 901 | 924 |
| 902 Handle<Code> code; | 925 Handle<Code> code; |
| 903 if (lookup->state() == LookupIterator::JSPROXY || | 926 if (lookup->state() == LookupIterator::JSPROXY || |
| 904 lookup->state() == LookupIterator::ACCESS_CHECK) { | 927 lookup->state() == LookupIterator::ACCESS_CHECK) { |
| 905 code = slow_stub(); | 928 code = slow_stub(); |
| 906 } else if (!lookup->IsFound()) { | 929 } else if (!lookup->IsFound()) { |
| 907 if (kind() == Code::LOAD_IC) { | 930 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) { |
| 908 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), | 931 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), |
| 909 receiver_map()); | 932 receiver_map()); |
| 910 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. | 933 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. |
| 911 if (code.is_null()) code = slow_stub(); | 934 if (code.is_null()) code = slow_stub(); |
| 912 } else { | 935 } else { |
| 913 code = slow_stub(); | 936 code = slow_stub(); |
| 914 } | 937 } |
| 915 } else { | 938 } else { |
| 916 if (lookup->state() == LookupIterator::ACCESSOR) { | 939 if (lookup->state() == LookupIterator::ACCESSOR) { |
| 917 if (!IsCompatibleReceiver(lookup, receiver_map())) { | 940 if (!IsCompatibleReceiver(lookup, receiver_map())) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 947 // Try to find a globally shared handler stub. | 970 // Try to find a globally shared handler stub. |
| 948 Handle<Code> code = GetMapIndependentHandler(lookup); | 971 Handle<Code> code = GetMapIndependentHandler(lookup); |
| 949 if (!code.is_null()) return code; | 972 if (!code.is_null()) return code; |
| 950 | 973 |
| 951 // Otherwise check the map's handler cache for a map-specific handler, and | 974 // Otherwise check the map's handler cache for a map-specific handler, and |
| 952 // compile one if the cache comes up empty. | 975 // compile one if the cache comes up empty. |
| 953 bool receiver_is_holder = | 976 bool receiver_is_holder = |
| 954 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); | 977 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); |
| 955 CacheHolderFlag flag; | 978 CacheHolderFlag flag; |
| 956 Handle<Map> stub_holder_map; | 979 Handle<Map> stub_holder_map; |
| 957 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) { | 980 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || |
| 981 kind() == Code::KEYED_LOAD_IC) { |
| 958 stub_holder_map = IC::GetHandlerCacheHolder( | 982 stub_holder_map = IC::GetHandlerCacheHolder( |
| 959 receiver_map(), receiver_is_holder, isolate(), &flag); | 983 receiver_map(), receiver_is_holder, isolate(), &flag); |
| 960 } else { | 984 } else { |
| 961 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); | 985 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); |
| 962 // Store handlers cannot be cached on prototypes. | 986 // Store handlers cannot be cached on prototypes. |
| 963 flag = kCacheOnReceiver; | 987 flag = kCacheOnReceiver; |
| 964 stub_holder_map = receiver_map(); | 988 stub_holder_map = receiver_map(); |
| 965 } | 989 } |
| 966 | 990 |
| 967 code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(), | 991 code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(), |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 } | 1106 } |
| 1083 break; // Custom-compiled handler. | 1107 break; // Custom-compiled handler. |
| 1084 } | 1108 } |
| 1085 } | 1109 } |
| 1086 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); | 1110 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
| 1087 return slow_stub(); | 1111 return slow_stub(); |
| 1088 } | 1112 } |
| 1089 | 1113 |
| 1090 case LookupIterator::DATA: { | 1114 case LookupIterator::DATA: { |
| 1091 if (lookup->is_dictionary_holder()) { | 1115 if (lookup->is_dictionary_holder()) { |
| 1092 if (kind() != Code::LOAD_IC) { | 1116 if (kind() != Code::LOAD_IC && kind() != Code::LOAD_GLOBAL_IC) { |
| 1093 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); | 1117 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
| 1094 return slow_stub(); | 1118 return slow_stub(); |
| 1095 } | 1119 } |
| 1096 if (holder->IsJSGlobalObject()) { | 1120 if (holder->IsJSGlobalObject()) { |
| 1097 break; // Custom-compiled handler. | 1121 break; // Custom-compiled handler. |
| 1098 } | 1122 } |
| 1099 // There is only one shared stub for loading normalized | 1123 // There is only one shared stub for loading normalized |
| 1100 // properties. It does not traverse the prototype chain, so the | 1124 // properties. It does not traverse the prototype chain, so the |
| 1101 // property must be found in the object for the stub to be | 1125 // property must be found in the object for the stub to be |
| 1102 // applicable. | 1126 // applicable. |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1219 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1243 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1220 Handle<Code> code = compiler.CompileLoadCallback(lookup->name(), info); | 1244 Handle<Code> code = compiler.CompileLoadCallback(lookup->name(), info); |
| 1221 if (FLAG_runtime_call_stats) return slow_stub(); | 1245 if (FLAG_runtime_call_stats) return slow_stub(); |
| 1222 return code; | 1246 return code; |
| 1223 } | 1247 } |
| 1224 UNREACHABLE(); | 1248 UNREACHABLE(); |
| 1225 } | 1249 } |
| 1226 | 1250 |
| 1227 case LookupIterator::DATA: { | 1251 case LookupIterator::DATA: { |
| 1228 if (lookup->is_dictionary_holder()) { | 1252 if (lookup->is_dictionary_holder()) { |
| 1229 DCHECK(kind() == Code::LOAD_IC); | 1253 DCHECK(kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC); |
| 1230 DCHECK(holder->IsJSGlobalObject()); | 1254 DCHECK(holder->IsJSGlobalObject()); |
| 1231 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal); | 1255 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal); |
| 1232 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1256 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1233 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | 1257 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
| 1234 Handle<Code> code = compiler.CompileLoadGlobal( | 1258 Handle<Code> code = compiler.CompileLoadGlobal( |
| 1235 cell, lookup->name(), lookup->IsConfigurable()); | 1259 cell, lookup->name(), lookup->IsConfigurable()); |
| 1236 return code; | 1260 return code; |
| 1237 } | 1261 } |
| 1238 | 1262 |
| 1239 // -------------- Fields -------------- | 1263 // -------------- Fields -------------- |
| (...skipping 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2261 Handle<Object> receiver = args.at<Object>(0); | 2285 Handle<Object> receiver = args.at<Object>(0); |
| 2262 Handle<Name> key = args.at<Name>(1); | 2286 Handle<Name> key = args.at<Name>(1); |
| 2263 | 2287 |
| 2264 DCHECK_EQ(4, args.length()); | 2288 DCHECK_EQ(4, args.length()); |
| 2265 Handle<Smi> slot = args.at<Smi>(2); | 2289 Handle<Smi> slot = args.at<Smi>(2); |
| 2266 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 2290 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
| 2267 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); | 2291 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); |
| 2268 // A monomorphic or polymorphic KeyedLoadIC with a string key can call the | 2292 // 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 | 2293 // LoadIC miss handler if the handler misses. Since the vector Nexus is |
| 2270 // set up outside the IC, handle that here. | 2294 // set up outside the IC, handle that here. |
| 2271 if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::LOAD_IC) { | 2295 FeedbackVectorSlotKind kind = vector->GetKind(vector_slot); |
| 2296 if (kind == FeedbackVectorSlotKind::LOAD_IC) { |
| 2272 LoadICNexus nexus(vector, vector_slot); | 2297 LoadICNexus nexus(vector, vector_slot); |
| 2273 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2298 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2274 ic.UpdateState(receiver, key); | 2299 ic.UpdateState(receiver, key); |
| 2275 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); | 2300 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); |
| 2301 |
| 2302 } else if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) { |
| 2303 DCHECK_EQ(*isolate->global_object(), *receiver); |
| 2304 LoadGlobalICNexus nexus(vector, vector_slot); |
| 2305 LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2306 ic.UpdateState(receiver, key); |
| 2307 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key)); |
| 2308 |
| 2276 } else { | 2309 } else { |
| 2277 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, | 2310 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, kind); |
| 2278 vector->GetKind(vector_slot)); | |
| 2279 KeyedLoadICNexus nexus(vector, vector_slot); | 2311 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2280 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2312 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2281 ic.UpdateState(receiver, key); | 2313 ic.UpdateState(receiver, key); |
| 2282 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); | 2314 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); |
| 2283 } | 2315 } |
| 2284 } | 2316 } |
| 2285 | 2317 |
| 2318 // Used from ic-<arch>.cc. |
| 2319 RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) { |
| 2320 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2321 HandleScope scope(isolate); |
| 2322 DCHECK_EQ(3, args.length()); |
| 2323 Handle<JSGlobalObject> global = isolate->global_object(); |
| 2324 Handle<Name> name = args.at<Name>(0); |
| 2325 Handle<Smi> slot = args.at<Smi>(1); |
| 2326 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); |
| 2327 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); |
| 2328 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, |
| 2329 vector->GetKind(vector_slot)); |
| 2330 |
| 2331 LoadGlobalICNexus nexus(vector, vector_slot); |
| 2332 LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2333 ic.UpdateState(global, name); |
| 2334 |
| 2335 Handle<Object> result; |
| 2336 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(name)); |
| 2337 return *result; |
| 2338 } |
| 2286 | 2339 |
| 2287 // Used from ic-<arch>.cc | 2340 // Used from ic-<arch>.cc |
| 2288 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) { | 2341 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) { |
| 2289 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2342 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2290 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss"); | 2343 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss"); |
| 2291 HandleScope scope(isolate); | 2344 HandleScope scope(isolate); |
| 2292 Handle<Object> receiver = args.at<Object>(0); | 2345 Handle<Object> receiver = args.at<Object>(0); |
| 2293 Handle<Object> key = args.at<Object>(1); | 2346 Handle<Object> key = args.at<Object>(1); |
| 2294 | 2347 |
| 2295 DCHECK(args.length() == 4); | 2348 DCHECK(args.length() == 4); |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2843 it.Next(); | 2896 it.Next(); |
| 2844 } | 2897 } |
| 2845 // Skip past the interceptor. | 2898 // Skip past the interceptor. |
| 2846 it.Next(); | 2899 it.Next(); |
| 2847 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it)); | 2900 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it)); |
| 2848 | 2901 |
| 2849 if (it.IsFound()) return *result; | 2902 if (it.IsFound()) return *result; |
| 2850 | 2903 |
| 2851 LoadICNexus nexus(isolate); | 2904 LoadICNexus nexus(isolate); |
| 2852 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2905 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2853 if (!ic.ShouldThrowReferenceError(it.GetReceiver())) { | 2906 // It could actually be any kind of LoadICs here but the predicate handles |
| 2907 // all the cases properly. |
| 2908 if (!ic.ShouldThrowReferenceError()) { |
| 2854 return isolate->heap()->undefined_value(); | 2909 return isolate->heap()->undefined_value(); |
| 2855 } | 2910 } |
| 2856 | 2911 |
| 2857 // Throw a reference error. | 2912 // Throw a reference error. |
| 2858 THROW_NEW_ERROR_RETURN_FAILURE( | 2913 THROW_NEW_ERROR_RETURN_FAILURE( |
| 2859 isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name())); | 2914 isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name())); |
| 2860 } | 2915 } |
| 2861 | 2916 |
| 2862 | 2917 |
| 2863 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) { | 2918 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2951 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, | 3006 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, |
| 2952 vector->GetKind(vector_slot)); | 3007 vector->GetKind(vector_slot)); |
| 2953 KeyedLoadICNexus nexus(vector, vector_slot); | 3008 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2954 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 3009 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2955 ic.UpdateState(receiver, key); | 3010 ic.UpdateState(receiver, key); |
| 2956 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); | 3011 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); |
| 2957 } | 3012 } |
| 2958 } | 3013 } |
| 2959 } // namespace internal | 3014 } // namespace internal |
| 2960 } // namespace v8 | 3015 } // namespace v8 |
| OLD | NEW |