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