Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(460)

Side by Side Diff: src/ic.cc

Issue 414443002: Always use the LoadStubCompiler for Load handlers, also for keyedload handlers. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Ensure that LoadIC can be used to compile keyed load ICs with shared load handlers Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/stub-cache.h » ('j') | src/stub-cache.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/stub-cache.h » ('j') | src/stub-cache.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698