| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 Handle<String> name) { | 1138 Handle<String> name) { |
| 1139 if (state() == UNINITIALIZED) { | 1139 if (state() == UNINITIALIZED) { |
| 1140 // This is the first time we execute this inline cache. | 1140 // This is the first time we execute this inline cache. |
| 1141 // Set the target to the pre monomorphic stub to delay | 1141 // Set the target to the pre monomorphic stub to delay |
| 1142 // setting the monomorphic state. | 1142 // setting the monomorphic state. |
| 1143 set_target(*pre_monomorphic_stub()); | 1143 set_target(*pre_monomorphic_stub()); |
| 1144 TRACE_IC("LoadIC", name); | 1144 TRACE_IC("LoadIC", name); |
| 1145 return; | 1145 return; |
| 1146 } | 1146 } |
| 1147 | 1147 |
| 1148 Handle<Type> type = CurrentTypeOf(object, isolate()); |
| 1148 Handle<Code> code; | 1149 Handle<Code> code; |
| 1149 if (!lookup->IsCacheable()) { | 1150 if (!lookup->IsCacheable()) { |
| 1150 // Bail out if the result is not cacheable. | 1151 // Bail out if the result is not cacheable. |
| 1151 code = slow_stub(); | 1152 code = slow_stub(); |
| 1152 } else if (!lookup->IsProperty()) { | 1153 } else if (!lookup->IsProperty()) { |
| 1153 if (kind() == Code::LOAD_IC) { | 1154 if (kind() == Code::LOAD_IC) { |
| 1154 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object); | 1155 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, type); |
| 1155 } else { | 1156 } else { |
| 1156 code = slow_stub(); | 1157 code = slow_stub(); |
| 1157 } | 1158 } |
| 1158 } else { | 1159 } else { |
| 1159 code = ComputeHandler(lookup, object, name); | 1160 code = ComputeHandler(lookup, object, name); |
| 1160 } | 1161 } |
| 1161 | 1162 |
| 1162 PatchCache(CurrentTypeOf(object, isolate()), name, code); | 1163 PatchCache(type, name, code); |
| 1163 TRACE_IC("LoadIC", name); | 1164 TRACE_IC("LoadIC", name); |
| 1164 } | 1165 } |
| 1165 | 1166 |
| 1166 | 1167 |
| 1167 void IC::UpdateMegamorphicCache(Type* type, Name* name, Code* code) { | 1168 void IC::UpdateMegamorphicCache(Type* type, Name* name, Code* code) { |
| 1168 // Cache code holding map should be consistent with | 1169 // Cache code holding map should be consistent with |
| 1169 // GenerateMonomorphicCacheProbe. | 1170 // GenerateMonomorphicCacheProbe. |
| 1170 Map* map = *TypeToMap(type, isolate()); | 1171 Map* map = *TypeToMap(type, isolate()); |
| 1171 isolate()->stub_cache()->Set(name, map, code); | 1172 isolate()->stub_cache()->Set(name, map, code); |
| 1172 } | 1173 } |
| 1173 | 1174 |
| 1174 | 1175 |
| 1175 Handle<Code> IC::ComputeHandler(LookupResult* lookup, | 1176 Handle<Code> IC::ComputeHandler(LookupResult* lookup, |
| 1176 Handle<Object> object, | 1177 Handle<Object> object, |
| 1177 Handle<String> name, | 1178 Handle<String> name, |
| 1178 Handle<Object> value) { | 1179 Handle<Object> value) { |
| 1179 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); | 1180 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); |
| 1180 Handle<HeapObject> stub_holder(GetCodeCacheHolder( | 1181 Handle<HeapObject> stub_holder(GetCodeCacheHolder( |
| 1181 isolate(), *object, cache_holder)); | 1182 isolate(), *object, cache_holder)); |
| 1182 | 1183 |
| 1183 Handle<Code> code = isolate()->stub_cache()->FindHandler( | 1184 Handle<Code> code = isolate()->stub_cache()->FindHandler( |
| 1184 name, stub_holder, kind(), cache_holder, strict_mode()); | 1185 name, handle(stub_holder->map()), kind(), cache_holder, strict_mode()); |
| 1185 if (!code.is_null()) return code; | 1186 if (!code.is_null()) return code; |
| 1186 | 1187 |
| 1187 code = CompileHandler(lookup, object, name, value, cache_holder); | 1188 code = CompileHandler(lookup, object, name, value, cache_holder); |
| 1188 ASSERT(code->is_handler()); | 1189 ASSERT(code->is_handler()); |
| 1189 | 1190 |
| 1190 if (code->type() != Code::NORMAL) { | 1191 if (code->type() != Code::NORMAL) { |
| 1191 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | 1192 HeapObject::UpdateMapCodeCache(stub_holder, name, code); |
| 1192 } | 1193 } |
| 1193 | 1194 |
| 1194 return code; | 1195 return code; |
| 1195 } | 1196 } |
| 1196 | 1197 |
| 1197 | 1198 |
| 1198 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, | 1199 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, |
| 1199 Handle<Object> object, | 1200 Handle<Object> object, |
| 1200 Handle<String> name, | 1201 Handle<String> name, |
| 1201 Handle<Object> unused, | 1202 Handle<Object> unused, |
| 1202 InlineCacheHolderFlag cache_holder) { | 1203 InlineCacheHolderFlag cache_holder) { |
| 1203 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { | 1204 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { |
| 1204 int length_index = String::kLengthOffset / kPointerSize; | 1205 int length_index = String::kLengthOffset / kPointerSize; |
| 1205 return SimpleFieldLoad(length_index); | 1206 return SimpleFieldLoad(length_index); |
| 1206 } | 1207 } |
| 1207 | 1208 |
| 1209 Handle<Type> type = CurrentTypeOf(object, isolate()); |
| 1208 Handle<JSObject> holder(lookup->holder()); | 1210 Handle<JSObject> holder(lookup->holder()); |
| 1209 LoadStubCompiler compiler(isolate(), cache_holder, kind()); | 1211 LoadStubCompiler compiler(isolate(), cache_holder, kind()); |
| 1210 | 1212 |
| 1211 switch (lookup->type()) { | 1213 switch (lookup->type()) { |
| 1212 case FIELD: { | 1214 case FIELD: { |
| 1213 PropertyIndex field = lookup->GetFieldIndex(); | 1215 PropertyIndex field = lookup->GetFieldIndex(); |
| 1214 if (object.is_identical_to(holder)) { | 1216 if (object.is_identical_to(holder)) { |
| 1215 return SimpleFieldLoad(field.translate(holder), | 1217 return SimpleFieldLoad(field.translate(holder), |
| 1216 field.is_inobject(holder), | 1218 field.is_inobject(holder), |
| 1217 lookup->representation()); | 1219 lookup->representation()); |
| 1218 } | 1220 } |
| 1219 return compiler.CompileLoadField( | 1221 return compiler.CompileLoadField( |
| 1220 object, holder, name, field, lookup->representation()); | 1222 type, holder, name, field, lookup->representation()); |
| 1221 } | 1223 } |
| 1222 case CONSTANT: { | 1224 case CONSTANT: { |
| 1223 Handle<Object> constant(lookup->GetConstant(), isolate()); | 1225 Handle<Object> constant(lookup->GetConstant(), isolate()); |
| 1224 // TODO(2803): Don't compute a stub for cons strings because they cannot | 1226 // TODO(2803): Don't compute a stub for cons strings because they cannot |
| 1225 // be embedded into code. | 1227 // be embedded into code. |
| 1226 if (constant->IsConsString()) break; | 1228 if (constant->IsConsString()) break; |
| 1227 return compiler.CompileLoadConstant(object, holder, name, constant); | 1229 return compiler.CompileLoadConstant(type, holder, name, constant); |
| 1228 } | 1230 } |
| 1229 case NORMAL: | 1231 case NORMAL: |
| 1230 if (kind() != Code::LOAD_IC) break; | 1232 if (kind() != Code::LOAD_IC) break; |
| 1231 if (holder->IsGlobalObject()) { | 1233 if (holder->IsGlobalObject()) { |
| 1232 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); | 1234 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 1233 Handle<PropertyCell> cell( | 1235 Handle<PropertyCell> cell( |
| 1234 global->GetPropertyCell(lookup), isolate()); | 1236 global->GetPropertyCell(lookup), isolate()); |
| 1235 Handle<Code> code = compiler.CompileLoadGlobal( | 1237 Handle<Code> code = compiler.CompileLoadGlobal( |
| 1236 object, global, cell, name, lookup->IsDontDelete()); | 1238 type, global, cell, name, lookup->IsDontDelete()); |
| 1237 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1239 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1238 Handle<HeapObject> stub_holder(GetCodeCacheHolder( | 1240 Handle<HeapObject> stub_holder(GetCodeCacheHolder( |
| 1239 isolate(), *object, cache_holder)); | 1241 isolate(), *object, cache_holder)); |
| 1240 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | 1242 HeapObject::UpdateMapCodeCache(stub_holder, name, code); |
| 1241 return code; | 1243 return code; |
| 1242 } | 1244 } |
| 1243 // There is only one shared stub for loading normalized | 1245 // There is only one shared stub for loading normalized |
| 1244 // properties. It does not traverse the prototype chain, so the | 1246 // properties. It does not traverse the prototype chain, so the |
| 1245 // property must be found in the object for the stub to be | 1247 // property must be found in the object for the stub to be |
| 1246 // applicable. | 1248 // applicable. |
| 1247 if (!object.is_identical_to(holder)) break; | 1249 if (!object.is_identical_to(holder)) break; |
| 1248 return isolate()->builtins()->LoadIC_Normal(); | 1250 return isolate()->builtins()->LoadIC_Normal(); |
| 1249 case CALLBACKS: { | 1251 case CALLBACKS: { |
| 1250 // Use simple field loads for some well-known callback properties. | 1252 // Use simple field loads for some well-known callback properties. |
| 1251 if (object->IsJSObject()) { | 1253 if (object->IsJSObject()) { |
| 1252 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1254 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1253 Handle<Map> map(receiver->map()); | 1255 Handle<Map> map(receiver->map()); |
| 1254 int object_offset; | 1256 int object_offset; |
| 1255 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { | 1257 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { |
| 1256 return SimpleFieldLoad(object_offset / kPointerSize); | 1258 return SimpleFieldLoad(object_offset / kPointerSize); |
| 1257 } | 1259 } |
| 1258 } | 1260 } |
| 1259 | 1261 |
| 1260 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1262 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
| 1261 if (callback->IsExecutableAccessorInfo()) { | 1263 if (callback->IsExecutableAccessorInfo()) { |
| 1262 Handle<ExecutableAccessorInfo> info = | 1264 Handle<ExecutableAccessorInfo> info = |
| 1263 Handle<ExecutableAccessorInfo>::cast(callback); | 1265 Handle<ExecutableAccessorInfo>::cast(callback); |
| 1264 if (v8::ToCData<Address>(info->getter()) == 0) break; | 1266 if (v8::ToCData<Address>(info->getter()) == 0) break; |
| 1265 if (!info->IsCompatibleReceiver(*object)) break; | 1267 if (!info->IsCompatibleReceiver(*object)) break; |
| 1266 return compiler.CompileLoadCallback(object, holder, name, info); | 1268 return compiler.CompileLoadCallback(type, holder, name, info); |
| 1267 } else if (callback->IsAccessorPair()) { | 1269 } else if (callback->IsAccessorPair()) { |
| 1268 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), | 1270 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), |
| 1269 isolate()); | 1271 isolate()); |
| 1270 if (!getter->IsJSFunction()) break; | 1272 if (!getter->IsJSFunction()) break; |
| 1271 if (holder->IsGlobalObject()) break; | 1273 if (holder->IsGlobalObject()) break; |
| 1272 if (!holder->HasFastProperties()) break; | 1274 if (!holder->HasFastProperties()) break; |
| 1273 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1275 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 1274 if (!object->IsJSObject() && | 1276 if (!object->IsJSObject() && |
| 1275 !function->IsBuiltin() && | 1277 !function->IsBuiltin() && |
| 1276 function->shared()->is_classic_mode()) { | 1278 function->shared()->is_classic_mode()) { |
| 1277 // Calling non-strict non-builtins with a value as the receiver | 1279 // Calling non-strict non-builtins with a value as the receiver |
| 1278 // requires boxing. | 1280 // requires boxing. |
| 1279 break; | 1281 break; |
| 1280 } | 1282 } |
| 1281 CallOptimization call_optimization(function); | 1283 CallOptimization call_optimization(function); |
| 1282 if (call_optimization.is_simple_api_call() && | 1284 if (call_optimization.is_simple_api_call() && |
| 1283 call_optimization.IsCompatibleReceiver(*object)) { | 1285 call_optimization.IsCompatibleReceiver(*object)) { |
| 1284 return compiler.CompileLoadCallback( | 1286 return compiler.CompileLoadCallback( |
| 1285 object, holder, name, call_optimization); | 1287 type, holder, name, call_optimization); |
| 1286 } | 1288 } |
| 1287 return compiler.CompileLoadViaGetter(object, holder, name, function); | 1289 return compiler.CompileLoadViaGetter(type, holder, name, function); |
| 1288 } | 1290 } |
| 1289 // TODO(dcarney): Handle correctly. | 1291 // TODO(dcarney): Handle correctly. |
| 1290 if (callback->IsDeclaredAccessorInfo()) break; | 1292 if (callback->IsDeclaredAccessorInfo()) break; |
| 1291 ASSERT(callback->IsForeign()); | 1293 ASSERT(callback->IsForeign()); |
| 1292 // No IC support for old-style native accessors. | 1294 // No IC support for old-style native accessors. |
| 1293 break; | 1295 break; |
| 1294 } | 1296 } |
| 1295 case INTERCEPTOR: | 1297 case INTERCEPTOR: |
| 1296 ASSERT(HasInterceptorGetter(*holder)); | 1298 ASSERT(HasInterceptorGetter(*holder)); |
| 1297 return compiler.CompileLoadInterceptor(object, holder, name); | 1299 return compiler.CompileLoadInterceptor(type, holder, name); |
| 1298 default: | 1300 default: |
| 1299 break; | 1301 break; |
| 1300 } | 1302 } |
| 1301 | 1303 |
| 1302 return slow_stub(); | 1304 return slow_stub(); |
| 1303 } | 1305 } |
| 1304 | 1306 |
| 1305 | 1307 |
| 1306 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { | 1308 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
| 1307 // This helper implements a few common fast cases for converting | 1309 // This helper implements a few common fast cases for converting |
| (...skipping 1468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2776 #undef ADDR | 2778 #undef ADDR |
| 2777 }; | 2779 }; |
| 2778 | 2780 |
| 2779 | 2781 |
| 2780 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2782 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2781 return IC_utilities[id]; | 2783 return IC_utilities[id]; |
| 2782 } | 2784 } |
| 2783 | 2785 |
| 2784 | 2786 |
| 2785 } } // namespace v8::internal | 2787 } } // namespace v8::internal |
| OLD | NEW |