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

Side by Side Diff: src/ic.cc

Issue 12340112: Polymorphism support for load IC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Added ARM port, introduced GenerateTailCall Created 7 years, 9 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') | src/log.h » ('j') | 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 917 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 return ReferenceError("not_defined", name); 928 return ReferenceError("not_defined", name);
929 } 929 }
930 return *result; 930 return *result;
931 } 931 }
932 932
933 // Get the property. 933 // Get the property.
934 return object->GetProperty(*object, &lookup, *name, &attr); 934 return object->GetProperty(*object, &lookup, *name, &attr);
935 } 935 }
936 936
937 937
938 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
939 Handle<Map> new_receiver_map) {
940 ASSERT(!new_receiver_map.is_null());
941 for (int current = 0; current < receiver_maps->length(); ++current) {
942 if (!receiver_maps->at(current).is_null() &&
943 receiver_maps->at(current).is_identical_to(new_receiver_map)) {
944 return false;
945 }
946 }
947 receiver_maps->Add(new_receiver_map);
948 return true;
949 }
950
951
952 bool IC::UpdatePolymorphicIC(State state,
953 StrictModeFlag strict_mode,
954 Handle<JSObject> receiver,
955 Handle<String> name,
956 Handle<Code> code) {
957 if (code->type() == Code::NORMAL) return false;
958 if (target()->ic_state() == MONOMORPHIC &&
959 target()->type() == Code::NORMAL) {
960 return false;
961 }
962 MapHandleList receiver_maps;
963 CodeHandleList handlers;
964 target()->FindAllMaps(&receiver_maps);
965 int number_of_maps = receiver_maps.length();
966 if (number_of_maps == 0 || number_of_maps >= 4) return false;
967
968 target()->FindAllCode(&handlers, receiver_maps.length());
969
970 if (!AddOneReceiverMapIfMissing(&receiver_maps,
971 Handle<Map>(receiver->map()))) {
972 return false;
973 }
974
975 handlers.Add(code);
976 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
977 &receiver_maps, &handlers, name);
978 set_target(*ic);
979 return true;
980 }
981
982
983 void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
984 Handle<Code> handler,
985 Handle<String> name) {
986 if (handler->type() == Code::NORMAL) return set_target(*handler);
987 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
988 receiver, handler, name);
989 set_target(*ic);
990 }
991
992
993 void KeyedLoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
994 Handle<Code> handler,
995 Handle<String> name) {
996 if (handler->type() == Code::NORMAL) return set_target(*handler);
997 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedMonomorphicIC(
998 receiver, handler, name);
999 set_target(*ic);
1000 }
1001
1002
938 void IC::PatchCache(State state, 1003 void IC::PatchCache(State state,
939 StrictModeFlag strict_mode, 1004 StrictModeFlag strict_mode,
940 Handle<JSObject> receiver, 1005 Handle<JSObject> receiver,
941 Handle<String> name, 1006 Handle<String> name,
942 Handle<Code> code) { 1007 Handle<Code> code) {
943 switch (state) { 1008 switch (state) {
944 case UNINITIALIZED: 1009 case UNINITIALIZED:
945 case PREMONOMORPHIC: 1010 case PREMONOMORPHIC:
946 case MONOMORPHIC_PROTOTYPE_FAILURE: 1011 case MONOMORPHIC_PROTOTYPE_FAILURE:
947 set_target(*code); 1012 UpdateMonomorphicIC(receiver, code, name);
948 break; 1013 break;
949 case MONOMORPHIC: 1014 case MONOMORPHIC:
950 // Only move to megamorphic if the target changes. 1015 // Only move to megamorphic if the target changes.
951 if (target() != *code) { 1016 if (target() != *code) {
952 // We are transitioning from monomorphic to megamorphic case. 1017 if (target()->is_load_stub()) {
953 // Place the current monomorphic stub and stub compiled for 1018 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) {
954 // the receiver into stub cache. 1019 break;
1020 }
1021 }
1022 // We are transitioning from monomorphic to megamorphic case. Place the
1023 // stub compiled for the receiver into stub cache.
955 Map* map = target()->FindFirstMap(); 1024 Map* map = target()->FindFirstMap();
956 if (map != NULL) { 1025 if (map != NULL) {
957 UpdateMegamorphicCache(map, *name, target()); 1026 UpdateMegamorphicCache(map, *name, target());
958 } 1027 }
959 UpdateMegamorphicCache(receiver->map(), *name, *code); 1028 UpdateMegamorphicCache(receiver->map(), *name, *code);
960 set_target((strict_mode == kStrictMode) 1029 set_target((strict_mode == kStrictMode)
961 ? *megamorphic_stub_strict() 1030 ? *megamorphic_stub_strict()
962 : *megamorphic_stub()); 1031 : *megamorphic_stub());
963 } 1032 }
964 break; 1033 break;
965 case MEGAMORPHIC: 1034 case MEGAMORPHIC:
966 // Update the stub cache. 1035 // Update the stub cache.
967 UpdateMegamorphicCache(receiver->map(), *name, *code); 1036 UpdateMegamorphicCache(receiver->map(), *name, *code);
968 break; 1037 break;
969 case POLYMORPHIC: 1038 case POLYMORPHIC:
970 // When trying to patch a polymorphic stub with anything other than 1039 if (target()->is_load_stub()) {
971 // another polymorphic stub, go generic. 1040 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) {
972 // TODO(verwaest): Currently we always go generic since no polymorphic 1041 break;
973 // stubs enter this code path. Replace with proper updating once named 1042 }
974 // load/store can also be polymorphic. 1043 MapHandleList receiver_maps;
975 set_target((strict_mode == kStrictMode) 1044 CodeHandleList handlers;
976 ? *generic_stub_strict() 1045 target()->FindAllMaps(&receiver_maps);
977 : *generic_stub()); 1046 target()->FindAllCode(&handlers, receiver_maps.length());
1047 for (int i = 0; i < receiver_maps.length(); i++) {
1048 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
1049 }
1050 UpdateMegamorphicCache(receiver->map(), *name, *code);
1051 set_target(*megamorphic_stub());
1052 } else {
1053 // When trying to patch a polymorphic keyed load/store element stub
1054 // with anything other than another polymorphic stub, go generic.
1055 set_target((strict_mode == kStrictMode)
1056 ? *generic_stub_strict()
1057 : *generic_stub());
1058 }
978 break; 1059 break;
979 case DEBUG_STUB: 1060 case DEBUG_STUB:
980 break; 1061 break;
981 case GENERIC: 1062 case GENERIC:
982 UNREACHABLE(); 1063 UNREACHABLE();
983 break; 1064 break;
984 } 1065 }
985 } 1066 }
986 1067
987 1068
1069 static void GetReceiverMapsForStub(Handle<Code> stub,
1070 MapHandleList* result) {
1071 ASSERT(stub->is_inline_cache_stub());
1072 switch (stub->ic_state()) {
1073 case MONOMORPHIC: {
1074 Map* map = stub->FindFirstMap();
1075 if (map != NULL) {
1076 result->Add(Handle<Map>(map));
1077 }
1078 break;
1079 }
1080 case POLYMORPHIC: {
1081 AssertNoAllocation no_allocation;
1082 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1083 for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
1084 RelocInfo* info = it.rinfo();
1085 Handle<Object> object(info->target_object(), stub->GetIsolate());
1086 if (object->IsString()) break;
1087 ASSERT(object->IsMap());
1088 AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
1089 }
1090 break;
1091 }
1092 case MEGAMORPHIC:
1093 break;
1094 case UNINITIALIZED:
1095 case PREMONOMORPHIC:
1096 case MONOMORPHIC_PROTOTYPE_FAILURE:
1097 case GENERIC:
1098 case DEBUG_STUB:
1099 UNREACHABLE();
1100 break;
1101 }
1102 }
1103
1104
988 void LoadIC::UpdateCaches(LookupResult* lookup, 1105 void LoadIC::UpdateCaches(LookupResult* lookup,
989 State state, 1106 State state,
990 Handle<Object> object, 1107 Handle<Object> object,
991 Handle<String> name) { 1108 Handle<String> name) {
992 // Bail out if the result is not cacheable. 1109 // Bail out if the result is not cacheable.
993 if (!lookup->IsCacheable()) return; 1110 if (!lookup->IsCacheable()) return;
994 1111
995 // Loading properties from values is not common, so don't try to 1112 // Loading properties from values is not common, so don't try to
996 // deal with non-JS objects here. 1113 // deal with non-JS objects here.
997 if (!object->IsJSObject()) return; 1114 if (!object->IsJSObject()) return;
998 1115
999 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1116 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1000 Handle<Code> code; 1117 Handle<Code> code;
1001 if (state == UNINITIALIZED) { 1118 if (state == UNINITIALIZED) {
1002 // This is the first time we execute this inline cache. 1119 // This is the first time we execute this inline cache.
1003 // Set the target to the pre monomorphic stub to delay 1120 // Set the target to the pre monomorphic stub to delay
1004 // setting the monomorphic state. 1121 // setting the monomorphic state.
1005 code = pre_monomorphic_stub(); 1122 code = pre_monomorphic_stub();
1006 } else { 1123 } else {
1007 code = ComputeLoadMonomorphic(lookup, receiver, name); 1124 code = ComputeLoadHandler(lookup, receiver, name);
1008 if (code.is_null()) return; 1125 if (code.is_null()) return;
1009 } 1126 }
1010 1127
1011 PatchCache(state, kNonStrictMode, receiver, name, code); 1128 PatchCache(state, kNonStrictMode, receiver, name, code);
1012 TRACE_IC("LoadIC", name, state, target()); 1129 TRACE_IC("LoadIC", name, state, target());
1013 } 1130 }
1014 1131
1015 1132
1016 void IC::UpdateMegamorphicCache(Map* map, String* name, Code* code) { 1133 void IC::UpdateMegamorphicCache(Map* map, String* name, Code* code) {
1017 // Cache code holding map should be consistent with 1134 // Cache code holding map should be consistent with
1018 // GenerateMonomorphicCacheProbe. 1135 // GenerateMonomorphicCacheProbe.
1019 isolate()->stub_cache()->Set(name, map, code); 1136 isolate()->stub_cache()->Set(name, map, code);
1020 } 1137 }
1021 1138
1022 1139
1023 Handle<Code> LoadIC::ComputeLoadMonomorphic(LookupResult* lookup, 1140 Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
1024 Handle<JSObject> receiver, 1141 Handle<JSObject> receiver,
1025 Handle<String> name) { 1142 Handle<String> name) {
1026 if (!lookup->IsProperty()) { 1143 if (!lookup->IsProperty()) {
1027 // Nonexistent property. The result is undefined. 1144 // Nonexistent property. The result is undefined.
1028 return isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver); 1145 return isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
1029 } 1146 }
1030 1147
1031 // Compute monomorphic stub. 1148 // Compute monomorphic stub.
1032 Handle<JSObject> holder(lookup->holder()); 1149 Handle<JSObject> holder(lookup->holder());
1033 switch (lookup->type()) { 1150 switch (lookup->type()) {
1034 case FIELD: 1151 case FIELD:
1035 return isolate()->stub_cache()->ComputeLoadField( 1152 return isolate()->stub_cache()->ComputeLoadField(
1036 name, receiver, holder, lookup->GetFieldIndex()); 1153 name, receiver, holder, lookup->GetFieldIndex());
1037 case CONSTANT_FUNCTION: { 1154 case CONSTANT_FUNCTION: {
1038 Handle<JSFunction> constant(lookup->GetConstantFunction()); 1155 Handle<JSFunction> constant(lookup->GetConstantFunction());
1039 return isolate()->stub_cache()->ComputeLoadConstant( 1156 return isolate()->stub_cache()->ComputeLoadConstant(
1040 name, receiver, holder, constant); 1157 name, receiver, holder, constant);
1041 } 1158 }
1042 case NORMAL: 1159 case NORMAL:
1043 if (holder->IsGlobalObject()) { 1160 if (holder->IsGlobalObject()) {
1044 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); 1161 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1045 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); 1162 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
1046 return isolate()->stub_cache()->ComputeLoadGlobal( 1163 return isolate()->stub_cache()->ComputeLoadGlobal(
1047 name, receiver, global, cell, lookup->IsDontDelete()); 1164 name, receiver, global, cell, lookup->IsDontDelete());
1048 } 1165 }
1049 // There is only one shared stub for loading normalized 1166 // There is only one shared stub for loading normalized
1050 // properties. It does not traverse the prototype chain, so the 1167 // properties. It does not traverse the prototype chain, so the
1051 // property must be found in the receiver for the stub to be 1168 // property must be found in the receiver for the stub to be
1052 // applicable. 1169 // applicable.
1053 if (!holder.is_identical_to(receiver)) break; 1170 if (!holder.is_identical_to(receiver)) break;
1054 return isolate()->stub_cache()->ComputeLoadNormal(); 1171 return isolate()->stub_cache()->ComputeLoadNormal(name, receiver);
1055 case CALLBACKS: { 1172 case CALLBACKS: {
1056 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1173 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1057 if (callback->IsExecutableAccessorInfo()) { 1174 if (callback->IsExecutableAccessorInfo()) {
1058 Handle<ExecutableAccessorInfo> info = 1175 Handle<ExecutableAccessorInfo> info =
1059 Handle<ExecutableAccessorInfo>::cast(callback); 1176 Handle<ExecutableAccessorInfo>::cast(callback);
1060 if (v8::ToCData<Address>(info->getter()) == 0) break; 1177 if (v8::ToCData<Address>(info->getter()) == 0) break;
1061 if (!info->IsCompatibleReceiver(*receiver)) break; 1178 if (!info->IsCompatibleReceiver(*receiver)) break;
1062 return isolate()->stub_cache()->ComputeLoadCallback( 1179 return isolate()->stub_cache()->ComputeLoadCallback(
1063 name, receiver, holder, info); 1180 name, receiver, holder, info);
1064 } else if (callback->IsAccessorPair()) { 1181 } else if (callback->IsAccessorPair()) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 key = Handle<Smi>(Smi::FromInt(int_value), isolate); 1217 key = Handle<Smi>(Smi::FromInt(int_value), isolate);
1101 } 1218 }
1102 } 1219 }
1103 } else if (key->IsUndefined()) { 1220 } else if (key->IsUndefined()) {
1104 key = isolate->factory()->undefined_string(); 1221 key = isolate->factory()->undefined_string();
1105 } 1222 }
1106 return key; 1223 return key;
1107 } 1224 }
1108 1225
1109 1226
1110 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
1111 Handle<Map> new_receiver_map) {
1112 ASSERT(!new_receiver_map.is_null());
1113 for (int current = 0; current < receiver_maps->length(); ++current) {
1114 if (!receiver_maps->at(current).is_null() &&
1115 receiver_maps->at(current).is_identical_to(new_receiver_map)) {
1116 return false;
1117 }
1118 }
1119 receiver_maps->Add(new_receiver_map);
1120 return true;
1121 }
1122
1123
1124 static void GetReceiverMapsForStub(Handle<Code> stub,
1125 MapHandleList* result) {
1126 ASSERT(stub->is_inline_cache_stub());
1127 ASSERT(stub->is_keyed_load_stub() || stub->is_keyed_store_stub());
1128 switch (stub->ic_state()) {
1129 case MONOMORPHIC: {
1130 Map* map = stub->FindFirstMap();
1131 if (map != NULL) {
1132 result->Add(Handle<Map>(map));
1133 }
1134 break;
1135 }
1136 case POLYMORPHIC: {
1137 AssertNoAllocation no_allocation;
1138 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1139 for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
1140 RelocInfo* info = it.rinfo();
1141 Handle<Object> object(info->target_object(), stub->GetIsolate());
1142 ASSERT(object->IsMap());
1143 AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
1144 }
1145 break;
1146 }
1147 case MEGAMORPHIC:
1148 break;
1149 case UNINITIALIZED:
1150 case PREMONOMORPHIC:
1151 case MONOMORPHIC_PROTOTYPE_FAILURE:
1152 case GENERIC:
1153 case DEBUG_STUB:
1154 UNREACHABLE();
1155 break;
1156 }
1157 }
1158
1159
1160 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { 1227 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
1161 State ic_state = target()->ic_state(); 1228 State ic_state = target()->ic_state();
1162 1229
1163 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS 1230 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1164 // via megamorphic stubs, since they don't have a map in their relocation info 1231 // via megamorphic stubs, since they don't have a map in their relocation info
1165 // and so the stubs can't be harvested for the object needed for a map check. 1232 // and so the stubs can't be harvested for the object needed for a map check.
1166 if (target()->type() != Code::NORMAL) { 1233 if (target()->type() != Code::NORMAL) {
1167 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); 1234 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
1168 return generic_stub(); 1235 return generic_stub();
1169 } 1236 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 ASSERT(!stub.is_null()); 1328 ASSERT(!stub.is_null());
1262 set_target(*stub); 1329 set_target(*stub);
1263 TRACE_IC("KeyedLoadIC", key, state, target()); 1330 TRACE_IC("KeyedLoadIC", key, state, target());
1264 } 1331 }
1265 1332
1266 1333
1267 return Runtime::GetObjectProperty(isolate(), object, key); 1334 return Runtime::GetObjectProperty(isolate(), object, key);
1268 } 1335 }
1269 1336
1270 1337
1271 Handle<Code> KeyedLoadIC::ComputeLoadMonomorphic(LookupResult* lookup, 1338 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
1272 Handle<JSObject> receiver, 1339 Handle<JSObject> receiver,
1273 Handle<String> name) { 1340 Handle<String> name) {
1274 // Bail out if we didn't find a result. 1341 // Bail out if we didn't find a result.
1275 if (!lookup->IsProperty()) return Handle<Code>::null(); 1342 if (!lookup->IsProperty()) return Handle<Code>::null();
1276 1343
1277 // Compute a monomorphic stub. 1344 // Compute a monomorphic stub.
1278 Handle<JSObject> holder(lookup->holder()); 1345 Handle<JSObject> holder(lookup->holder());
1279 switch (lookup->type()) { 1346 switch (lookup->type()) {
1280 case FIELD: 1347 case FIELD:
1281 return isolate()->stub_cache()->ComputeKeyedLoadField( 1348 return isolate()->stub_cache()->ComputeKeyedLoadField(
1282 name, receiver, holder, lookup->GetFieldIndex()); 1349 name, receiver, holder, lookup->GetFieldIndex());
1283 case CONSTANT_FUNCTION: { 1350 case CONSTANT_FUNCTION: {
(...skipping 1291 matching lines...) Expand 10 before | Expand all | Expand 10 after
2575 #undef ADDR 2642 #undef ADDR
2576 }; 2643 };
2577 2644
2578 2645
2579 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2646 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2580 return IC_utilities[id]; 2647 return IC_utilities[id];
2581 } 2648 }
2582 2649
2583 2650
2584 } } // namespace v8::internal 2651 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698