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 <iostream> | 7 #include <iostream> |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/api-arguments-inl.h" | 10 #include "src/api-arguments-inl.h" |
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 } | 986 } |
987 } | 987 } |
988 return true; | 988 return true; |
989 } | 989 } |
990 | 990 |
991 | 991 |
992 void LoadIC::UpdateCaches(LookupIterator* lookup) { | 992 void LoadIC::UpdateCaches(LookupIterator* lookup) { |
993 if (state() == UNINITIALIZED && kind() != Code::LOAD_GLOBAL_IC) { | 993 if (state() == UNINITIALIZED && kind() != Code::LOAD_GLOBAL_IC) { |
994 // This is the first time we execute this inline cache. Set the target to | 994 // This is the first time we execute this inline cache. Set the target to |
995 // the pre monomorphic stub to delay setting the monomorphic state. | 995 // the pre monomorphic stub to delay setting the monomorphic state. |
| 996 TRACE_HANDLER_STATS(isolate(), LoadIC_Premonomorphic); |
996 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 997 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
997 TRACE_IC("LoadIC", lookup->name()); | 998 TRACE_IC("LoadIC", lookup->name()); |
998 return; | 999 return; |
999 } | 1000 } |
1000 | 1001 |
1001 Handle<Object> code; | 1002 Handle<Object> code; |
1002 if (lookup->state() == LookupIterator::JSPROXY || | 1003 if (lookup->state() == LookupIterator::JSPROXY || |
1003 lookup->state() == LookupIterator::ACCESS_CHECK) { | 1004 lookup->state() == LookupIterator::ACCESS_CHECK) { |
1004 code = slow_stub(); | 1005 code = slow_stub(); |
1005 } else if (!lookup->IsFound()) { | 1006 } else if (!lookup->IsFound()) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 DCHECK(!map->is_dictionary_map()); | 1102 DCHECK(!map->is_dictionary_map()); |
1102 DCHECK(map->is_prototype_map()); | 1103 DCHECK(map->is_prototype_map()); |
1103 handler = Smi::FromInt(1); | 1104 handler = Smi::FromInt(1); |
1104 } | 1105 } |
1105 stub_cache()->Set(*name_handle, *map_handle, handler); | 1106 stub_cache()->Set(*name_handle, *map_handle, handler); |
1106 return; | 1107 return; |
1107 } | 1108 } |
1108 stub_cache()->Set(name, map, handler); | 1109 stub_cache()->Set(name, map, handler); |
1109 } | 1110 } |
1110 | 1111 |
| 1112 void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) { |
| 1113 if (!FLAG_runtime_call_stats) return; |
| 1114 |
| 1115 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || |
| 1116 kind() == Code::KEYED_LOAD_IC) { |
| 1117 switch (lookup->state()) { |
| 1118 case LookupIterator::ACCESS_CHECK: |
| 1119 TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_AccessCheck); |
| 1120 break; |
| 1121 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| 1122 TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Exotic); |
| 1123 break; |
| 1124 case LookupIterator::INTERCEPTOR: |
| 1125 TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Interceptor); |
| 1126 break; |
| 1127 case LookupIterator::JSPROXY: |
| 1128 TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_JSProxy); |
| 1129 break; |
| 1130 case LookupIterator::NOT_FOUND: |
| 1131 TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_NonExistent); |
| 1132 break; |
| 1133 case LookupIterator::ACCESSOR: |
| 1134 TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Accessor); |
| 1135 break; |
| 1136 case LookupIterator::DATA: |
| 1137 TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Data); |
| 1138 break; |
| 1139 case LookupIterator::TRANSITION: |
| 1140 TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Transition); |
| 1141 break; |
| 1142 } |
| 1143 } else if (kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC) { |
| 1144 switch (lookup->state()) { |
| 1145 case LookupIterator::ACCESS_CHECK: |
| 1146 TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_AccessCheck); |
| 1147 break; |
| 1148 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| 1149 TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Exotic); |
| 1150 break; |
| 1151 case LookupIterator::INTERCEPTOR: |
| 1152 TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Interceptor); |
| 1153 break; |
| 1154 case LookupIterator::JSPROXY: |
| 1155 TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_JSProxy); |
| 1156 break; |
| 1157 case LookupIterator::NOT_FOUND: |
| 1158 TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_NonExistent); |
| 1159 break; |
| 1160 case LookupIterator::ACCESSOR: |
| 1161 TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Accessor); |
| 1162 break; |
| 1163 case LookupIterator::DATA: |
| 1164 TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Data); |
| 1165 break; |
| 1166 case LookupIterator::TRANSITION: |
| 1167 TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Transition); |
| 1168 break; |
| 1169 } |
| 1170 } else { |
| 1171 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
| 1172 } |
| 1173 } |
| 1174 |
1111 Handle<Object> IC::ComputeHandler(LookupIterator* lookup, | 1175 Handle<Object> IC::ComputeHandler(LookupIterator* lookup, |
1112 Handle<Object> value) { | 1176 Handle<Object> value) { |
1113 // Try to find a globally shared handler stub. | 1177 // Try to find a globally shared handler stub. |
1114 Handle<Object> handler = GetMapIndependentHandler(lookup); | 1178 Handle<Object> handler = GetMapIndependentHandler(lookup); |
1115 if (!handler.is_null()) { | 1179 if (!handler.is_null()) { |
1116 DCHECK(IC::IsHandler(*handler)); | 1180 DCHECK(IC::IsHandler(*handler)); |
1117 return handler; | 1181 return handler; |
1118 } | 1182 } |
1119 | 1183 |
1120 // Otherwise check the map's handler cache for a map-specific handler, and | 1184 // Otherwise check the map's handler cache for a map-specific handler, and |
(...skipping 14 matching lines...) Expand all Loading... |
1135 } | 1199 } |
1136 | 1200 |
1137 Handle<Code> code = PropertyHandlerCompiler::Find( | 1201 Handle<Code> code = PropertyHandlerCompiler::Find( |
1138 lookup->name(), stub_holder_map, kind(), flag); | 1202 lookup->name(), stub_holder_map, kind(), flag); |
1139 // Use the cached value if it exists, and if it is different from the | 1203 // Use the cached value if it exists, and if it is different from the |
1140 // handler that just missed. | 1204 // handler that just missed. |
1141 if (!code.is_null()) { | 1205 if (!code.is_null()) { |
1142 Handle<Object> handler; | 1206 Handle<Object> handler; |
1143 if (maybe_handler_.ToHandle(&handler)) { | 1207 if (maybe_handler_.ToHandle(&handler)) { |
1144 if (!handler.is_identical_to(code)) { | 1208 if (!handler.is_identical_to(code)) { |
1145 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); | 1209 TraceHandlerCacheHitStats(lookup); |
1146 return code; | 1210 return code; |
1147 } | 1211 } |
1148 } else { | 1212 } else { |
1149 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. | 1213 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. |
1150 // In MEGAMORPHIC case, check if the handler in the megamorphic stub | 1214 // In MEGAMORPHIC case, check if the handler in the megamorphic stub |
1151 // cache (which just missed) is different from the cached handler. | 1215 // cache (which just missed) is different from the cached handler. |
1152 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { | 1216 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { |
1153 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map(); | 1217 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map(); |
1154 Object* megamorphic_cached_handler = | 1218 Object* megamorphic_cached_handler = |
1155 stub_cache()->Get(*lookup->name(), map); | 1219 stub_cache()->Get(*lookup->name(), map); |
1156 if (megamorphic_cached_handler != *code) { | 1220 if (megamorphic_cached_handler != *code) { |
1157 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); | 1221 TraceHandlerCacheHitStats(lookup); |
1158 return code; | 1222 return code; |
1159 } | 1223 } |
1160 } else { | 1224 } else { |
1161 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); | 1225 TraceHandlerCacheHitStats(lookup); |
1162 return code; | 1226 return code; |
1163 } | 1227 } |
1164 } | 1228 } |
1165 } | 1229 } |
1166 | 1230 |
1167 code = CompileHandler(lookup, value, flag); | 1231 code = CompileHandler(lookup, value, flag); |
1168 DCHECK(code->is_handler()); | 1232 DCHECK(code->is_handler()); |
1169 DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag); | 1233 DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag); |
1170 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | 1234 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); |
1171 | 1235 |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1721 MAYBE_RETURN_NULL( | 1785 MAYBE_RETURN_NULL( |
1722 Object::SetProperty(&it, value, language_mode(), store_mode)); | 1786 Object::SetProperty(&it, value, language_mode(), store_mode)); |
1723 return value; | 1787 return value; |
1724 } | 1788 } |
1725 | 1789 |
1726 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, | 1790 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, |
1727 JSReceiver::StoreFromKeyed store_mode) { | 1791 JSReceiver::StoreFromKeyed store_mode) { |
1728 if (state() == UNINITIALIZED) { | 1792 if (state() == UNINITIALIZED) { |
1729 // This is the first time we execute this inline cache. Set the target to | 1793 // This is the first time we execute this inline cache. Set the target to |
1730 // the pre monomorphic stub to delay setting the monomorphic state. | 1794 // the pre monomorphic stub to delay setting the monomorphic state. |
| 1795 TRACE_HANDLER_STATS(isolate(), StoreIC_Premonomorphic); |
1731 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 1796 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
1732 TRACE_IC("StoreIC", lookup->name()); | 1797 TRACE_IC("StoreIC", lookup->name()); |
1733 return; | 1798 return; |
1734 } | 1799 } |
1735 | 1800 |
1736 bool use_ic = LookupForWrite(lookup, value, store_mode); | 1801 bool use_ic = LookupForWrite(lookup, value, store_mode); |
1737 if (!use_ic) { | 1802 if (!use_ic) { |
1738 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); | 1803 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); |
1739 } | 1804 } |
1740 Handle<Object> handler = use_ic ? ComputeHandler(lookup, value) | 1805 Handle<Object> handler = use_ic ? ComputeHandler(lookup, value) |
(...skipping 1328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3069 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); | 3134 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
3070 it.Next(); | 3135 it.Next(); |
3071 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 3136 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
3072 Object::GetProperty(&it)); | 3137 Object::GetProperty(&it)); |
3073 } | 3138 } |
3074 | 3139 |
3075 return *result; | 3140 return *result; |
3076 } | 3141 } |
3077 } // namespace internal | 3142 } // namespace internal |
3078 } // namespace v8 | 3143 } // namespace v8 |
OLD | NEW |