Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(496)

Side by Side Diff: src/ic.cc

Issue 12051057: Merge UpdateLoadCaches into a single function dispatching on ComputeLoadMonorphic and UpdateMegamor… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 923 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 // If we did not find a property, check if we need to throw an exception. 934 // If we did not find a property, check if we need to throw an exception.
935 if (!lookup.IsFound()) { 935 if (!lookup.IsFound()) {
936 if (IsUndeclaredGlobal(object)) { 936 if (IsUndeclaredGlobal(object)) {
937 return ReferenceError("not_defined", name); 937 return ReferenceError("not_defined", name);
938 } 938 }
939 LOG(isolate(), SuspectReadEvent(*name, *object)); 939 LOG(isolate(), SuspectReadEvent(*name, *object));
940 } 940 }
941 941
942 // Update inline cache and stub cache. 942 // Update inline cache and stub cache.
943 if (FLAG_use_ic) { 943 if (FLAG_use_ic) {
944 UpdateLoadCaches(&lookup, state, object, name); 944 UpdateCaches(&lookup, state, object, name);
945 } 945 }
946 946
947 PropertyAttributes attr; 947 PropertyAttributes attr;
948 if (lookup.IsInterceptor() || lookup.IsHandler()) { 948 if (lookup.IsInterceptor() || lookup.IsHandler()) {
949 // Get the property. 949 // Get the property.
950 Handle<Object> result = 950 Handle<Object> result =
951 Object::GetProperty(object, object, &lookup, name, &attr); 951 Object::GetProperty(object, object, &lookup, name, &attr);
952 RETURN_IF_EMPTY_HANDLE(isolate(), result); 952 RETURN_IF_EMPTY_HANDLE(isolate(), result);
953 // If the property is not present, check if we need to throw an 953 // If the property is not present, check if we need to throw an
954 // exception. 954 // exception.
955 if (attr == ABSENT && IsUndeclaredGlobal(object)) { 955 if (attr == ABSENT && IsUndeclaredGlobal(object)) {
956 return ReferenceError("not_defined", name); 956 return ReferenceError("not_defined", name);
957 } 957 }
958 return *result; 958 return *result;
959 } 959 }
960 960
961 // Get the property. 961 // Get the property.
962 return object->GetProperty(*object, &lookup, *name, &attr); 962 return object->GetProperty(*object, &lookup, *name, &attr);
963 } 963 }
964 964
965 965
966 void LoadIC::UpdateLoadCaches(LookupResult* lookup, 966 void LoadIC::UpdateCaches(LookupResult* lookup,
967 State state, 967 State state,
968 Handle<Object> object, 968 Handle<Object> object,
969 Handle<String> name) { 969 Handle<String> name) {
970 // Bail out if the result is not cacheable. 970 // Bail out if the result is not cacheable.
971 if (!lookup->IsCacheable()) return; 971 if (!lookup->IsCacheable()) return;
972 972
973 // Loading properties from values is not common, so don't try to 973 // Loading properties from values is not common, so don't try to
974 // deal with non-JS objects here. 974 // deal with non-JS objects here.
975 if (!object->IsJSObject()) return; 975 if (!object->IsJSObject()) return;
976 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
977 976
978 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; 977 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
979 978
980 // Compute the code stub for this load. 979 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
981 Handle<Code> code; 980 Handle<Code> code;
982 if (state == UNINITIALIZED) { 981 if (state == UNINITIALIZED) {
983 // This is the first time we execute this inline cache. 982 // This is the first time we execute this inline cache.
984 // Set the target to the pre monomorphic stub to delay 983 // Set the target to the pre monomorphic stub to delay
985 // setting the monomorphic state. 984 // setting the monomorphic state.
986 code = pre_monomorphic_stub(); 985 code = pre_monomorphic_stub();
987 } else if (!lookup->IsProperty()) {
988 // Nonexistent property. The result is undefined.
989 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
990 } else { 986 } else {
991 // Compute monomorphic stub. 987 code = ComputeLoadMonomorphic(lookup, receiver, name);
992 Handle<JSObject> holder(lookup->holder()); 988 if (code.is_null()) return;
993 switch (lookup->type()) {
994 case FIELD:
995 code = isolate()->stub_cache()->ComputeLoadField(
996 name, receiver, holder, lookup->GetFieldIndex());
997 break;
998 case CONSTANT_FUNCTION: {
999 Handle<JSFunction> constant(lookup->GetConstantFunction());
1000 code = isolate()->stub_cache()->ComputeLoadConstant(
1001 name, receiver, holder, constant);
1002 break;
1003 }
1004 case NORMAL:
1005 if (holder->IsGlobalObject()) {
1006 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1007 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
1008 code = isolate()->stub_cache()->ComputeLoadGlobal(
1009 name, receiver, global, cell, lookup->IsDontDelete());
1010 } else {
1011 // There is only one shared stub for loading normalized
1012 // properties. It does not traverse the prototype chain, so the
1013 // property must be found in the receiver for the stub to be
1014 // applicable.
1015 if (!holder.is_identical_to(receiver)) return;
1016 code = isolate()->stub_cache()->ComputeLoadNormal();
1017 }
1018 break;
1019 case CALLBACKS: {
1020 Handle<Object> callback(lookup->GetCallbackObject());
1021 if (callback->IsAccessorInfo()) {
1022 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
1023 if (v8::ToCData<Address>(info->getter()) == 0) return;
1024 if (!info->IsCompatibleReceiver(*receiver)) return;
1025 code = isolate()->stub_cache()->ComputeLoadCallback(
1026 name, receiver, holder, info);
1027 } else if (callback->IsAccessorPair()) {
1028 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter());
1029 if (!getter->IsJSFunction()) return;
1030 if (holder->IsGlobalObject()) return;
1031 if (!holder->HasFastProperties()) return;
1032 code = isolate()->stub_cache()->ComputeLoadViaGetter(
1033 name, receiver, holder, Handle<JSFunction>::cast(getter));
1034 } else {
1035 ASSERT(callback->IsForeign());
1036 // No IC support for old-style native accessors.
1037 return;
1038 }
1039 break;
1040 }
1041 case INTERCEPTOR:
1042 ASSERT(HasInterceptorGetter(*holder));
1043 code = isolate()->stub_cache()->ComputeLoadInterceptor(
1044 name, receiver, holder);
1045 break;
1046 default:
1047 return;
1048 }
1049 } 989 }
1050 990
1051 // Patch the call site depending on the state of the cache. 991 // Patch the call site depending on the state of the cache.
1052 switch (state) { 992 switch (state) {
1053 case UNINITIALIZED: 993 case UNINITIALIZED:
1054 case PREMONOMORPHIC: 994 case PREMONOMORPHIC:
1055 case MONOMORPHIC_PROTOTYPE_FAILURE: 995 case MONOMORPHIC_PROTOTYPE_FAILURE:
1056 set_target(*code); 996 set_target(*code);
1057 break; 997 break;
1058 case MONOMORPHIC: 998 case MONOMORPHIC:
1059 if (target() != *code) { 999 if (target() != *code) {
1060 // We are transitioning from monomorphic to megamorphic case. 1000 // We are transitioning from monomorphic to megamorphic case.
1061 // Place the current monomorphic stub and stub compiled for 1001 // Place the current monomorphic stub and stub compiled for
1062 // the receiver into stub cache. 1002 // the receiver into stub cache.
1063 Map* map = target()->FindFirstMap(); 1003 Map* map = target()->FindFirstMap();
1064 if (map != NULL) { 1004 if (map != NULL) {
1065 isolate()->stub_cache()->Set(*name, map, target()); 1005 UpdateMegamorphicCache(map, *name, target());
1066 } 1006 }
1067 isolate()->stub_cache()->Set(*name, receiver->map(), *code); 1007 UpdateMegamorphicCache(receiver->map(), *name, *code);
1068
1069 set_target(*megamorphic_stub()); 1008 set_target(*megamorphic_stub());
1070 } 1009 }
1071 break; 1010 break;
1072 case MEGAMORPHIC: 1011 case MEGAMORPHIC:
1073 // Cache code holding map should be consistent with 1012 UpdateMegamorphicCache(receiver->map(), *name, *code);
1074 // GenerateMonomorphicCacheProbe.
1075 isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1076 break; 1013 break;
1077 case DEBUG_STUB: 1014 case DEBUG_STUB:
1078 break; 1015 break;
1079 case POLYMORPHIC: 1016 case POLYMORPHIC:
1080 case GENERIC: 1017 case GENERIC:
1081 UNREACHABLE(); 1018 UNREACHABLE();
1082 break; 1019 break;
1083 } 1020 }
1084 1021
1085 TRACE_IC("LoadIC", name, state, target()); 1022 TRACE_IC("LoadIC", name, state, target());
1086 } 1023 }
1087 1024
1088 1025
1026 void LoadIC::UpdateMegamorphicCache(Map* map, String* name, Code* code) {
1027 // Cache code holding map should be consistent with
1028 // GenerateMonomorphicCacheProbe.
1029 isolate()->stub_cache()->Set(name, map, code);
1030 }
1031
1032
1033 Handle<Code> LoadIC::ComputeLoadMonomorphic(LookupResult* lookup,
1034 Handle<JSObject> receiver,
1035 Handle<String> name) {
1036 if (!lookup->IsProperty()) {
1037 // Nonexistent property. The result is undefined.
1038 return isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
1039 }
1040
1041 // Compute monomorphic stub.
1042 Handle<JSObject> holder(lookup->holder());
1043 switch (lookup->type()) {
1044 case FIELD:
1045 return isolate()->stub_cache()->ComputeLoadField(
1046 name, receiver, holder, lookup->GetFieldIndex());
1047 case CONSTANT_FUNCTION: {
1048 Handle<JSFunction> constant(lookup->GetConstantFunction());
1049 return isolate()->stub_cache()->ComputeLoadConstant(
1050 name, receiver, holder, constant);
1051 }
1052 case NORMAL:
1053 if (holder->IsGlobalObject()) {
1054 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1055 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
1056 return isolate()->stub_cache()->ComputeLoadGlobal(
1057 name, receiver, global, cell, lookup->IsDontDelete());
1058 }
1059 // There is only one shared stub for loading normalized
1060 // properties. It does not traverse the prototype chain, so the
1061 // property must be found in the receiver for the stub to be
1062 // applicable.
1063 if (!holder.is_identical_to(receiver)) break;
1064 return isolate()->stub_cache()->ComputeLoadNormal();
1065 case CALLBACKS: {
1066 Handle<Object> callback(lookup->GetCallbackObject());
1067 if (callback->IsAccessorInfo()) {
1068 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
1069 if (v8::ToCData<Address>(info->getter()) == 0) break;
1070 if (!info->IsCompatibleReceiver(*receiver)) break;
1071 return isolate()->stub_cache()->ComputeLoadCallback(
1072 name, receiver, holder, info);
1073 } else if (callback->IsAccessorPair()) {
1074 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter());
1075 if (!getter->IsJSFunction()) break;
1076 if (holder->IsGlobalObject()) break;
1077 if (!holder->HasFastProperties()) break;
1078 return isolate()->stub_cache()->ComputeLoadViaGetter(
1079 name, receiver, holder, Handle<JSFunction>::cast(getter));
1080 }
1081 ASSERT(callback->IsForeign());
1082 // No IC support for old-style native accessors.
1083 break;
1084 }
1085 case INTERCEPTOR:
1086 ASSERT(HasInterceptorGetter(*holder));
1087 return isolate()->stub_cache()->ComputeLoadInterceptor(
1088 name, receiver, holder);
1089 default:
1090 break;
1091 }
1092 return Handle<Code>::null();
1093 }
1094
1095
1089 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { 1096 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1090 // This helper implements a few common fast cases for converting 1097 // This helper implements a few common fast cases for converting
1091 // non-smi keys of keyed loads/stores to a smi or a string. 1098 // non-smi keys of keyed loads/stores to a smi or a string.
1092 if (key->IsHeapNumber()) { 1099 if (key->IsHeapNumber()) {
1093 double value = Handle<HeapNumber>::cast(key)->value(); 1100 double value = Handle<HeapNumber>::cast(key)->value();
1094 if (isnan(value)) { 1101 if (isnan(value)) {
1095 key = isolate->factory()->nan_symbol(); 1102 key = isolate->factory()->nan_symbol();
1096 } else { 1103 } else {
1097 int int_value = FastD2I(value); 1104 int int_value = FastD2I(value);
1098 if (value == int_value && Smi::IsValid(int_value)) { 1105 if (value == int_value && Smi::IsValid(int_value)) {
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1255 if (!stub.is_null()) set_target(*stub); 1262 if (!stub.is_null()) set_target(*stub);
1256 } 1263 }
1257 1264
1258 TRACE_IC("KeyedLoadIC", key, state, target()); 1265 TRACE_IC("KeyedLoadIC", key, state, target());
1259 1266
1260 // Get the property. 1267 // Get the property.
1261 return Runtime::GetObjectProperty(isolate(), object, key); 1268 return Runtime::GetObjectProperty(isolate(), object, key);
1262 } 1269 }
1263 1270
1264 1271
1265 void KeyedLoadIC::UpdateLoadCaches(LookupResult* lookup, 1272 Handle<Code> KeyedLoadIC::ComputeLoadMonomorphic(LookupResult* lookup,
1266 State state, 1273 Handle<JSObject> receiver,
1267 Handle<Object> object, 1274 Handle<String> name) {
1268 Handle<String> name) {
1269 // Bail out if we didn't find a result. 1275 // Bail out if we didn't find a result.
1270 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 1276 if (!lookup->IsProperty()) return Handle<Code>::null();
1271 1277
1272 if (!object->IsJSObject()) return; 1278 // Compute a monomorphic stub.
1273 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1279 Handle<JSObject> holder(lookup->holder());
1274 1280 switch (lookup->type()) {
1275 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; 1281 case FIELD:
1276 1282 return isolate()->stub_cache()->ComputeKeyedLoadField(
1277 // Compute the code stub for this load. 1283 name, receiver, holder, lookup->GetFieldIndex());
1278 Handle<Code> code; 1284 case CONSTANT_FUNCTION: {
1279 1285 Handle<JSFunction> constant(lookup->GetConstantFunction());
1280 if (state == UNINITIALIZED) { 1286 return isolate()->stub_cache()->ComputeKeyedLoadConstant(
1281 // This is the first time we execute this inline cache. 1287 name, receiver, holder, constant);
1282 // Set the target to the pre monomorphic stub to delay
1283 // setting the monomorphic state.
1284 code = pre_monomorphic_stub();
1285 } else {
1286 // Compute a monomorphic stub.
1287 Handle<JSObject> holder(lookup->holder());
1288 switch (lookup->type()) {
1289 case FIELD:
1290 code = isolate()->stub_cache()->ComputeKeyedLoadField(
1291 name, receiver, holder, lookup->GetFieldIndex());
1292 break;
1293 case CONSTANT_FUNCTION: {
1294 Handle<JSFunction> constant(lookup->GetConstantFunction());
1295 code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
1296 name, receiver, holder, constant);
1297 break;
1298 }
1299 case CALLBACKS: {
1300 Handle<Object> callback_object(lookup->GetCallbackObject());
1301 if (!callback_object->IsAccessorInfo()) return;
1302 Handle<AccessorInfo> callback =
1303 Handle<AccessorInfo>::cast(callback_object);
1304 if (v8::ToCData<Address>(callback->getter()) == 0) return;
1305 if (!callback->IsCompatibleReceiver(*receiver)) return;
1306 code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
1307 name, receiver, holder, callback);
1308 break;
1309 }
1310 case INTERCEPTOR:
1311 ASSERT(HasInterceptorGetter(lookup->holder()));
1312 code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
1313 name, receiver, holder);
1314 break;
1315 default:
1316 // Always rewrite to the generic case so that we do not
1317 // repeatedly try to rewrite.
1318 code = generic_stub();
1319 break;
1320 } 1288 }
1289 case CALLBACKS: {
1290 Handle<Object> callback_object(lookup->GetCallbackObject());
1291 if (!callback_object->IsAccessorInfo()) break;
1292 Handle<AccessorInfo> callback =
1293 Handle<AccessorInfo>::cast(callback_object);
1294 if (v8::ToCData<Address>(callback->getter()) == 0) break;
1295 if (!callback->IsCompatibleReceiver(*receiver)) break;
1296 return isolate()->stub_cache()->ComputeKeyedLoadCallback(
1297 name, receiver, holder, callback);
1298 }
1299 case INTERCEPTOR:
1300 ASSERT(HasInterceptorGetter(lookup->holder()));
1301 return isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
1302 name, receiver, holder);
1303 default:
1304 // Always rewrite to the generic case so that we do not
1305 // repeatedly try to rewrite.
1306 return generic_stub();
1321 } 1307 }
1322 1308 return Handle<Code>::null();
1323 // Patch the call site depending on the state of the cache.
1324 switch (state) {
1325 case UNINITIALIZED:
1326 case PREMONOMORPHIC:
1327 case POLYMORPHIC:
1328 set_target(*code);
1329 break;
1330 case MONOMORPHIC:
1331 // Only move to megamorphic if the target changes.
1332 if (target() != *code) {
1333 set_target(*megamorphic_stub());
1334 }
1335 break;
1336 case MEGAMORPHIC:
1337 case GENERIC:
1338 case DEBUG_STUB:
1339 break;
1340 case MONOMORPHIC_PROTOTYPE_FAILURE:
1341 UNREACHABLE();
1342 break;
1343 }
1344
1345 TRACE_IC("KeyedLoadIC", name, state, target());
1346 } 1309 }
1347 1310
1348 1311
1349 static bool StoreICableLookup(LookupResult* lookup) { 1312 static bool StoreICableLookup(LookupResult* lookup) {
1350 // Bail out if we didn't find a result. 1313 // Bail out if we didn't find a result.
1351 if (!lookup->IsFound()) return false; 1314 if (!lookup->IsFound()) return false;
1352 1315
1353 // Bail out if inline caching is not allowed. 1316 // Bail out if inline caching is not allowed.
1354 if (!lookup->IsCacheable()) return false; 1317 if (!lookup->IsCacheable()) return false;
1355 1318
(...skipping 1316 matching lines...) Expand 10 before | Expand all | Expand 10 after
2672 #undef ADDR 2635 #undef ADDR
2673 }; 2636 };
2674 2637
2675 2638
2676 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2639 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2677 return IC_utilities[id]; 2640 return IC_utilities[id];
2678 } 2641 }
2679 2642
2680 2643
2681 } } // namespace v8::internal 2644 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698