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

Side by Side Diff: src/ic.cc

Issue 62953007: Handle all object types (minus smi) in load/store ICs (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed commentsx Created 7 years, 1 month 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/ic-inl.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 987 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 set_target(*ic); 998 set_target(*ic);
999 return true; 999 return true;
1000 } 1000 }
1001 1001
1002 1002
1003 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver, 1003 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1004 Handle<Code> handler, 1004 Handle<Code> handler,
1005 Handle<String> name) { 1005 Handle<String> name) {
1006 if (!handler->is_handler()) return set_target(*handler); 1006 if (!handler->is_handler()) return set_target(*handler);
1007 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( 1007 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
1008 receiver, handler, name, strict_mode()); 1008 name, receiver, handler, strict_mode());
1009 set_target(*ic); 1009 set_target(*ic);
1010 } 1010 }
1011 1011
1012 1012
1013 void IC::CopyICToMegamorphicCache(Handle<String> name) { 1013 void IC::CopyICToMegamorphicCache(Handle<String> name) {
1014 MapHandleList receiver_maps; 1014 MapHandleList receiver_maps;
1015 CodeHandleList handlers; 1015 CodeHandleList handlers;
1016 target()->FindAllMaps(&receiver_maps); 1016 target()->FindAllMaps(&receiver_maps);
1017 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return; 1017 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return;
1018 for (int i = 0; i < receiver_maps.length(); i++) { 1018 for (int i = 0; i < receiver_maps.length(); i++) {
1019 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); 1019 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
1020 } 1020 }
1021 } 1021 }
1022 1022
1023 1023
1024 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { 1024 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) {
1025 Map* current_map = target()->FindFirstMap(); 1025 Map* current_map = target()->FindFirstMap();
1026 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); 1026 ElementsKind receiver_elements_kind = receiver_map->elements_kind();
1027 bool more_general_transition = 1027 bool more_general_transition =
1028 IsMoreGeneralElementsKindTransition( 1028 IsMoreGeneralElementsKindTransition(
1029 current_map->elements_kind(), receiver_elements_kind); 1029 current_map->elements_kind(), receiver_elements_kind);
1030 Map* transitioned_map = more_general_transition 1030 Map* transitioned_map = more_general_transition
1031 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) 1031 ? current_map->LookupElementsTransitionMap(receiver_elements_kind)
1032 : NULL; 1032 : NULL;
1033 1033
1034 return transitioned_map == receiver_map; 1034 return transitioned_map == receiver_map;
1035 } 1035 }
1036 1036
1037 1037
1038 void IC::PatchCache(Handle<HeapObject> receiver, 1038 void IC::PatchCache(Handle<Object> object,
1039 Handle<String> name, 1039 Handle<String> name,
1040 Handle<Code> code) { 1040 Handle<Code> code) {
1041 // TODO(verwaest): Handle smi here as well.
1042 if (!object->IsHeapObject()) return;
1043
1044 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
1041 switch (state()) { 1045 switch (state()) {
1042 case UNINITIALIZED: 1046 case UNINITIALIZED:
1043 case PREMONOMORPHIC: 1047 case PREMONOMORPHIC:
1044 case MONOMORPHIC_PROTOTYPE_FAILURE: 1048 case MONOMORPHIC_PROTOTYPE_FAILURE:
1045 UpdateMonomorphicIC(receiver, code, name); 1049 UpdateMonomorphicIC(receiver, code, name);
1046 break; 1050 break;
1047 case MONOMORPHIC: 1051 case MONOMORPHIC:
1048 // For now, call stubs are allowed to rewrite to the same stub. This 1052 // For now, call stubs are allowed to rewrite to the same stub. This
1049 // happens e.g., when the field does not contain a function. 1053 // happens e.g., when the field does not contain a function.
1050 ASSERT(target()->is_call_stub() || 1054 ASSERT(target()->is_call_stub() ||
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 } else { 1094 } else {
1091 KeyedLoadFieldStub stub(inobject, offset, representation); 1095 KeyedLoadFieldStub stub(inobject, offset, representation);
1092 return stub.GetCode(isolate()); 1096 return stub.GetCode(isolate());
1093 } 1097 }
1094 } 1098 }
1095 1099
1096 1100
1097 void LoadIC::UpdateCaches(LookupResult* lookup, 1101 void LoadIC::UpdateCaches(LookupResult* lookup,
1098 Handle<Object> object, 1102 Handle<Object> object,
1099 Handle<String> name) { 1103 Handle<String> name) {
1100 // TODO(verwaest): It would be nice to support loading fields from smis as
1101 // well. For now just fail to update the cache.
1102 if (!object->IsHeapObject()) return;
1103
1104 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
1105
1106 Handle<Code> code;
1107 if (state() == UNINITIALIZED) { 1104 if (state() == UNINITIALIZED) {
1108 // This is the first time we execute this inline cache. 1105 // This is the first time we execute this inline cache.
1109 // Set the target to the pre monomorphic stub to delay 1106 // Set the target to the pre monomorphic stub to delay
1110 // setting the monomorphic state. 1107 // setting the monomorphic state.
1111 set_target(*pre_monomorphic_stub()); 1108 set_target(*pre_monomorphic_stub());
1112 TRACE_IC("LoadIC", name); 1109 TRACE_IC("LoadIC", name);
1113 return; 1110 return;
1114 } else if (!lookup->IsCacheable()) { 1111 }
1112
1113 Handle<Code> code;
1114 if (!lookup->IsCacheable()) {
1115 // Bail out if the result is not cacheable. 1115 // Bail out if the result is not cacheable.
1116 code = slow_stub(); 1116 code = slow_stub();
1117 } else if (object->IsString() &&
1118 name->Equals(isolate()->heap()->length_string())) {
1119 int length_index = String::kLengthOffset / kPointerSize;
1120 code = SimpleFieldLoad(length_index);
1121 } else if (!object->IsJSObject()) {
1122 // TODO(jkummerow): It would be nice to support non-JSObjects in
1123 // ComputeLoadHandler, then we wouldn't need to go generic here.
1124 code = slow_stub();
1125 } else if (!lookup->IsProperty()) { 1117 } else if (!lookup->IsProperty()) {
1126 code = kind() == Code::LOAD_IC 1118 if (kind() == Code::LOAD_IC) {
1127 ? isolate()->stub_cache()->ComputeLoadNonexistent( 1119 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object);
1128 name, Handle<JSObject>::cast(receiver)) 1120 } else {
1129 : slow_stub(); 1121 code = slow_stub();
1122 }
1130 } else { 1123 } else {
1131 code = ComputeHandler(lookup, Handle<JSObject>::cast(receiver), name); 1124 code = ComputeHandler(lookup, object, name);
1132 } 1125 }
1133 1126
1134 PatchCache(receiver, name, code); 1127 PatchCache(object, name, code);
1135 TRACE_IC("LoadIC", name); 1128 TRACE_IC("LoadIC", name);
1136 } 1129 }
1137 1130
1138 1131
1139 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { 1132 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
1140 // Cache code holding map should be consistent with 1133 // Cache code holding map should be consistent with
1141 // GenerateMonomorphicCacheProbe. 1134 // GenerateMonomorphicCacheProbe.
1142 isolate()->stub_cache()->Set(name, map, code); 1135 isolate()->stub_cache()->Set(name, map, code);
1143 } 1136 }
1144 1137
1145 1138
1146 Handle<Code> IC::ComputeHandler(LookupResult* lookup, 1139 Handle<Code> IC::ComputeHandler(LookupResult* lookup,
1147 Handle<JSObject> receiver, 1140 Handle<Object> object,
1148 Handle<String> name, 1141 Handle<String> name,
1149 Handle<Object> value) { 1142 Handle<Object> value) {
1143 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object);
1144 Handle<HeapObject> stub_holder(GetCodeCacheHolder(
1145 isolate(), *object, cache_holder));
1146
1150 Handle<Code> code = isolate()->stub_cache()->FindHandler( 1147 Handle<Code> code = isolate()->stub_cache()->FindHandler(
1151 name, receiver, kind()); 1148 name, stub_holder, kind(), cache_holder, strict_mode());
1152 if (!code.is_null()) return code; 1149 if (!code.is_null()) return code;
1153 1150
1154 code = CompileHandler(lookup, receiver, name, value); 1151 code = CompileHandler(lookup, object, name, value, cache_holder);
1155 ASSERT(code->is_handler()); 1152 ASSERT(code->is_handler());
1156 1153
1157 if (code->type() != Code::NORMAL) { 1154 if (code->type() != Code::NORMAL) {
1158 HeapObject::UpdateMapCodeCache(receiver, name, code); 1155 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
1159 } 1156 }
1160 1157
1161 return code; 1158 return code;
1162 } 1159 }
1163 1160
1164 1161
1165 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, 1162 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
1166 Handle<JSObject> receiver, 1163 Handle<Object> object,
1167 Handle<String> name, 1164 Handle<String> name,
1168 Handle<Object> unused) { 1165 Handle<Object> unused,
1166 InlineCacheHolderFlag cache_holder) {
1167 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
1168 int length_index = String::kLengthOffset / kPointerSize;
1169 return SimpleFieldLoad(length_index);
1170 }
1171
1169 Handle<JSObject> holder(lookup->holder()); 1172 Handle<JSObject> holder(lookup->holder());
1170 LoadStubCompiler compiler(isolate(), kind()); 1173 LoadStubCompiler compiler(isolate(), cache_holder, kind());
1171 1174
1172 switch (lookup->type()) { 1175 switch (lookup->type()) {
1173 case FIELD: { 1176 case FIELD: {
1174 PropertyIndex field = lookup->GetFieldIndex(); 1177 PropertyIndex field = lookup->GetFieldIndex();
1175 if (receiver.is_identical_to(holder)) { 1178 if (object.is_identical_to(holder)) {
1176 return SimpleFieldLoad(field.translate(holder), 1179 return SimpleFieldLoad(field.translate(holder),
1177 field.is_inobject(holder), 1180 field.is_inobject(holder),
1178 lookup->representation()); 1181 lookup->representation());
1179 } 1182 }
1180 return compiler.CompileLoadField( 1183 return compiler.CompileLoadField(
1181 receiver, holder, name, field, lookup->representation()); 1184 object, holder, name, field, lookup->representation());
1182 } 1185 }
1183 case CONSTANT: { 1186 case CONSTANT: {
1184 Handle<Object> constant(lookup->GetConstant(), isolate()); 1187 Handle<Object> constant(lookup->GetConstant(), isolate());
1185 // TODO(2803): Don't compute a stub for cons strings because they cannot 1188 // TODO(2803): Don't compute a stub for cons strings because they cannot
1186 // be embedded into code. 1189 // be embedded into code.
1187 if (constant->IsConsString()) break; 1190 if (constant->IsConsString()) break;
1188 return compiler.CompileLoadConstant(receiver, holder, name, constant); 1191 return compiler.CompileLoadConstant(object, holder, name, constant);
1189 } 1192 }
1190 case NORMAL: 1193 case NORMAL:
1191 if (kind() != Code::LOAD_IC) break; 1194 if (kind() != Code::LOAD_IC) break;
1192 if (holder->IsGlobalObject()) { 1195 if (holder->IsGlobalObject()) {
1193 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); 1196 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1194 Handle<PropertyCell> cell( 1197 Handle<PropertyCell> cell(
1195 global->GetPropertyCell(lookup), isolate()); 1198 global->GetPropertyCell(lookup), isolate());
1196 Handle<Code> code = compiler.CompileLoadGlobal( 1199 Handle<Code> code = compiler.CompileLoadGlobal(
1197 receiver, global, cell, name, lookup->IsDontDelete()); 1200 object, global, cell, name, lookup->IsDontDelete());
1198 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. 1201 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1199 HeapObject::UpdateMapCodeCache(receiver, name, code); 1202 Handle<HeapObject> stub_holder(GetCodeCacheHolder(
1203 isolate(), *object, cache_holder));
1204 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
1200 return code; 1205 return code;
1201 } 1206 }
1202 // There is only one shared stub for loading normalized 1207 // There is only one shared stub for loading normalized
1203 // properties. It does not traverse the prototype chain, so the 1208 // properties. It does not traverse the prototype chain, so the
1204 // property must be found in the receiver for the stub to be 1209 // property must be found in the object for the stub to be
1205 // applicable. 1210 // applicable.
1206 if (!holder.is_identical_to(receiver)) break; 1211 if (!object.is_identical_to(holder)) break;
1207 return isolate()->builtins()->LoadIC_Normal(); 1212 return isolate()->builtins()->LoadIC_Normal();
1208 case CALLBACKS: { 1213 case CALLBACKS: {
1209 // Use simple field loads for some well-known callback properties. 1214 // Use simple field loads for some well-known callback properties.
1210 int object_offset; 1215 int object_offset;
1211 Handle<Map> map(receiver->map()); 1216 if (object->IsJSObject()) {
1212 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { 1217 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1213 PropertyIndex index = 1218 Handle<Map> map(receiver->map());
1214 PropertyIndex::NewHeaderIndex(object_offset / kPointerSize); 1219 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
1215 return compiler.CompileLoadField( 1220 PropertyIndex index =
1216 receiver, receiver, name, index, Representation::Tagged()); 1221 PropertyIndex::NewHeaderIndex(object_offset / kPointerSize);
1222 return compiler.CompileLoadField(
1223 receiver, receiver, name, index, Representation::Tagged());
1224 }
1217 } 1225 }
1218 1226
1219 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1227 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1220 if (callback->IsExecutableAccessorInfo()) { 1228 if (callback->IsExecutableAccessorInfo()) {
1221 Handle<ExecutableAccessorInfo> info = 1229 Handle<ExecutableAccessorInfo> info =
1222 Handle<ExecutableAccessorInfo>::cast(callback); 1230 Handle<ExecutableAccessorInfo>::cast(callback);
1223 if (v8::ToCData<Address>(info->getter()) == 0) break; 1231 if (v8::ToCData<Address>(info->getter()) == 0) break;
1224 if (!info->IsCompatibleReceiver(*receiver)) break; 1232 if (!info->IsCompatibleReceiver(*object)) break;
1225 return compiler.CompileLoadCallback(receiver, holder, name, info); 1233 return compiler.CompileLoadCallback(object, holder, name, info);
1226 } else if (callback->IsAccessorPair()) { 1234 } else if (callback->IsAccessorPair()) {
1227 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), 1235 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
1228 isolate()); 1236 isolate());
1229 if (!getter->IsJSFunction()) break; 1237 if (!getter->IsJSFunction()) break;
1230 if (holder->IsGlobalObject()) break; 1238 if (holder->IsGlobalObject()) break;
1231 if (!holder->HasFastProperties()) break; 1239 if (!holder->HasFastProperties()) break;
1232 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); 1240 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1241 if (!object->IsJSObject() &&
1242 !function->IsBuiltin() &&
1243 function->shared()->is_classic_mode()) {
1244 // Calling non-strict non-builtins with a value as the receiver
1245 // requires boxing.
1246 break;
1247 }
1233 CallOptimization call_optimization(function); 1248 CallOptimization call_optimization(function);
1234 if (call_optimization.is_simple_api_call() && 1249 if (call_optimization.is_simple_api_call() &&
1235 call_optimization.IsCompatibleReceiver(*receiver)) { 1250 call_optimization.IsCompatibleReceiver(*object)) {
1236 return compiler.CompileLoadCallback( 1251 return compiler.CompileLoadCallback(
1237 receiver, holder, name, call_optimization); 1252 object, holder, name, call_optimization);
1238 } 1253 }
1239 return compiler.CompileLoadViaGetter(receiver, holder, name, function); 1254 return compiler.CompileLoadViaGetter(object, holder, name, function);
1240 } 1255 }
1241 // TODO(dcarney): Handle correctly. 1256 // TODO(dcarney): Handle correctly.
1242 if (callback->IsDeclaredAccessorInfo()) break; 1257 if (callback->IsDeclaredAccessorInfo()) break;
1243 ASSERT(callback->IsForeign()); 1258 ASSERT(callback->IsForeign());
1244 // No IC support for old-style native accessors. 1259 // No IC support for old-style native accessors.
1245 break; 1260 break;
1246 } 1261 }
1247 case INTERCEPTOR: 1262 case INTERCEPTOR:
1248 ASSERT(HasInterceptorGetter(*holder)); 1263 ASSERT(HasInterceptorGetter(*holder));
1249 return compiler.CompileLoadInterceptor(receiver, holder, name); 1264 return compiler.CompileLoadInterceptor(object, holder, name);
1250 default: 1265 default:
1251 break; 1266 break;
1252 } 1267 }
1253 1268
1254 return slow_stub(); 1269 return slow_stub();
1255 } 1270 }
1256 1271
1257 1272
1258 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { 1273 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1259 // This helper implements a few common fast cases for converting 1274 // This helper implements a few common fast cases for converting
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1575 ASSERT(!lookup->IsHandler()); 1590 ASSERT(!lookup->IsHandler());
1576 1591
1577 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); 1592 Handle<Code> code = ComputeHandler(lookup, receiver, name, value);
1578 1593
1579 PatchCache(receiver, name, code); 1594 PatchCache(receiver, name, code);
1580 TRACE_IC("StoreIC", name); 1595 TRACE_IC("StoreIC", name);
1581 } 1596 }
1582 1597
1583 1598
1584 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, 1599 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
1585 Handle<JSObject> receiver, 1600 Handle<Object> object,
1586 Handle<String> name, 1601 Handle<String> name,
1587 Handle<Object> value) { 1602 Handle<Object> value,
1603 InlineCacheHolderFlag cache_holder) {
1604 ASSERT(cache_holder == OWN_MAP);
1605 // This is currently guaranteed by checks in StoreIC::Store.
1606 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1607
1588 Handle<JSObject> holder(lookup->holder()); 1608 Handle<JSObject> holder(lookup->holder());
1589 StoreStubCompiler compiler(isolate(), strict_mode(), kind()); 1609 StoreStubCompiler compiler(isolate(), strict_mode(), kind());
1590 switch (lookup->type()) { 1610 switch (lookup->type()) {
1591 case FIELD: 1611 case FIELD:
1592 return compiler.CompileStoreField(receiver, lookup, name); 1612 return compiler.CompileStoreField(receiver, lookup, name);
1593 case TRANSITION: { 1613 case TRANSITION: {
1594 // Explicitly pass in the receiver map since LookupForWrite may have 1614 // Explicitly pass in the receiver map since LookupForWrite may have
1595 // stored something else than the receiver in the holder. 1615 // stored something else than the receiver in the holder.
1596 Handle<Map> transition( 1616 Handle<Map> transition(
1597 lookup->GetTransitionTarget(receiver->map()), isolate()); 1617 lookup->GetTransitionTarget(receiver->map()), isolate());
(...skipping 1132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2730 #undef ADDR 2750 #undef ADDR
2731 }; 2751 };
2732 2752
2733 2753
2734 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2754 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2735 return IC_utilities[id]; 2755 return IC_utilities[id];
2736 } 2756 }
2737 2757
2738 2758
2739 } } // namespace v8::internal 2759 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698