| 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 |