| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(), | 98 JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(), |
| 99 stdout, true); | 99 stdout, true); |
| 100 } | 100 } |
| 101 | 101 |
| 102 ExtraICState extra_state = new_target->extra_ic_state(); | 102 ExtraICState extra_state = new_target->extra_ic_state(); |
| 103 const char* modifier = ""; | 103 const char* modifier = ""; |
| 104 if (new_target->kind() == Code::KEYED_STORE_IC) { | 104 if (new_target->kind() == Code::KEYED_STORE_IC) { |
| 105 modifier = GetTransitionMarkModifier( | 105 modifier = GetTransitionMarkModifier( |
| 106 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); | 106 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); |
| 107 } | 107 } |
| 108 if (new_target->kind() == Code::LOAD_IC || new_target->kind() == Code::KEYED
_LOAD_IC) { |
| 109 LoadIC::PropertyLookupMode lookup_mode = LoadIC::PropertyLookupMode(extra_
state); |
| 110 PrintF("<%s>", lookup_mode == LoadIC::NORMAL_LOOKUP ? "normal" : "own"); |
| 111 } |
| 112 |
| 108 PrintF(" (%c->%c%s)", TransitionMarkFromState(old_state), | 113 PrintF(" (%c->%c%s)", TransitionMarkFromState(old_state), |
| 109 TransitionMarkFromState(new_state), modifier); | 114 TransitionMarkFromState(new_state), modifier); |
| 110 #ifdef OBJECT_PRINT | 115 #ifdef OBJECT_PRINT |
| 111 OFStream os(stdout); | 116 OFStream os(stdout); |
| 112 name->Print(os); | 117 name->Print(os); |
| 113 #else | 118 #else |
| 114 name->ShortPrint(stdout); | 119 name->ShortPrint(stdout); |
| 115 #endif | 120 #endif |
| 116 PrintF("]\n"); | 121 PrintF("]\n"); |
| 122 if (name->IsString() && strcmp(String::cast(*name)->ToCString().get(), "xBas
e") == 0 && |
| 123 new_state == MEGAMORPHIC) { |
| 124 PrintF("Here!\n"); |
| 125 } |
| 117 } | 126 } |
| 118 } | 127 } |
| 119 | 128 |
| 120 #define TRACE_IC(type, name) TraceIC(type, name) | 129 #define TRACE_IC(type, name) TraceIC(type, name) |
| 121 #define TRACE_VECTOR_IC(type, name, old_state, new_state) \ | 130 #define TRACE_VECTOR_IC(type, name, old_state, new_state) \ |
| 122 TraceIC(type, name, old_state, new_state) | 131 TraceIC(type, name, old_state, new_state) |
| 123 | 132 |
| 124 IC::IC(FrameDepth depth, Isolate* isolate) | 133 IC::IC(FrameDepth depth, Isolate* isolate) |
| 125 : isolate_(isolate), | 134 : isolate_(isolate), |
| 126 target_set_(false), | 135 target_set_(false), |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 | 512 |
| 504 | 513 |
| 505 void KeyedLoadIC::Clear(Isolate* isolate, | 514 void KeyedLoadIC::Clear(Isolate* isolate, |
| 506 Address address, | 515 Address address, |
| 507 Code* target, | 516 Code* target, |
| 508 ConstantPoolArray* constant_pool) { | 517 ConstantPoolArray* constant_pool) { |
| 509 if (IsCleared(target)) return; | 518 if (IsCleared(target)) return; |
| 510 // Make sure to also clear the map used in inline fast cases. If we | 519 // Make sure to also clear the map used in inline fast cases. If we |
| 511 // do not clear these maps, cached code can keep objects alive | 520 // do not clear these maps, cached code can keep objects alive |
| 512 // through the embedded maps. | 521 // through the embedded maps. |
| 513 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | 522 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::KEYED_LOAD_
IC, |
| 523 target->extra_ic_state()); |
| 524 SetTargetAtAddress(address, code, constant_pool); |
| 514 } | 525 } |
| 515 | 526 |
| 516 | 527 |
| 517 void CallIC::Clear(Isolate* isolate, | 528 void CallIC::Clear(Isolate* isolate, |
| 518 Address address, | 529 Address address, |
| 519 Code* target, | 530 Code* target, |
| 520 ConstantPoolArray* constant_pool) { | 531 ConstantPoolArray* constant_pool) { |
| 521 // Currently, CallIC doesn't have state changes. | 532 // Currently, CallIC doesn't have state changes. |
| 522 } | 533 } |
| 523 | 534 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 Token::Value op; | 576 Token::Value op; |
| 566 ICCompareStub::DecodeKey(target->stub_key(), NULL, NULL, &handler_state, &op); | 577 ICCompareStub::DecodeKey(target->stub_key(), NULL, NULL, &handler_state, &op); |
| 567 // Only clear CompareICs that can retain objects. | 578 // Only clear CompareICs that can retain objects. |
| 568 if (handler_state != KNOWN_OBJECT) return; | 579 if (handler_state != KNOWN_OBJECT) return; |
| 569 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); | 580 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); |
| 570 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 581 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
| 571 } | 582 } |
| 572 | 583 |
| 573 | 584 |
| 574 // static | 585 // static |
| 575 Handle<Code> KeyedLoadIC::generic_stub(Isolate* isolate) { | 586 Handle<Code> KeyedLoadIC::generic_stub(Isolate* isolate, ExtraICState extra_ic_s
tate) { |
| 587 // TODO: plumbing |
| 576 if (FLAG_compiled_keyed_generic_loads) { | 588 if (FLAG_compiled_keyed_generic_loads) { |
| 577 return KeyedLoadGenericStub(isolate).GetCode(); | 589 return KeyedLoadGenericStub(isolate, GetPropertyLookupMode(extra_ic_state)).
GetCode(); |
| 578 } else { | 590 } else { |
| 579 return isolate->builtins()->KeyedLoadIC_Generic(); | 591 return PropertyICCompiler::ComputeKeyedLoad(isolate, GENERIC, extra_ic_state
); |
| 580 } | 592 } |
| 581 } | 593 } |
| 582 | 594 |
| 583 | 595 |
| 584 static bool MigrateDeprecated(Handle<Object> object) { | 596 static bool MigrateDeprecated(Handle<Object> object) { |
| 585 if (!object->IsJSObject()) return false; | 597 if (!object->IsJSObject()) return false; |
| 586 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 598 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 587 if (!receiver->map()->is_deprecated()) return false; | 599 if (!receiver->map()->is_deprecated()) return false; |
| 588 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 600 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
| 589 return true; | 601 return true; |
| 590 } | 602 } |
| 591 | 603 |
| 592 | 604 |
| 593 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<String> name) { | 605 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { |
| 594 // If the object is undefined or null it's illegal to try to get any | 606 // If the object is undefined or null it's illegal to try to get any |
| 595 // of its properties; throw a TypeError in that case. | 607 // of its properties; throw a TypeError in that case. |
| 596 if (object->IsUndefined() || object->IsNull()) { | 608 if (object->IsUndefined() || object->IsNull()) { |
| 597 return TypeError("non_object_property_load", object, name); | 609 return TypeError("non_object_property_load", object, name); |
| 598 } | 610 } |
| 599 | 611 |
| 600 // Check if the name is trivially convertible to an index and get | 612 // Check if the name is trivially convertible to an index and get |
| 601 // the element or char if so. | 613 // the element or char if so. |
| 602 uint32_t index; | 614 uint32_t index; |
| 603 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 615 if (kind() == Code::KEYED_LOAD_IC && |
| 616 name->IsString() && String::cast(*name)->AsArrayIndex(&index)) { |
| 604 // Rewrite to the generic keyed load stub. | 617 // Rewrite to the generic keyed load stub. |
| 605 if (FLAG_use_ic) { | 618 if (FLAG_use_ic) { |
| 606 set_target(*KeyedLoadIC::generic_stub(isolate())); | 619 set_target(*KeyedLoadIC::generic_stub(isolate(), extra_ic_state())); |
| 607 TRACE_IC("LoadIC", name); | 620 TRACE_IC("LoadIC", name); |
| 608 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 621 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
| 609 } | 622 } |
| 610 Handle<Object> result; | 623 Handle<Object> result; |
| 611 ASSIGN_RETURN_ON_EXCEPTION( | 624 ASSIGN_RETURN_ON_EXCEPTION( |
| 612 isolate(), | 625 isolate(), |
| 613 result, | 626 result, |
| 614 Runtime::GetElementOrCharAt(isolate(), object, index), | 627 Runtime::GetElementOrCharAt(isolate(), object, index), |
| 615 Object); | 628 Object); |
| 616 return result; | 629 return result; |
| 617 } | 630 } |
| 618 | 631 |
| 619 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; | 632 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; |
| 620 | 633 |
| 621 // Named lookup in the object. | 634 // Named lookup in the object. |
| 622 LookupIterator it(object, name); | 635 LookupIterator::Configuration lookup_configuration = |
| 623 LookupForRead(&it); | 636 property_lookup_mode() == OWN_PROPERTY_LOOKUP ? |
| 637 LookupIterator::CHECK_OWN_REAL : |
| 638 LookupIterator::CHECK_ALL; |
| 639 |
| 640 LookupIterator it(object, name, lookup_configuration); |
| 641 LookupForRead(&it); |
| 624 | 642 |
| 625 // If we did not find a property, check if we need to throw an exception. | 643 // If we did not find a property, check if we need to throw an exception. |
| 626 if (!it.IsFound()) { | 644 if (!it.IsFound()) { |
| 627 if (IsUndeclaredGlobal(object)) { | 645 if (IsUndeclaredGlobal(object)) { |
| 628 return ReferenceError("not_defined", name); | 646 return ReferenceError("not_defined", |
| 647 name->IsString() |
| 648 ? Handle<String>::cast(name) |
| 649 : Handle<String>()); |
| 629 } | 650 } |
| 630 LOG(isolate(), SuspectReadEvent(*name, *object)); | 651 LOG(isolate(), SuspectReadEvent(*name, *object)); |
| 631 } | 652 } |
| 632 | 653 |
| 633 // Update inline cache and stub cache. | 654 // Update inline cache and stub cache. |
| 634 if (use_ic) UpdateCaches(&it, object, name); | 655 if (use_ic) UpdateCaches(&it, object, name); |
| 635 | 656 |
| 636 // Get the property. | 657 // Get the property. |
| 637 Handle<Object> result; | 658 Handle<Object> result; |
| 638 ASSIGN_RETURN_ON_EXCEPTION( | 659 ASSIGN_RETURN_ON_EXCEPTION( |
| 639 isolate(), result, Object::GetProperty(&it), Object); | 660 isolate(), result, Object::GetProperty(&it), Object); |
| 640 // If the property is not present, check if we need to throw an exception. | 661 // If the property is not present, check if we need to throw an exception. |
| 641 if (!it.IsFound() && IsUndeclaredGlobal(object)) { | 662 if (!it.IsFound() && IsUndeclaredGlobal(object)) { |
| 642 return ReferenceError("not_defined", name); | 663 return ReferenceError("not_defined", |
| 664 name->IsString() |
| 665 ? Handle<String>::cast(name) |
| 666 : Handle<String>()); |
| 643 } | 667 } |
| 644 | 668 |
| 645 return result; | 669 return result; |
| 646 } | 670 } |
| 647 | 671 |
| 648 | 672 |
| 649 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 673 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, |
| 650 Handle<Map> new_receiver_map) { | 674 Handle<Map> new_receiver_map) { |
| 651 DCHECK(!new_receiver_map.is_null()); | 675 DCHECK(!new_receiver_map.is_null()); |
| 652 for (int current = 0; current < receiver_maps->length(); ++current) { | 676 for (int current = 0; current < receiver_maps->length(); ++current) { |
| 653 if (!receiver_maps->at(current).is_null() && | 677 if (!receiver_maps->at(current).is_null() && |
| 654 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 678 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
| 655 return false; | 679 return false; |
| 656 } | 680 } |
| 657 } | 681 } |
| 658 receiver_maps->Add(new_receiver_map); | 682 receiver_maps->Add(new_receiver_map); |
| 659 return true; | 683 return true; |
| 660 } | 684 } |
| 661 | 685 |
| 662 | 686 |
| 663 bool IC::UpdatePolymorphicIC(Handle<String> name, Handle<Code> code) { | 687 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) { |
| 664 if (!code->is_handler()) return false; | 688 if (!code->is_handler()) return false; |
| 665 if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false; | 689 if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false; |
| 666 Handle<HeapType> type = receiver_type(); | 690 Handle<HeapType> type = receiver_type(); |
| 667 TypeHandleList types; | 691 TypeHandleList types; |
| 668 CodeHandleList handlers; | 692 CodeHandleList handlers; |
| 669 | 693 |
| 670 TargetTypes(&types); | 694 TargetTypes(&types); |
| 671 int number_of_types = types.length(); | 695 int number_of_types = types.length(); |
| 672 int deprecated_types = 0; | 696 int deprecated_types = 0; |
| 673 int handler_to_overwrite = -1; | 697 int handler_to_overwrite = -1; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 | 783 |
| 760 | 784 |
| 761 template | 785 template |
| 762 Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone); | 786 Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone); |
| 763 | 787 |
| 764 | 788 |
| 765 template | 789 template |
| 766 Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, Isolate* region); | 790 Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, Isolate* region); |
| 767 | 791 |
| 768 | 792 |
| 769 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<String> name) { | 793 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { |
| 770 DCHECK(handler->is_handler()); | 794 DCHECK(handler->is_handler()); |
| 771 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( | 795 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( |
| 772 kind(), name, receiver_type(), handler, extra_ic_state()); | 796 kind(), name, receiver_type(), handler, extra_ic_state()); |
| 773 set_target(*ic); | 797 set_target(*ic); |
| 774 } | 798 } |
| 775 | 799 |
| 776 | 800 |
| 777 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 801 void IC::CopyICToMegamorphicCache(Handle<Name> name) { |
| 778 TypeHandleList types; | 802 TypeHandleList types; |
| 779 CodeHandleList handlers; | 803 CodeHandleList handlers; |
| 780 TargetTypes(&types); | 804 TargetTypes(&types); |
| 781 if (!target()->FindHandlers(&handlers, types.length())) return; | 805 if (!target()->FindHandlers(&handlers, types.length())) return; |
| 782 for (int i = 0; i < types.length(); i++) { | 806 for (int i = 0; i < types.length(); i++) { |
| 783 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); | 807 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); |
| 784 } | 808 } |
| 785 } | 809 } |
| 786 | 810 |
| 787 | 811 |
| 788 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { | 812 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { |
| 789 if (source_map == NULL) return true; | 813 if (source_map == NULL) return true; |
| 790 if (target_map == NULL) return false; | 814 if (target_map == NULL) return false; |
| 791 ElementsKind target_elements_kind = target_map->elements_kind(); | 815 ElementsKind target_elements_kind = target_map->elements_kind(); |
| 792 bool more_general_transition = | 816 bool more_general_transition = |
| 793 IsMoreGeneralElementsKindTransition( | 817 IsMoreGeneralElementsKindTransition( |
| 794 source_map->elements_kind(), target_elements_kind); | 818 source_map->elements_kind(), target_elements_kind); |
| 795 Map* transitioned_map = more_general_transition | 819 Map* transitioned_map = more_general_transition |
| 796 ? source_map->LookupElementsTransitionMap(target_elements_kind) | 820 ? source_map->LookupElementsTransitionMap(target_elements_kind) |
| 797 : NULL; | 821 : NULL; |
| 798 | 822 |
| 799 return transitioned_map == target_map; | 823 return transitioned_map == target_map; |
| 800 } | 824 } |
| 801 | 825 |
| 802 | 826 |
| 803 void IC::PatchCache(Handle<String> name, Handle<Code> code) { | 827 void IC::PatchCache(Handle<Name> name, Handle<Code> code) { |
| 804 switch (state()) { | 828 switch (state()) { |
| 805 case UNINITIALIZED: | 829 case UNINITIALIZED: |
| 806 case PREMONOMORPHIC: | 830 case PREMONOMORPHIC: |
| 807 UpdateMonomorphicIC(code, name); | 831 UpdateMonomorphicIC(code, name); |
| 808 break; | 832 break; |
| 809 case PROTOTYPE_FAILURE: | 833 case PROTOTYPE_FAILURE: |
| 810 case MONOMORPHIC: | 834 case MONOMORPHIC: |
| 811 case POLYMORPHIC: | 835 case POLYMORPHIC: |
| 812 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { | 836 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { |
| 813 if (UpdatePolymorphicIC(name, code)) break; | 837 if (UpdatePolymorphicIC(name, code)) break; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 827 } | 851 } |
| 828 } | 852 } |
| 829 | 853 |
| 830 | 854 |
| 831 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, | 855 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, |
| 832 ExtraICState extra_state) { | 856 ExtraICState extra_state) { |
| 833 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); | 857 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); |
| 834 } | 858 } |
| 835 | 859 |
| 836 | 860 |
| 861 Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate, |
| 862 ExtraICState extra_state) { |
| 863 return PropertyICCompiler::ComputeKeyedLoad(isolate, UNINITIALIZED, extra_stat
e); |
| 864 } |
| 865 |
| 866 |
| 837 Handle<Code> LoadIC::megamorphic_stub() { | 867 Handle<Code> LoadIC::megamorphic_stub() { |
| 838 if (kind() == Code::LOAD_IC) { | 868 if (kind() == Code::LOAD_IC) { |
| 839 return PropertyICCompiler::ComputeLoad(isolate(), MEGAMORPHIC, | 869 return PropertyICCompiler::ComputeLoad(isolate(), MEGAMORPHIC, |
| 840 extra_ic_state()); | 870 extra_ic_state()); |
| 841 } else { | 871 } else { |
| 842 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | 872 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
| 843 return KeyedLoadIC::generic_stub(isolate()); | 873 return KeyedLoadIC::generic_stub(isolate(), extra_ic_state()); |
| 844 } | 874 } |
| 845 } | 875 } |
| 846 | 876 |
| 847 | 877 |
| 848 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 878 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
| 849 ExtraICState extra_state) { | 879 ExtraICState extra_state) { |
| 850 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); | 880 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); |
| 851 } | 881 } |
| 852 | 882 |
| 853 | 883 |
| 854 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { | 884 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate, |
| 855 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); | 885 ExtraICState extra_state) { |
| 886 return PropertyICCompiler::ComputeKeyedLoad(isolate, PREMONOMORPHIC, extra_sta
te); |
| 856 } | 887 } |
| 857 | 888 |
| 858 | 889 |
| 859 Handle<Code> LoadIC::pre_monomorphic_stub() const { | 890 Handle<Code> LoadIC::pre_monomorphic_stub() const { |
| 860 if (kind() == Code::LOAD_IC) { | 891 if (kind() == Code::LOAD_IC) { |
| 861 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); | 892 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); |
| 862 } else { | 893 } else { |
| 863 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | 894 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
| 864 return KeyedLoadIC::pre_monomorphic_stub(isolate()); | 895 return KeyedLoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); |
| 865 } | 896 } |
| 866 } | 897 } |
| 867 | 898 |
| 868 | 899 |
| 869 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { | 900 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { |
| 870 LoadFieldStub stub(isolate(), index); | 901 LoadFieldStub stub(isolate(), index); |
| 871 return stub.GetCode(); | 902 return stub.GetCode(); |
| 872 } | 903 } |
| 873 | 904 |
| 874 | 905 |
| 875 void LoadIC::UpdateCaches(LookupIterator* lookup, Handle<Object> object, | 906 void LoadIC::UpdateCaches(LookupIterator* lookup, Handle<Object> object, |
| 876 Handle<String> name) { | 907 Handle<Name> name) { |
| 877 if (state() == UNINITIALIZED) { | 908 if (state() == UNINITIALIZED) { |
| 878 // This is the first time we execute this inline cache. | 909 // This is the first time we execute this inline cache. |
| 879 // Set the target to the pre monomorphic stub to delay | 910 // Set the target to the pre monomorphic stub to delay |
| 880 // setting the monomorphic state. | 911 // setting the monomorphic state. |
| 881 set_target(*pre_monomorphic_stub()); | 912 set_target(*pre_monomorphic_stub()); |
| 882 TRACE_IC("LoadIC", name); | 913 TRACE_IC("LoadIC", name); |
| 883 return; | 914 return; |
| 884 } | 915 } |
| 885 | 916 |
| 886 Handle<Code> code; | 917 Handle<Code> code; |
| 887 if (lookup->state() == LookupIterator::JSPROXY || | 918 if (lookup->state() == LookupIterator::JSPROXY || |
| 888 lookup->state() == LookupIterator::ACCESS_CHECK) { | 919 lookup->state() == LookupIterator::ACCESS_CHECK) { |
| 889 code = slow_stub(); | 920 code = slow_stub(); |
| 890 } else if (!lookup->IsFound()) { | 921 } else if (!lookup->IsFound()) { |
| 891 if (kind() == Code::LOAD_IC) { | 922 if (kind() == Code::LOAD_IC && property_lookup_mode() == NORMAL_LOOKUP) { |
| 892 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(name, | 923 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(name, |
| 893 receiver_type()); | 924 receiver_type()); |
| 894 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. | 925 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. |
| 895 if (code.is_null()) code = slow_stub(); | 926 if (code.is_null()) code = slow_stub(); |
| 896 } else { | 927 } else { |
| 897 code = slow_stub(); | 928 code = slow_stub(); |
| 898 } | 929 } |
| 899 } else { | 930 } else { |
| 900 code = ComputeHandler(lookup, object, name); | 931 code = ComputeHandler(lookup, object, name); |
| 901 } | 932 } |
| 902 | 933 |
| 903 PatchCache(name, code); | 934 PatchCache(name, code); |
| 904 TRACE_IC("LoadIC", name); | 935 TRACE_IC("LoadIC", name); |
| 905 } | 936 } |
| 906 | 937 |
| 907 | 938 |
| 908 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { | 939 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { |
| 909 if (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC) return; | 940 if (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC) return; |
| 910 Map* map = *TypeToMap(type, isolate()); | 941 Map* map = *TypeToMap(type, isolate()); |
| 911 isolate()->stub_cache()->Set(name, map, code); | 942 isolate()->stub_cache()->Set(name, map, code); |
| 912 } | 943 } |
| 913 | 944 |
| 914 | 945 |
| 915 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> object, | 946 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> object, |
| 916 Handle<String> name, Handle<Object> value) { | 947 Handle<Name> name, Handle<Object> value) { |
| 917 bool receiver_is_holder = | 948 bool receiver_is_holder = |
| 918 object.is_identical_to(lookup->GetHolder<JSObject>()); | 949 object.is_identical_to(lookup->GetHolder<JSObject>()); |
| 919 CacheHolderFlag flag; | 950 CacheHolderFlag flag; |
| 920 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 951 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( |
| 921 *receiver_type(), receiver_is_holder, isolate(), &flag); | 952 *receiver_type(), receiver_is_holder, isolate(), &flag); |
| 922 | 953 |
| 923 Handle<Code> code = PropertyHandlerCompiler::Find( | 954 Handle<Code> code = PropertyHandlerCompiler::Find( |
| 924 name, stub_holder_map, kind(), flag, | 955 name, stub_holder_map, kind(), flag, |
| 925 lookup->holder_map()->is_dictionary_map() ? Code::NORMAL : Code::FAST); | 956 lookup->holder_map()->is_dictionary_map() ? Code::NORMAL : Code::FAST); |
| 926 // Use the cached value if it exists, and if it is different from the | 957 // Use the cached value if it exists, and if it is different from the |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 | 1025 |
| 995 if (code->type() != Code::NORMAL) { | 1026 if (code->type() != Code::NORMAL) { |
| 996 Map::UpdateCodeCache(stub_holder_map, name, code); | 1027 Map::UpdateCodeCache(stub_holder_map, name, code); |
| 997 } | 1028 } |
| 998 | 1029 |
| 999 return code; | 1030 return code; |
| 1000 } | 1031 } |
| 1001 | 1032 |
| 1002 | 1033 |
| 1003 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, | 1034 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, |
| 1004 Handle<Object> object, Handle<String> name, | 1035 Handle<Object> object, Handle<Name> name, |
| 1005 Handle<Object> unused, | 1036 Handle<Object> unused, |
| 1006 CacheHolderFlag cache_holder) { | 1037 CacheHolderFlag cache_holder) { |
| 1007 if (object->IsString() && | 1038 if (object->IsString() && |
| 1008 String::Equals(isolate()->factory()->length_string(), name)) { | 1039 Name::Equals(isolate()->factory()->length_string(), name)) { |
| 1009 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); | 1040 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); |
| 1010 return SimpleFieldLoad(index); | 1041 return SimpleFieldLoad(index); |
| 1011 } | 1042 } |
| 1012 | 1043 |
| 1013 if (object->IsStringWrapper() && | 1044 if (object->IsStringWrapper() && |
| 1014 String::Equals(isolate()->factory()->length_string(), name)) { | 1045 Name::Equals(isolate()->factory()->length_string(), name)) { |
| 1015 StringLengthStub string_length_stub(isolate()); | 1046 StringLengthStub string_length_stub(isolate()); |
| 1016 return string_length_stub.GetCode(); | 1047 return string_length_stub.GetCode(); |
| 1017 } | 1048 } |
| 1018 | 1049 |
| 1019 // Use specialized code for getting prototype of functions. | 1050 // Use specialized code for getting prototype of functions. |
| 1020 if (object->IsJSFunction() && | 1051 if (object->IsJSFunction() && |
| 1021 String::Equals(isolate()->factory()->prototype_string(), name) && | 1052 Name::Equals(isolate()->factory()->prototype_string(), name) && |
| 1022 Handle<JSFunction>::cast(object)->should_have_prototype() && | 1053 Handle<JSFunction>::cast(object)->should_have_prototype() && |
| 1023 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { | 1054 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { |
| 1024 Handle<Code> stub; | 1055 Handle<Code> stub; |
| 1025 FunctionPrototypeStub function_prototype_stub(isolate()); | 1056 FunctionPrototypeStub function_prototype_stub(isolate()); |
| 1026 return function_prototype_stub.GetCode(); | 1057 return function_prototype_stub.GetCode(); |
| 1027 } | 1058 } |
| 1028 | 1059 |
| 1029 Handle<HeapType> type = receiver_type(); | 1060 Handle<HeapType> type = receiver_type(); |
| 1030 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1061 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
| 1031 bool receiver_is_holder = object.is_identical_to(holder); | 1062 bool receiver_is_holder = object.is_identical_to(holder); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1230 return result; | 1261 return result; |
| 1231 } | 1262 } |
| 1232 | 1263 |
| 1233 Handle<Object> load_handle; | 1264 Handle<Object> load_handle; |
| 1234 Handle<Code> stub = generic_stub(); | 1265 Handle<Code> stub = generic_stub(); |
| 1235 | 1266 |
| 1236 // Check for non-string values that can be converted into an | 1267 // Check for non-string values that can be converted into an |
| 1237 // internalized string directly or is representable as a smi. | 1268 // internalized string directly or is representable as a smi. |
| 1238 key = TryConvertKey(key, isolate()); | 1269 key = TryConvertKey(key, isolate()); |
| 1239 | 1270 |
| 1240 if (key->IsInternalizedString()) { | 1271 if (key->IsInternalizedString() || key->IsSymbol()) { |
| 1241 ASSIGN_RETURN_ON_EXCEPTION( | 1272 ASSIGN_RETURN_ON_EXCEPTION( |
| 1242 isolate(), | 1273 isolate(), |
| 1243 load_handle, | 1274 load_handle, |
| 1244 LoadIC::Load(object, Handle<String>::cast(key)), | 1275 LoadIC::Load(object, Handle<Name>::cast(key)), |
| 1245 Object); | 1276 Object); |
| 1246 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1277 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
| 1247 if (object->IsString() && key->IsNumber()) { | 1278 if (object->IsString() && key->IsNumber()) { |
| 1248 if (state() == UNINITIALIZED) stub = string_stub(); | 1279 if (state() == UNINITIALIZED) stub = string_stub(); |
| 1249 } else if (object->IsJSObject()) { | 1280 } else if (object->IsJSObject()) { |
| 1250 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1281 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1251 if (receiver->elements()->map() == | 1282 if (receiver->elements()->map() == |
| 1252 isolate()->heap()->sloppy_arguments_elements_map()) { | 1283 isolate()->heap()->sloppy_arguments_elements_map()) { |
| 1253 stub = sloppy_arguments_stub(); | 1284 stub = sloppy_arguments_stub(); |
| 1254 } else if (receiver->HasIndexedInterceptor()) { | 1285 } else if (receiver->HasIndexedInterceptor()) { |
| (...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2098 } | 2129 } |
| 2099 | 2130 |
| 2100 | 2131 |
| 2101 // Used from ic-<arch>.cc. | 2132 // Used from ic-<arch>.cc. |
| 2102 RUNTIME_FUNCTION(LoadIC_Miss) { | 2133 RUNTIME_FUNCTION(LoadIC_Miss) { |
| 2103 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2134 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2104 HandleScope scope(isolate); | 2135 HandleScope scope(isolate); |
| 2105 DCHECK(args.length() == 2); | 2136 DCHECK(args.length() == 2); |
| 2106 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2137 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2107 Handle<Object> receiver = args.at<Object>(0); | 2138 Handle<Object> receiver = args.at<Object>(0); |
| 2108 Handle<String> key = args.at<String>(1); | 2139 Handle<Name> key = args.at<Name>(1); |
| 2109 ic.UpdateState(receiver, key); | 2140 ic.UpdateState(receiver, key); |
| 2110 Handle<Object> result; | 2141 Handle<Object> result; |
| 2111 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2142 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2112 return *result; | 2143 return *result; |
| 2113 } | 2144 } |
| 2114 | 2145 |
| 2115 | 2146 |
| 2116 // Used from ic-<arch>.cc | 2147 // Used from ic-<arch>.cc |
| 2117 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { | 2148 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { |
| 2118 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2149 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| (...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3170 #undef ADDR | 3201 #undef ADDR |
| 3171 }; | 3202 }; |
| 3172 | 3203 |
| 3173 | 3204 |
| 3174 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3205 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3175 return IC_utilities[id]; | 3206 return IC_utilities[id]; |
| 3176 } | 3207 } |
| 3177 | 3208 |
| 3178 | 3209 |
| 3179 } } // namespace v8::internal | 3210 } } // namespace v8::internal |
| OLD | NEW |