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 813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate, | 824 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate, |
825 ExtraICState extra_state) { | 825 ExtraICState extra_state) { |
826 LanguageMode mode = StoreICState::GetLanguageMode(extra_state); | 826 LanguageMode mode = StoreICState::GetLanguageMode(extra_state); |
827 return is_strict(mode) | 827 return is_strict(mode) |
828 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict() | 828 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict() |
829 : isolate->builtins()->KeyedStoreIC_Megamorphic(); | 829 : isolate->builtins()->KeyedStoreIC_Megamorphic(); |
830 } | 830 } |
831 | 831 |
832 Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) { | 832 Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) { |
833 if (FLAG_tf_load_ic_stub) { | 833 if (FLAG_tf_load_ic_stub) { |
| 834 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH); |
834 return handle(Smi::FromInt(index.GetLoadByFieldOffset()), isolate()); | 835 return handle(Smi::FromInt(index.GetLoadByFieldOffset()), isolate()); |
835 } | 836 } |
836 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); | 837 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); |
837 LoadFieldStub stub(isolate(), index); | 838 LoadFieldStub stub(isolate(), index); |
838 return stub.GetCode(); | 839 return stub.GetCode(); |
839 } | 840 } |
840 | 841 |
| 842 Handle<Object> LoadIC::SimpleFieldLoadFromPrototype(FieldIndex index, |
| 843 Handle<Map> receiver_map, |
| 844 Handle<JSObject> holder) { |
| 845 if (!FLAG_tf_load_ic_stub) return Handle<Object>::null(); |
| 846 |
| 847 DCHECK(holder->HasFastProperties()); |
| 848 |
| 849 // The following kinds of receiver maps require custom handler compilation. |
| 850 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() || |
| 851 receiver_map->IsJSGlobalObjectMap() || |
| 852 receiver_map->is_dictionary_map()) { |
| 853 return Handle<Object>::null(); |
| 854 } |
| 855 |
| 856 // Switch to custom compiled handler if the prototype chain contains global |
| 857 // or dictionary objects. |
| 858 for (PrototypeIterator iter(*receiver_map); !iter.IsAtEnd(); iter.Advance()) { |
| 859 JSObject* current = iter.GetCurrent<JSObject>(); |
| 860 if (current == *holder) break; |
| 861 Map* current_map = current->map(); |
| 862 if (current_map->IsJSGlobalObjectMap() || |
| 863 current_map->IsJSGlobalProxyMap() || current_map->is_dictionary_map()) { |
| 864 return Handle<Object>::null(); |
| 865 } |
| 866 // Only objects that do not require access checks are allowed in stubs. |
| 867 DCHECK(!current_map->is_access_check_needed()); |
| 868 } |
| 869 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH); |
| 870 Handle<Cell> validity_cell = |
| 871 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
| 872 DCHECK(!validity_cell.is_null()); |
| 873 |
| 874 Handle<Object> handler(Smi::FromInt(index.GetLoadByFieldOffset()), isolate()); |
| 875 DCHECK(handler->IsSmi()); |
| 876 |
| 877 Factory* factory = isolate()->factory(); |
| 878 |
| 879 Handle<WeakCell> holder_cell = factory->NewWeakCell(holder); |
| 880 return factory->NewTuple3(validity_cell, holder_cell, handler); |
| 881 } |
841 | 882 |
842 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { | 883 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { |
843 DCHECK(lookup->state() == LookupIterator::ACCESSOR); | 884 DCHECK(lookup->state() == LookupIterator::ACCESSOR); |
844 Isolate* isolate = lookup->isolate(); | 885 Isolate* isolate = lookup->isolate(); |
845 Handle<Object> accessors = lookup->GetAccessors(); | 886 Handle<Object> accessors = lookup->GetAccessors(); |
846 if (accessors->IsAccessorInfo()) { | 887 if (accessors->IsAccessorInfo()) { |
847 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); | 888 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
848 if (info->getter() != NULL && | 889 if (info->getter() != NULL && |
849 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { | 890 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { |
850 return false; | 891 return false; |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal); | 1176 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal); |
1136 return isolate()->builtins()->LoadIC_Normal(); | 1177 return isolate()->builtins()->LoadIC_Normal(); |
1137 } | 1178 } |
1138 | 1179 |
1139 // -------------- Fields -------------- | 1180 // -------------- Fields -------------- |
1140 if (lookup->property_details().type() == DATA) { | 1181 if (lookup->property_details().type() == DATA) { |
1141 FieldIndex field = lookup->GetFieldIndex(); | 1182 FieldIndex field = lookup->GetFieldIndex(); |
1142 if (receiver_is_holder) { | 1183 if (receiver_is_holder) { |
1143 return SimpleFieldLoad(field); | 1184 return SimpleFieldLoad(field); |
1144 } | 1185 } |
| 1186 Handle<Object> handler = |
| 1187 SimpleFieldLoadFromPrototype(field, map, holder); |
| 1188 if (!handler.is_null()) { |
| 1189 return handler; |
| 1190 } |
1145 break; // Custom-compiled handler. | 1191 break; // Custom-compiled handler. |
1146 } | 1192 } |
1147 | 1193 |
1148 // -------------- Constant properties -------------- | 1194 // -------------- Constant properties -------------- |
1149 DCHECK(lookup->property_details().type() == DATA_CONSTANT); | 1195 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
1150 if (receiver_is_holder) { | 1196 if (receiver_is_holder) { |
1151 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); | 1197 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); |
1152 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); | 1198 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); |
1153 return stub.GetCode(); | 1199 return stub.GetCode(); |
1154 } | 1200 } |
(...skipping 1744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2899 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); | 2945 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
2900 it.Next(); | 2946 it.Next(); |
2901 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 2947 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
2902 Object::GetProperty(&it)); | 2948 Object::GetProperty(&it)); |
2903 } | 2949 } |
2904 | 2950 |
2905 return *result; | 2951 return *result; |
2906 } | 2952 } |
2907 } // namespace internal | 2953 } // namespace internal |
2908 } // namespace v8 | 2954 } // namespace v8 |
OLD | NEW |