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 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) { | 850 Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) { |
851 if (FLAG_tf_load_ic_stub) { | 851 if (FLAG_tf_load_ic_stub) { |
852 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH); | 852 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH); |
853 return SmiHandler::MakeLoadFieldHandler(isolate(), index); | 853 return SmiHandler::MakeLoadFieldHandler(isolate(), index); |
854 } | 854 } |
855 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); | 855 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); |
856 LoadFieldStub stub(isolate(), index); | 856 LoadFieldStub stub(isolate(), index); |
857 return stub.GetCode(); | 857 return stub.GetCode(); |
858 } | 858 } |
859 | 859 |
860 Handle<Object> LoadIC::SimpleFieldLoadFromPrototype(FieldIndex index, | 860 bool LoadIC::IsPrototypeValidityCellCheckEnough(Handle<Map> receiver_map, |
861 Handle<Map> receiver_map, | 861 Handle<JSObject> holder) { |
862 Handle<JSObject> holder) { | |
863 if (!FLAG_tf_load_ic_stub) return Handle<Object>::null(); | |
864 | |
865 DCHECK(holder->HasFastProperties()); | 862 DCHECK(holder->HasFastProperties()); |
866 | 863 |
867 // The following kinds of receiver maps require custom handler compilation. | 864 // The following kinds of receiver maps require custom handler compilation. |
868 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() || | 865 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() || |
869 receiver_map->IsJSGlobalObjectMap() || | 866 receiver_map->IsJSGlobalObjectMap() || |
870 receiver_map->is_dictionary_map()) { | 867 receiver_map->is_dictionary_map()) { |
871 return Handle<Object>::null(); | 868 return false; |
872 } | 869 } |
873 | 870 |
874 // Switch to custom compiled handler if the prototype chain contains global | 871 // Switch to custom compiled handler if the prototype chain contains global |
875 // or dictionary objects. | 872 // or dictionary objects. |
876 for (PrototypeIterator iter(*receiver_map); !iter.IsAtEnd(); iter.Advance()) { | 873 for (PrototypeIterator iter(*receiver_map); !iter.IsAtEnd(); iter.Advance()) { |
877 JSObject* current = iter.GetCurrent<JSObject>(); | 874 JSObject* current = iter.GetCurrent<JSObject>(); |
878 if (current == *holder) break; | 875 if (current == *holder) break; |
879 Map* current_map = current->map(); | 876 Map* current_map = current->map(); |
880 if (current_map->IsJSGlobalObjectMap() || | 877 if (current_map->IsJSGlobalObjectMap() || |
881 current_map->IsJSGlobalProxyMap() || current_map->is_dictionary_map()) { | 878 current_map->IsJSGlobalProxyMap() || current_map->is_dictionary_map()) { |
882 return Handle<Object>::null(); | 879 return false; |
883 } | 880 } |
884 // Only objects that do not require access checks are allowed in stubs. | 881 // Only objects that do not require access checks are allowed in stubs. |
885 DCHECK(!current_map->is_access_check_needed()); | 882 DCHECK(!current_map->is_access_check_needed()); |
886 } | 883 } |
887 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH); | 884 return true; |
| 885 } |
| 886 |
| 887 Handle<Object> LoadIC::SimpleLoadFromPrototype(Handle<Map> receiver_map, |
| 888 Handle<JSObject> holder, |
| 889 Handle<Object> smi_handler) { |
| 890 DCHECK(IsPrototypeValidityCellCheckEnough(receiver_map, holder)); |
| 891 |
888 Handle<Cell> validity_cell = | 892 Handle<Cell> validity_cell = |
889 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); | 893 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
890 DCHECK(!validity_cell.is_null()); | 894 DCHECK(!validity_cell.is_null()); |
891 | 895 |
892 Handle<Object> handler(SmiHandler::MakeLoadFieldHandler(isolate(), index)); | |
893 Factory* factory = isolate()->factory(); | 896 Factory* factory = isolate()->factory(); |
894 | 897 |
895 Handle<WeakCell> holder_cell = factory->NewWeakCell(holder); | 898 Handle<WeakCell> holder_cell = factory->NewWeakCell(holder); |
896 return factory->NewTuple3(validity_cell, holder_cell, handler); | 899 return factory->NewTuple3(validity_cell, holder_cell, smi_handler); |
897 } | 900 } |
898 | 901 |
899 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { | 902 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { |
900 DCHECK(lookup->state() == LookupIterator::ACCESSOR); | 903 DCHECK(lookup->state() == LookupIterator::ACCESSOR); |
901 Isolate* isolate = lookup->isolate(); | 904 Isolate* isolate = lookup->isolate(); |
902 Handle<Object> accessors = lookup->GetAccessors(); | 905 Handle<Object> accessors = lookup->GetAccessors(); |
903 if (accessors->IsAccessorInfo()) { | 906 if (accessors->IsAccessorInfo()) { |
904 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); | 907 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
905 if (info->getter() != NULL && | 908 if (info->getter() != NULL && |
906 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { | 909 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); | 1192 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
1190 return slow_stub(); | 1193 return slow_stub(); |
1191 } | 1194 } |
1192 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal); | 1195 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal); |
1193 return isolate()->builtins()->LoadIC_Normal(); | 1196 return isolate()->builtins()->LoadIC_Normal(); |
1194 } | 1197 } |
1195 | 1198 |
1196 // -------------- Fields -------------- | 1199 // -------------- Fields -------------- |
1197 if (lookup->property_details().type() == DATA) { | 1200 if (lookup->property_details().type() == DATA) { |
1198 FieldIndex field = lookup->GetFieldIndex(); | 1201 FieldIndex field = lookup->GetFieldIndex(); |
| 1202 Handle<Object> smi_handler = SimpleFieldLoad(field); |
1199 if (receiver_is_holder) { | 1203 if (receiver_is_holder) { |
1200 return SimpleFieldLoad(field); | 1204 return smi_handler; |
1201 } | 1205 } |
1202 Handle<Object> handler = | 1206 if (FLAG_tf_load_ic_stub && |
1203 SimpleFieldLoadFromPrototype(field, map, holder); | 1207 IsPrototypeValidityCellCheckEnough(map, holder)) { |
1204 if (!handler.is_null()) { | 1208 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH); |
1205 return handler; | 1209 return SimpleLoadFromPrototype(map, holder, smi_handler); |
1206 } | 1210 } |
1207 break; // Custom-compiled handler. | 1211 break; // Custom-compiled handler. |
1208 } | 1212 } |
1209 | 1213 |
1210 // -------------- Constant properties -------------- | 1214 // -------------- Constant properties -------------- |
1211 DCHECK(lookup->property_details().type() == DATA_CONSTANT); | 1215 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
1212 if (receiver_is_holder) { | 1216 if (FLAG_tf_load_ic_stub) { |
1213 if (FLAG_tf_load_ic_stub) { | 1217 Handle<Object> smi_handler = SmiHandler::MakeLoadConstantHandler( |
| 1218 isolate(), lookup->GetConstantIndex()); |
| 1219 if (receiver_is_holder) { |
1214 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH); | 1220 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH); |
1215 return SmiHandler::MakeLoadConstantHandler( | 1221 return smi_handler; |
1216 isolate(), lookup->GetConstantIndex()); | |
1217 } | 1222 } |
1218 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); | 1223 if (IsPrototypeValidityCellCheckEnough(map, holder)) { |
1219 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); | 1224 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH); |
1220 return stub.GetCode(); | 1225 return SimpleLoadFromPrototype(map, holder, smi_handler); |
| 1226 } |
| 1227 } else { |
| 1228 if (receiver_is_holder) { |
| 1229 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); |
| 1230 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); |
| 1231 return stub.GetCode(); |
| 1232 } |
1221 } | 1233 } |
1222 break; // Custom-compiled handler. | 1234 break; // Custom-compiled handler. |
1223 } | 1235 } |
1224 | 1236 |
1225 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 1237 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
1226 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); | 1238 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
1227 return slow_stub(); | 1239 return slow_stub(); |
1228 case LookupIterator::ACCESS_CHECK: | 1240 case LookupIterator::ACCESS_CHECK: |
1229 case LookupIterator::JSPROXY: | 1241 case LookupIterator::JSPROXY: |
1230 case LookupIterator::NOT_FOUND: | 1242 case LookupIterator::NOT_FOUND: |
(...skipping 1735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2966 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); | 2978 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
2967 it.Next(); | 2979 it.Next(); |
2968 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 2980 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
2969 Object::GetProperty(&it)); | 2981 Object::GetProperty(&it)); |
2970 } | 2982 } |
2971 | 2983 |
2972 return *result; | 2984 return *result; |
2973 } | 2985 } |
2974 } // namespace internal | 2986 } // namespace internal |
2975 } // namespace v8 | 2987 } // namespace v8 |
OLD | NEW |