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 |