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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 #endif | 146 #endif |
147 fp_ = fp; | 147 fp_ = fp; |
148 if (FLAG_enable_ool_constant_pool) { | 148 if (FLAG_enable_ool_constant_pool) { |
149 raw_constant_pool_ = handle( | 149 raw_constant_pool_ = handle( |
150 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), | 150 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), |
151 isolate); | 151 isolate); |
152 } | 152 } |
153 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 153 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
154 target_ = handle(raw_target(), isolate); | 154 target_ = handle(raw_target(), isolate); |
155 state_ = target_->ic_state(); | 155 state_ = target_->ic_state(); |
| 156 kind_ = target_->kind(); |
156 extra_ic_state_ = target_->extra_ic_state(); | 157 extra_ic_state_ = target_->extra_ic_state(); |
157 } | 158 } |
158 | 159 |
159 | 160 |
160 SharedFunctionInfo* IC::GetSharedFunctionInfo() const { | 161 SharedFunctionInfo* IC::GetSharedFunctionInfo() const { |
161 // Compute the JavaScript frame for the frame pointer of this IC | 162 // Compute the JavaScript frame for the frame pointer of this IC |
162 // structure. We need this to be able to find the function | 163 // structure. We need this to be able to find the function |
163 // corresponding to the frame. | 164 // corresponding to the frame. |
164 StackFrameIterator it(isolate()); | 165 StackFrameIterator it(isolate()); |
165 while (it.frame()->fp() != this->fp()) it.Advance(); | 166 while (it.frame()->fp() != this->fp()) it.Advance(); |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 CompareIC::State handler_state; | 519 CompareIC::State handler_state; |
519 Token::Value op; | 520 Token::Value op; |
520 ICCompareStub::DecodeKey(target->stub_key(), NULL, NULL, &handler_state, &op); | 521 ICCompareStub::DecodeKey(target->stub_key(), NULL, NULL, &handler_state, &op); |
521 // Only clear CompareICs that can retain objects. | 522 // Only clear CompareICs that can retain objects. |
522 if (handler_state != KNOWN_OBJECT) return; | 523 if (handler_state != KNOWN_OBJECT) return; |
523 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); | 524 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); |
524 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 525 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
525 } | 526 } |
526 | 527 |
527 | 528 |
528 Handle<Code> KeyedLoadIC::megamorphic_stub() { | 529 // static |
| 530 Handle<Code> KeyedLoadIC::generic_stub(Isolate* isolate) { |
529 if (FLAG_compiled_keyed_generic_loads) { | 531 if (FLAG_compiled_keyed_generic_loads) { |
530 return KeyedLoadGenericElementStub(isolate()).GetCode(); | 532 return KeyedLoadGenericElementStub(isolate).GetCode(); |
531 } else { | 533 } else { |
532 return isolate()->builtins()->KeyedLoadIC_Generic(); | 534 return isolate->builtins()->KeyedLoadIC_Generic(); |
533 } | 535 } |
534 } | 536 } |
535 | 537 |
536 Handle<Code> KeyedLoadIC::generic_stub() const { | |
537 if (FLAG_compiled_keyed_generic_loads) { | |
538 return KeyedLoadGenericElementStub(isolate()).GetCode(); | |
539 } else { | |
540 return isolate()->builtins()->KeyedLoadIC_Generic(); | |
541 } | |
542 } | |
543 | |
544 | 538 |
545 static bool MigrateDeprecated(Handle<Object> object) { | 539 static bool MigrateDeprecated(Handle<Object> object) { |
546 if (!object->IsJSObject()) return false; | 540 if (!object->IsJSObject()) return false; |
547 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 541 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
548 if (!receiver->map()->is_deprecated()) return false; | 542 if (!receiver->map()->is_deprecated()) return false; |
549 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 543 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
550 return true; | 544 return true; |
551 } | 545 } |
552 | 546 |
553 | 547 |
554 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<String> name) { | 548 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<String> name) { |
555 // If the object is undefined or null it's illegal to try to get any | 549 // If the object is undefined or null it's illegal to try to get any |
556 // of its properties; throw a TypeError in that case. | 550 // of its properties; throw a TypeError in that case. |
557 if (object->IsUndefined() || object->IsNull()) { | 551 if (object->IsUndefined() || object->IsNull()) { |
558 return TypeError("non_object_property_load", object, name); | 552 return TypeError("non_object_property_load", object, name); |
559 } | 553 } |
560 | 554 |
561 // Check if the name is trivially convertible to an index and get | 555 // Check if the name is trivially convertible to an index and get |
562 // the element or char if so. | 556 // the element or char if so. |
563 uint32_t index; | 557 uint32_t index; |
564 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 558 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
565 // Rewrite to the generic keyed load stub. | 559 // Rewrite to the generic keyed load stub. |
566 if (FLAG_use_ic) { | 560 if (FLAG_use_ic) { |
567 set_target(*generic_stub()); | 561 set_target(*KeyedLoadIC::generic_stub(isolate())); |
568 TRACE_IC("LoadIC", name); | 562 TRACE_IC("LoadIC", name); |
569 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 563 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
570 } | 564 } |
571 Handle<Object> result; | 565 Handle<Object> result; |
572 ASSIGN_RETURN_ON_EXCEPTION( | 566 ASSIGN_RETURN_ON_EXCEPTION( |
573 isolate(), | 567 isolate(), |
574 result, | 568 result, |
575 Runtime::GetElementOrCharAt(isolate(), object, index), | 569 Runtime::GetElementOrCharAt(isolate(), object, index), |
576 Object); | 570 Object); |
577 return result; | 571 return result; |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 case PREMONOMORPHIC: | 763 case PREMONOMORPHIC: |
770 UpdateMonomorphicIC(code, name); | 764 UpdateMonomorphicIC(code, name); |
771 break; | 765 break; |
772 case PROTOTYPE_FAILURE: | 766 case PROTOTYPE_FAILURE: |
773 case MONOMORPHIC: | 767 case MONOMORPHIC: |
774 case POLYMORPHIC: | 768 case POLYMORPHIC: |
775 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { | 769 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { |
776 if (UpdatePolymorphicIC(name, code)) break; | 770 if (UpdatePolymorphicIC(name, code)) break; |
777 CopyICToMegamorphicCache(name); | 771 CopyICToMegamorphicCache(name); |
778 } | 772 } |
779 if (FLAG_compiled_keyed_generic_loads && (kind() == Code::LOAD_IC)) { | |
780 set_target(*generic_stub()); | |
781 break; | |
782 } | |
783 set_target(*megamorphic_stub()); | 773 set_target(*megamorphic_stub()); |
784 // Fall through. | 774 // Fall through. |
785 case MEGAMORPHIC: | 775 case MEGAMORPHIC: |
786 UpdateMegamorphicCache(*receiver_type(), *name, *code); | 776 UpdateMegamorphicCache(*receiver_type(), *name, *code); |
787 break; | 777 break; |
788 case DEBUG_STUB: | 778 case DEBUG_STUB: |
789 break; | 779 break; |
790 case GENERIC: | 780 case GENERIC: |
791 UNREACHABLE(); | 781 UNREACHABLE(); |
792 break; | 782 break; |
793 } | 783 } |
794 } | 784 } |
795 | 785 |
796 | 786 |
797 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, | 787 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, |
798 ExtraICState extra_state) { | 788 ExtraICState extra_state) { |
799 return isolate->stub_cache()->ComputeLoad(UNINITIALIZED, extra_state); | 789 return isolate->stub_cache()->ComputeLoad(UNINITIALIZED, extra_state); |
800 } | 790 } |
801 | 791 |
802 | 792 |
| 793 Handle<Code> LoadIC::megamorphic_stub() { |
| 794 if (kind() == Code::LOAD_IC) { |
| 795 return isolate()->stub_cache()->ComputeLoad(MEGAMORPHIC, extra_ic_state()); |
| 796 } else { |
| 797 ASSERT_EQ(Code::KEYED_LOAD_IC, kind()); |
| 798 return KeyedLoadIC::generic_stub(isolate()); |
| 799 } |
| 800 } |
| 801 |
| 802 |
803 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 803 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
804 ExtraICState extra_state) { | 804 ExtraICState extra_state) { |
805 return isolate->stub_cache()->ComputeLoad(PREMONOMORPHIC, extra_state); | 805 return isolate->stub_cache()->ComputeLoad(PREMONOMORPHIC, extra_state); |
806 } | 806 } |
807 | 807 |
808 | 808 |
809 Handle<Code> LoadIC::megamorphic_stub() { | 809 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { |
810 return isolate()->stub_cache()->ComputeLoad(MEGAMORPHIC, extra_ic_state()); | 810 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); |
811 } | 811 } |
812 | 812 |
813 | 813 |
814 Handle<Code> LoadIC::generic_stub() const { | 814 Handle<Code> LoadIC::pre_monomorphic_stub() const { |
815 return KeyedLoadGenericElementStub(isolate()).GetCode(); | 815 if (kind() == Code::LOAD_IC) { |
| 816 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); |
| 817 } else { |
| 818 ASSERT_EQ(Code::KEYED_LOAD_IC, kind()); |
| 819 return KeyedLoadIC::pre_monomorphic_stub(isolate()); |
| 820 } |
816 } | 821 } |
817 | 822 |
818 | 823 |
819 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { | 824 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { |
820 if (kind() == Code::LOAD_IC) { | 825 LoadFieldStub stub(isolate(), index); |
821 LoadFieldStub stub(isolate(), index); | 826 return stub.GetCode(); |
822 return stub.GetCode(); | |
823 } else { | |
824 KeyedLoadFieldStub stub(isolate(), index); | |
825 return stub.GetCode(); | |
826 } | |
827 } | 827 } |
828 | 828 |
829 | 829 |
830 void LoadIC::UpdateCaches(LookupResult* lookup, | 830 void LoadIC::UpdateCaches(LookupResult* lookup, |
831 Handle<Object> object, | 831 Handle<Object> object, |
832 Handle<String> name) { | 832 Handle<String> name) { |
833 if (state() == UNINITIALIZED) { | 833 if (state() == UNINITIALIZED) { |
834 // This is the first time we execute this inline cache. | 834 // This is the first time we execute this inline cache. |
835 // Set the target to the pre monomorphic stub to delay | 835 // Set the target to the pre monomorphic stub to delay |
836 // setting the monomorphic state. | 836 // setting the monomorphic state. |
(...skipping 18 matching lines...) Expand all Loading... |
855 } else { | 855 } else { |
856 code = ComputeHandler(lookup, object, name); | 856 code = ComputeHandler(lookup, object, name); |
857 } | 857 } |
858 | 858 |
859 PatchCache(name, code); | 859 PatchCache(name, code); |
860 TRACE_IC("LoadIC", name); | 860 TRACE_IC("LoadIC", name); |
861 } | 861 } |
862 | 862 |
863 | 863 |
864 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { | 864 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { |
865 // Cache code holding map should be consistent with | 865 if (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC) return; |
866 // GenerateMonomorphicCacheProbe. | |
867 Map* map = *TypeToMap(type, isolate()); | 866 Map* map = *TypeToMap(type, isolate()); |
868 isolate()->stub_cache()->Set(name, map, code); | 867 isolate()->stub_cache()->Set(name, map, code); |
869 } | 868 } |
870 | 869 |
871 | 870 |
872 Handle<Code> IC::ComputeHandler(LookupResult* lookup, | 871 Handle<Code> IC::ComputeHandler(LookupResult* lookup, |
873 Handle<Object> object, | 872 Handle<Object> object, |
874 Handle<String> name, | 873 Handle<String> name, |
875 Handle<Object> value) { | 874 Handle<Object> value) { |
876 bool receiver_is_holder = lookup->ReceiverIsHolder(object); | 875 bool receiver_is_holder = lookup->ReceiverIsHolder(object); |
877 CacheHolderFlag flag; | 876 CacheHolderFlag flag; |
878 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 877 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( |
879 *receiver_type(), receiver_is_holder, isolate(), &flag); | 878 *receiver_type(), receiver_is_holder, isolate(), &flag); |
880 | 879 |
881 Handle<Code> code = isolate()->stub_cache()->FindHandler( | 880 Handle<Code> code = isolate()->stub_cache()->FindHandler( |
882 name, stub_holder_map, kind(), flag, | 881 name, stub_holder_map, handler_kind(), flag, |
883 lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL); | 882 lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL); |
884 // Use the cached value if it exists, and if it is different from the | 883 // Use the cached value if it exists, and if it is different from the |
885 // handler that just missed. | 884 // handler that just missed. |
886 if (!code.is_null()) { | 885 if (!code.is_null()) { |
887 if (!maybe_handler_.is_null() && | 886 if (!maybe_handler_.is_null() && |
888 !maybe_handler_.ToHandleChecked().is_identical_to(code)) { | 887 !maybe_handler_.ToHandleChecked().is_identical_to(code)) { |
889 return code; | 888 return code; |
890 } | 889 } |
891 if (maybe_handler_.is_null()) { | 890 if (maybe_handler_.is_null()) { |
892 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. | 891 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. |
(...skipping 25 matching lines...) Expand all Loading... |
918 Handle<String> name, Handle<Object> unused, | 917 Handle<String> name, Handle<Object> unused, |
919 CacheHolderFlag cache_holder) { | 918 CacheHolderFlag cache_holder) { |
920 if (object->IsString() && | 919 if (object->IsString() && |
921 String::Equals(isolate()->factory()->length_string(), name)) { | 920 String::Equals(isolate()->factory()->length_string(), name)) { |
922 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); | 921 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); |
923 return SimpleFieldLoad(index); | 922 return SimpleFieldLoad(index); |
924 } | 923 } |
925 | 924 |
926 if (object->IsStringWrapper() && | 925 if (object->IsStringWrapper() && |
927 String::Equals(isolate()->factory()->length_string(), name)) { | 926 String::Equals(isolate()->factory()->length_string(), name)) { |
928 if (kind() == Code::LOAD_IC) { | 927 StringLengthStub string_length_stub(isolate()); |
929 StringLengthStub string_length_stub(isolate()); | 928 return string_length_stub.GetCode(); |
930 return string_length_stub.GetCode(); | |
931 } else { | |
932 KeyedStringLengthStub string_length_stub(isolate()); | |
933 return string_length_stub.GetCode(); | |
934 } | |
935 } | 929 } |
936 | 930 |
937 // Use specialized code for getting prototype of functions. | 931 // Use specialized code for getting prototype of functions. |
938 if (object->IsJSFunction() && | 932 if (object->IsJSFunction() && |
939 String::Equals(isolate()->factory()->prototype_string(), name) && | 933 String::Equals(isolate()->factory()->prototype_string(), name) && |
940 Handle<JSFunction>::cast(object)->should_have_prototype() && | 934 Handle<JSFunction>::cast(object)->should_have_prototype() && |
941 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { | 935 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { |
942 Handle<Code> stub; | 936 Handle<Code> stub; |
943 FunctionPrototypeStub function_prototype_stub(isolate(), kind()); | 937 FunctionPrototypeStub function_prototype_stub(isolate(), kind()); |
944 return function_prototype_stub.GetCode(); | 938 return function_prototype_stub.GetCode(); |
945 } | 939 } |
946 | 940 |
947 Handle<HeapType> type = receiver_type(); | 941 Handle<HeapType> type = receiver_type(); |
948 Handle<JSObject> holder(lookup->holder()); | 942 Handle<JSObject> holder(lookup->holder()); |
949 bool receiver_is_holder = object.is_identical_to(holder); | 943 bool receiver_is_holder = object.is_identical_to(holder); |
950 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind()); | 944 LoadStubCompiler compiler(isolate(), handler_kind(), kNoExtraICState, |
| 945 cache_holder); |
951 | 946 |
952 switch (lookup->type()) { | 947 switch (lookup->type()) { |
953 case FIELD: { | 948 case FIELD: { |
954 FieldIndex field = lookup->GetFieldIndex(); | 949 FieldIndex field = lookup->GetFieldIndex(); |
955 if (receiver_is_holder) { | 950 if (receiver_is_holder) { |
956 return SimpleFieldLoad(field); | 951 return SimpleFieldLoad(field); |
957 } | 952 } |
958 return compiler.CompileLoadField( | 953 return compiler.CompileLoadField( |
959 type, holder, name, field, lookup->representation()); | 954 type, holder, name, field, lookup->representation()); |
960 } | 955 } |
(...skipping 2080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3041 #undef ADDR | 3036 #undef ADDR |
3042 }; | 3037 }; |
3043 | 3038 |
3044 | 3039 |
3045 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3040 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3046 return IC_utilities[id]; | 3041 return IC_utilities[id]; |
3047 } | 3042 } |
3048 | 3043 |
3049 | 3044 |
3050 } } // namespace v8::internal | 3045 } } // namespace v8::internal |
OLD | NEW |