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

Side by Side Diff: src/ic.cc

Issue 71163006: Merge bleeding_edge r17376:17693. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Fix all.gyp 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/ia32/stub-cache-ia32.cc ('k') | src/incremental-marking.cc » ('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 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 break; 263 break;
264 default: 264 default:
265 return false; 265 return false;
266 } 266 }
267 return false; 267 return false;
268 } 268 }
269 269
270 270
271 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, 271 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
272 Handle<String> name) { 272 Handle<String> name) {
273 DisallowHeapAllocation no_gc;
274
275 if (target()->is_call_stub()) { 273 if (target()->is_call_stub()) {
276 LookupResult lookup(isolate()); 274 LookupResult lookup(isolate());
277 LookupForRead(receiver, name, &lookup); 275 LookupForRead(receiver, name, &lookup);
278 if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) { 276 if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) {
279 return true; 277 return true;
280 } 278 }
281 } 279 }
282 280
283 if (target()->is_keyed_stub()) { 281 if (target()->is_keyed_stub()) {
284 // Determine whether the failure is due to a name failure. 282 // Determine whether the failure is due to a name failure.
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 target()->arguments_count(), kind_, extra_ic_state()); 759 target()->arguments_count(), kind_, extra_ic_state());
762 } 760 }
763 761
764 762
765 void CallICBase::UpdateCaches(LookupResult* lookup, 763 void CallICBase::UpdateCaches(LookupResult* lookup,
766 Handle<Object> object, 764 Handle<Object> object,
767 Handle<String> name) { 765 Handle<String> name) {
768 // Bail out if we didn't find a result. 766 // Bail out if we didn't find a result.
769 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 767 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
770 768
771 // Compute the number of arguments. 769 if (state() == UNINITIALIZED) {
772 Handle<Code> code; 770 set_target(*pre_monomorphic_stub());
773 code = state() == UNINITIALIZED 771 TRACE_IC("CallIC", name);
774 ? pre_monomorphic_stub() 772 return;
775 : ComputeMonomorphicStub(lookup, object, name); 773 }
776 774
775 Handle<Code> code = ComputeMonomorphicStub(lookup, object, name);
777 // If there's no appropriate stub we simply avoid updating the caches. 776 // If there's no appropriate stub we simply avoid updating the caches.
778 // TODO(verwaest): Install a slow fallback in this case to avoid not learning, 777 // TODO(verwaest): Install a slow fallback in this case to avoid not learning,
779 // and deopting Crankshaft code. 778 // and deopting Crankshaft code.
780 if (code.is_null()) return; 779 if (code.is_null()) return;
781 780
782 Handle<JSObject> cache_object = object->IsJSObject() 781 Handle<JSObject> cache_object = object->IsJSObject()
783 ? Handle<JSObject>::cast(object) 782 ? Handle<JSObject>::cast(object)
784 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), 783 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
785 isolate()); 784 isolate());
786 785
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 } 946 }
948 receiver_maps->Add(new_receiver_map); 947 receiver_maps->Add(new_receiver_map);
949 return true; 948 return true;
950 } 949 }
951 950
952 951
953 bool IC::UpdatePolymorphicIC(Handle<HeapObject> receiver, 952 bool IC::UpdatePolymorphicIC(Handle<HeapObject> receiver,
954 Handle<String> name, 953 Handle<String> name,
955 Handle<Code> code) { 954 Handle<Code> code) {
956 if (!code->is_handler()) return false; 955 if (!code->is_handler()) return false;
957
958 MapHandleList receiver_maps; 956 MapHandleList receiver_maps;
959 CodeHandleList handlers; 957 CodeHandleList handlers;
960 958
961 int number_of_valid_maps; 959 int number_of_valid_maps;
962 int handler_to_overwrite = -1; 960 int handler_to_overwrite = -1;
963 Handle<Map> new_receiver_map(receiver->map()); 961 Handle<Map> new_receiver_map(receiver->map());
964 {
965 DisallowHeapAllocation no_gc;
966 target()->FindAllMaps(&receiver_maps);
967 int number_of_maps = receiver_maps.length();
968 number_of_valid_maps = number_of_maps;
969 962
970 for (int i = 0; i < number_of_maps; i++) { 963 target()->FindAllMaps(&receiver_maps);
971 Handle<Map> map = receiver_maps.at(i); 964 int number_of_maps = receiver_maps.length();
972 // Filter out deprecated maps to ensure its instances get migrated. 965 number_of_valid_maps = number_of_maps;
973 if (map->is_deprecated()) {
974 number_of_valid_maps--;
975 // If the receiver map is already in the polymorphic IC, this indicates
976 // there was a prototoype chain failure. In that case, just overwrite the
977 // handler.
978 } else if (map.is_identical_to(new_receiver_map)) {
979 number_of_valid_maps--;
980 handler_to_overwrite = i;
981 }
982 }
983 966
984 if (number_of_valid_maps >= 4) return false; 967 for (int i = 0; i < number_of_maps; i++) {
985 if (number_of_maps == 0) return false; 968 Handle<Map> map = receiver_maps.at(i);
986 969 // Filter out deprecated maps to ensure its instances get migrated.
987 if (!target()->FindHandlers(&handlers, receiver_maps.length())) { 970 if (map->is_deprecated()) {
988 return false; 971 number_of_valid_maps--;
972 // If the receiver map is already in the polymorphic IC, this indicates
973 // there was a prototoype chain failure. In that case, just overwrite the
974 // handler.
975 } else if (map.is_identical_to(new_receiver_map)) {
976 number_of_valid_maps--;
977 handler_to_overwrite = i;
989 } 978 }
990 } 979 }
991 980
981 if (number_of_valid_maps >= 4) return false;
982 if (number_of_maps == 0) return false;
983
984 if (!target()->FindHandlers(&handlers, receiver_maps.length())) {
985 return false;
986 }
987
992 number_of_valid_maps++; 988 number_of_valid_maps++;
993 if (handler_to_overwrite >= 0) { 989 if (handler_to_overwrite >= 0) {
994 handlers.Set(handler_to_overwrite, code); 990 handlers.Set(handler_to_overwrite, code);
995 } else { 991 } else {
996 receiver_maps.Add(new_receiver_map); 992 receiver_maps.Add(new_receiver_map);
997 handlers.Add(code); 993 handlers.Add(code);
998 } 994 }
999 995
1000 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( 996 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
1001 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode()); 997 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode());
1002 set_target(*ic); 998 set_target(*ic);
1003 return true; 999 return true;
1004 } 1000 }
1005 1001
1006 1002
1007 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver, 1003 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1008 Handle<Code> handler, 1004 Handle<Code> handler,
1009 Handle<String> name) { 1005 Handle<String> name) {
1010 if (!handler->is_handler()) return set_target(*handler); 1006 if (!handler->is_handler()) return set_target(*handler);
1011 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( 1007 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
1012 receiver, handler, name, strict_mode()); 1008 receiver, handler, name, strict_mode());
1013 set_target(*ic); 1009 set_target(*ic);
1014 } 1010 }
1015 1011
1016 1012
1017 void IC::CopyICToMegamorphicCache(Handle<String> name) { 1013 void IC::CopyICToMegamorphicCache(Handle<String> name) {
1018 MapHandleList receiver_maps; 1014 MapHandleList receiver_maps;
1019 CodeHandleList handlers; 1015 CodeHandleList handlers;
1020 { 1016 target()->FindAllMaps(&receiver_maps);
1021 DisallowHeapAllocation no_gc; 1017 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return;
1022 target()->FindAllMaps(&receiver_maps);
1023 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return;
1024 }
1025 for (int i = 0; i < receiver_maps.length(); i++) { 1018 for (int i = 0; i < receiver_maps.length(); i++) {
1026 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); 1019 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
1027 } 1020 }
1028 } 1021 }
1029 1022
1030 1023
1031 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { 1024 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) {
1032 DisallowHeapAllocation no_allocation;
1033
1034 Map* current_map = target()->FindFirstMap(); 1025 Map* current_map = target()->FindFirstMap();
1035 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); 1026 ElementsKind receiver_elements_kind = receiver_map->elements_kind();
1036 bool more_general_transition = 1027 bool more_general_transition =
1037 IsMoreGeneralElementsKindTransition( 1028 IsMoreGeneralElementsKindTransition(
1038 current_map->elements_kind(), receiver_elements_kind); 1029 current_map->elements_kind(), receiver_elements_kind);
1039 Map* transitioned_map = more_general_transition 1030 Map* transitioned_map = more_general_transition
1040 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) 1031 ? current_map->LookupElementsTransitionMap(receiver_elements_kind)
1041 : NULL; 1032 : NULL;
1042 1033
1043 return transitioned_map == receiver_map; 1034 return transitioned_map == receiver_map;
(...skipping 10 matching lines...) Expand all
1054 UpdateMonomorphicIC(receiver, code, name); 1045 UpdateMonomorphicIC(receiver, code, name);
1055 break; 1046 break;
1056 case MONOMORPHIC: 1047 case MONOMORPHIC:
1057 // For now, call stubs are allowed to rewrite to the same stub. This 1048 // For now, call stubs are allowed to rewrite to the same stub. This
1058 // happens e.g., when the field does not contain a function. 1049 // happens e.g., when the field does not contain a function.
1059 ASSERT(target()->is_call_stub() || 1050 ASSERT(target()->is_call_stub() ||
1060 target()->is_keyed_call_stub() || 1051 target()->is_keyed_call_stub() ||
1061 !target().is_identical_to(code)); 1052 !target().is_identical_to(code));
1062 if (!target()->is_keyed_stub()) { 1053 if (!target()->is_keyed_stub()) {
1063 bool is_same_handler = false; 1054 bool is_same_handler = false;
1064 { 1055 Code* old_handler = target()->FindFirstHandler();
1065 DisallowHeapAllocation no_allocation; 1056 is_same_handler = old_handler == *code;
1066 Code* old_handler = target()->FindFirstHandler(); 1057
1067 is_same_handler = old_handler == *code; 1058 if (is_same_handler &&
1068 } 1059 IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
1069 if (is_same_handler
1070 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
1071 UpdateMonomorphicIC(receiver, code, name); 1060 UpdateMonomorphicIC(receiver, code, name);
1072 break; 1061 break;
1073 } 1062 }
1074 if (UpdatePolymorphicIC(receiver, name, code)) { 1063 }
1075 break; 1064 // Fall through.
1076 } 1065 case POLYMORPHIC:
1077 1066 if (!target()->is_keyed_stub()) {
1067 if (UpdatePolymorphicIC(receiver, name, code)) break;
1078 CopyICToMegamorphicCache(name); 1068 CopyICToMegamorphicCache(name);
1079 } 1069 }
1080
1081 UpdateMegamorphicCache(receiver->map(), *name, *code);
1082 set_target(*megamorphic_stub()); 1070 set_target(*megamorphic_stub());
1083 break; 1071 // Fall through.
1084 case MEGAMORPHIC: 1072 case MEGAMORPHIC:
1085 UpdateMegamorphicCache(receiver->map(), *name, *code); 1073 UpdateMegamorphicCache(receiver->map(), *name, *code);
1086 break; 1074 break;
1087 case POLYMORPHIC:
1088 if (target()->is_keyed_stub()) {
1089 // When trying to patch a polymorphic keyed stub with anything other
1090 // than another polymorphic stub, go generic.
1091 set_target(*generic_stub());
1092 } else {
1093 if (UpdatePolymorphicIC(receiver, name, code)) {
1094 break;
1095 }
1096 CopyICToMegamorphicCache(name);
1097 UpdateMegamorphicCache(receiver->map(), *name, *code);
1098 set_target(*megamorphic_stub());
1099 }
1100 break;
1101 case DEBUG_STUB: 1075 case DEBUG_STUB:
1102 break; 1076 break;
1103 case GENERIC: 1077 case GENERIC:
1104 UNREACHABLE(); 1078 UNREACHABLE();
1105 break; 1079 break;
1106 } 1080 }
1107 } 1081 }
1108 1082
1109 1083
1110 Handle<Code> LoadIC::SimpleFieldLoad(int offset, 1084 Handle<Code> LoadIC::SimpleFieldLoad(int offset,
1111 bool inobject, 1085 bool inobject,
1112 Representation representation) { 1086 Representation representation) {
1113 if (kind() == Code::LOAD_IC) { 1087 if (kind() == Code::LOAD_IC) {
1114 LoadFieldStub stub(inobject, offset, representation); 1088 LoadFieldStub stub(inobject, offset, representation);
1115 return stub.GetCode(isolate()); 1089 return stub.GetCode(isolate());
1116 } else { 1090 } else {
1117 KeyedLoadFieldStub stub(inobject, offset, representation); 1091 KeyedLoadFieldStub stub(inobject, offset, representation);
1118 return stub.GetCode(isolate()); 1092 return stub.GetCode(isolate());
1119 } 1093 }
1120 } 1094 }
1121 1095
1096
1122 void LoadIC::UpdateCaches(LookupResult* lookup, 1097 void LoadIC::UpdateCaches(LookupResult* lookup,
1123 Handle<Object> object, 1098 Handle<Object> object,
1124 Handle<String> name) { 1099 Handle<String> name) {
1125 // TODO(verwaest): It would be nice to support loading fields from smis as 1100 // TODO(verwaest): It would be nice to support loading fields from smis as
1126 // well. For now just fail to update the cache. 1101 // well. For now just fail to update the cache.
1127 if (!object->IsHeapObject()) return; 1102 if (!object->IsHeapObject()) return;
1128 1103
1129 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); 1104 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
1130 1105
1131 Handle<Code> code; 1106 Handle<Code> code;
1132 if (state() == UNINITIALIZED) { 1107 if (state() == UNINITIALIZED) {
1133 // This is the first time we execute this inline cache. 1108 // This is the first time we execute this inline cache.
1134 // Set the target to the pre monomorphic stub to delay 1109 // Set the target to the pre monomorphic stub to delay
1135 // setting the monomorphic state. 1110 // setting the monomorphic state.
1136 code = pre_monomorphic_stub(); 1111 set_target(*pre_monomorphic_stub());
1112 TRACE_IC("LoadIC", name);
1113 return;
1137 } else if (!lookup->IsCacheable()) { 1114 } else if (!lookup->IsCacheable()) {
1138 // Bail out if the result is not cacheable. 1115 // Bail out if the result is not cacheable.
1139 code = slow_stub(); 1116 code = slow_stub();
1140 } else if (object->IsString() && 1117 } else if (object->IsString() &&
1141 name->Equals(isolate()->heap()->length_string())) { 1118 name->Equals(isolate()->heap()->length_string())) {
1142 int length_index = String::kLengthOffset / kPointerSize; 1119 int length_index = String::kLengthOffset / kPointerSize;
1143 code = SimpleFieldLoad(length_index); 1120 code = SimpleFieldLoad(length_index);
1144 } else if (!object->IsJSObject()) { 1121 } else if (!object->IsJSObject()) {
1145 // TODO(jkummerow): It would be nice to support non-JSObjects in 1122 // TODO(jkummerow): It would be nice to support non-JSObjects in
1146 // ComputeLoadHandler, then we wouldn't need to go generic here. 1123 // ComputeLoadHandler, then we wouldn't need to go generic here.
(...skipping 21 matching lines...) Expand all
1168 1145
1169 Handle<Code> IC::ComputeHandler(LookupResult* lookup, 1146 Handle<Code> IC::ComputeHandler(LookupResult* lookup,
1170 Handle<JSObject> receiver, 1147 Handle<JSObject> receiver,
1171 Handle<String> name, 1148 Handle<String> name,
1172 Handle<Object> value) { 1149 Handle<Object> value) {
1173 Handle<Code> code = isolate()->stub_cache()->FindHandler( 1150 Handle<Code> code = isolate()->stub_cache()->FindHandler(
1174 name, receiver, kind()); 1151 name, receiver, kind());
1175 if (!code.is_null()) return code; 1152 if (!code.is_null()) return code;
1176 1153
1177 code = CompileHandler(lookup, receiver, name, value); 1154 code = CompileHandler(lookup, receiver, name, value);
1155 ASSERT(code->is_handler());
1178 1156
1179 if (code->is_handler() && code->type() != Code::NORMAL) { 1157 if (code->type() != Code::NORMAL) {
1180 HeapObject::UpdateMapCodeCache(receiver, name, code); 1158 HeapObject::UpdateMapCodeCache(receiver, name, code);
1181 } 1159 }
1182 1160
1183 return code; 1161 return code;
1184 } 1162 }
1185 1163
1186 1164
1187 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, 1165 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
1188 Handle<JSObject> receiver, 1166 Handle<JSObject> receiver,
1189 Handle<String> name, 1167 Handle<String> name,
(...skipping 18 matching lines...) Expand all
1208 // be embedded into code. 1186 // be embedded into code.
1209 if (constant->IsConsString()) break; 1187 if (constant->IsConsString()) break;
1210 return compiler.CompileLoadConstant(receiver, holder, name, constant); 1188 return compiler.CompileLoadConstant(receiver, holder, name, constant);
1211 } 1189 }
1212 case NORMAL: 1190 case NORMAL:
1213 if (kind() != Code::LOAD_IC) break; 1191 if (kind() != Code::LOAD_IC) break;
1214 if (holder->IsGlobalObject()) { 1192 if (holder->IsGlobalObject()) {
1215 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); 1193 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1216 Handle<PropertyCell> cell( 1194 Handle<PropertyCell> cell(
1217 global->GetPropertyCell(lookup), isolate()); 1195 global->GetPropertyCell(lookup), isolate());
1218 // TODO(verwaest): Turn into a handler. 1196 Handle<Code> code = compiler.CompileLoadGlobal(
1219 return isolate()->stub_cache()->ComputeLoadGlobal( 1197 receiver, global, cell, name, lookup->IsDontDelete());
1220 name, receiver, global, cell, lookup->IsDontDelete()); 1198 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1199 HeapObject::UpdateMapCodeCache(receiver, name, code);
1200 return code;
1221 } 1201 }
1222 // There is only one shared stub for loading normalized 1202 // There is only one shared stub for loading normalized
1223 // properties. It does not traverse the prototype chain, so the 1203 // properties. It does not traverse the prototype chain, so the
1224 // property must be found in the receiver for the stub to be 1204 // property must be found in the receiver for the stub to be
1225 // applicable. 1205 // applicable.
1226 if (!holder.is_identical_to(receiver)) break; 1206 if (!holder.is_identical_to(receiver)) break;
1227 return isolate()->builtins()->LoadIC_Normal(); 1207 return isolate()->builtins()->LoadIC_Normal();
1228 case CALLBACKS: { 1208 case CALLBACKS: {
1229 // Use simple field loads for some well-known callback properties. 1209 // Use simple field loads for some well-known callback properties.
1230 int object_offset; 1210 int object_offset;
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 return compiler.CompileStoreTransition( 1605 return compiler.CompileStoreTransition(
1626 receiver, lookup, transition, name); 1606 receiver, lookup, transition, name);
1627 } 1607 }
1628 case NORMAL: 1608 case NORMAL:
1629 if (kind() == Code::KEYED_STORE_IC) break; 1609 if (kind() == Code::KEYED_STORE_IC) break;
1630 if (receiver->IsGlobalObject()) { 1610 if (receiver->IsGlobalObject()) {
1631 // The stub generated for the global object picks the value directly 1611 // The stub generated for the global object picks the value directly
1632 // from the property cell. So the property must be directly on the 1612 // from the property cell. So the property must be directly on the
1633 // global object. 1613 // global object.
1634 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1614 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1635 Handle<PropertyCell> cell( 1615 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate());
1636 global->GetPropertyCell(lookup), isolate()); 1616 Handle<Type> union_type = PropertyCell::UpdatedType(cell, value);
1637 // TODO(verwaest): Turn into a handler. 1617 StoreGlobalStub stub(strict_mode(), union_type->IsConstant());
1638 return isolate()->stub_cache()->ComputeStoreGlobal( 1618
1639 name, global, cell, value, strict_mode()); 1619 Handle<Code> code = stub.GetCodeCopyFromTemplate(
1620 isolate(), receiver->map(), *cell);
1621 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1622 HeapObject::UpdateMapCodeCache(receiver, name, code);
1623 return code;
1640 } 1624 }
1641 ASSERT(holder.is_identical_to(receiver)); 1625 ASSERT(holder.is_identical_to(receiver));
1642 return strict_mode() == kStrictMode 1626 return strict_mode() == kStrictMode
1643 ? isolate()->builtins()->StoreIC_Normal_Strict() 1627 ? isolate()->builtins()->StoreIC_Normal_Strict()
1644 : isolate()->builtins()->StoreIC_Normal(); 1628 : isolate()->builtins()->StoreIC_Normal();
1645 case CALLBACKS: { 1629 case CALLBACKS: {
1646 if (kind() == Code::KEYED_STORE_IC) break; 1630 if (kind() == Code::KEYED_STORE_IC) break;
1647 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1631 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1648 if (callback->IsExecutableAccessorInfo()) { 1632 if (callback->IsExecutableAccessorInfo()) {
1649 Handle<ExecutableAccessorInfo> info = 1633 Handle<ExecutableAccessorInfo> info =
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
1929 } 1913 }
1930 } 1914 }
1931 } 1915 }
1932 1916
1933 1917
1934 MaybeObject* KeyedStoreIC::Store(Handle<Object> object, 1918 MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
1935 Handle<Object> key, 1919 Handle<Object> key,
1936 Handle<Object> value, 1920 Handle<Object> value,
1937 ICMissMode miss_mode) { 1921 ICMissMode miss_mode) {
1938 if (MigrateDeprecated(object)) { 1922 if (MigrateDeprecated(object)) {
1939 return Runtime::SetObjectPropertyOrFail( 1923 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object,
1940 isolate(), object , key, value, NONE, strict_mode()); 1924 key,
1925 value,
1926 NONE,
1927 strict_mode());
1928 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1929 return *result;
1941 } 1930 }
1942 1931
1943 // Check for values that can be converted into an internalized string directly 1932 // Check for values that can be converted into an internalized string directly
1944 // or is representable as a smi. 1933 // or is representable as a smi.
1945 key = TryConvertKey(key, isolate()); 1934 key = TryConvertKey(key, isolate());
1946 1935
1947 MaybeObject* maybe_object = NULL; 1936 MaybeObject* maybe_object = NULL;
1948 Handle<Code> stub = generic_stub(); 1937 Handle<Code> stub = generic_stub();
1949 1938
1950 if (key->IsInternalizedString()) { 1939 if (key->IsInternalizedString()) {
(...skipping 18 matching lines...) Expand all
1969 ASSERT(!object->IsJSGlobalProxy()); 1958 ASSERT(!object->IsJSGlobalProxy());
1970 1959
1971 if (miss_mode != MISS_FORCE_GENERIC) { 1960 if (miss_mode != MISS_FORCE_GENERIC) {
1972 if (object->IsJSObject()) { 1961 if (object->IsJSObject()) {
1973 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1962 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1974 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); 1963 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure();
1975 if (receiver->elements()->map() == 1964 if (receiver->elements()->map() ==
1976 isolate()->heap()->non_strict_arguments_elements_map()) { 1965 isolate()->heap()->non_strict_arguments_elements_map()) {
1977 stub = non_strict_arguments_stub(); 1966 stub = non_strict_arguments_stub();
1978 } else if (key_is_smi_like && 1967 } else if (key_is_smi_like &&
1979 (!target().is_identical_to(non_strict_arguments_stub()))) { 1968 !(target().is_identical_to(non_strict_arguments_stub()))) {
1980 KeyedAccessStoreMode store_mode = 1969 // We should go generic if receiver isn't a dictionary, but our
1981 GetStoreMode(receiver, key, value); 1970 // prototype chain does have dictionary elements. This ensures that
1982 stub = StoreElementStub(receiver, store_mode); 1971 // other non-dictionary receivers in the polymorphic case benefit
1972 // from fast path keyed stores.
1973 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) {
1974 KeyedAccessStoreMode store_mode =
1975 GetStoreMode(receiver, key, value);
1976 stub = StoreElementStub(receiver, store_mode);
1977 }
1983 } 1978 }
1984 } 1979 }
1985 } 1980 }
1986 } 1981 }
1987 } 1982 }
1988 1983
1989 if (!is_target_set()) { 1984 if (!is_target_set()) {
1990 if (*stub == *generic_stub()) { 1985 if (*stub == *generic_stub()) {
1991 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); 1986 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
1992 } 1987 }
1993 ASSERT(!stub.is_null()); 1988 ASSERT(!stub.is_null());
1994 set_target(*stub); 1989 set_target(*stub);
1995 TRACE_IC("StoreIC", key); 1990 TRACE_IC("StoreIC", key);
1996 } 1991 }
1997 1992
1998 if (maybe_object) return maybe_object; 1993 if (maybe_object) return maybe_object;
1999 return Runtime::SetObjectPropertyOrFail( 1994 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key,
2000 isolate(), object , key, value, NONE, strict_mode()); 1995 value,
1996 NONE,
1997 strict_mode());
1998 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1999 return *result;
2001 } 2000 }
2002 2001
2003 2002
2004 #undef TRACE_IC 2003 #undef TRACE_IC
2005 2004
2006 2005
2007 // ---------------------------------------------------------------------------- 2006 // ----------------------------------------------------------------------------
2008 // Static IC stub generators. 2007 // Static IC stub generators.
2009 // 2008 //
2010 2009
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
2221 2220
2222 2221
2223 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { 2222 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) {
2224 HandleScope scope(isolate); 2223 HandleScope scope(isolate);
2225 ASSERT(args.length() == 3); 2224 ASSERT(args.length() == 3);
2226 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2225 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2227 Handle<Object> object = args.at<Object>(0); 2226 Handle<Object> object = args.at<Object>(0);
2228 Handle<Object> key = args.at<Object>(1); 2227 Handle<Object> key = args.at<Object>(1);
2229 Handle<Object> value = args.at<Object>(2); 2228 Handle<Object> value = args.at<Object>(2);
2230 StrictModeFlag strict_mode = ic.strict_mode(); 2229 StrictModeFlag strict_mode = ic.strict_mode();
2231 return Runtime::SetObjectProperty(isolate, 2230 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
2232 object, 2231 value,
2233 key, 2232 NONE,
2234 value, 2233 strict_mode);
2235 NONE, 2234 RETURN_IF_EMPTY_HANDLE(isolate, result);
2236 strict_mode); 2235 return *result;
2237 } 2236 }
2238 2237
2239 2238
2240 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { 2239 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
2241 HandleScope scope(isolate); 2240 HandleScope scope(isolate);
2242 ASSERT(args.length() == 3); 2241 ASSERT(args.length() == 3);
2243 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2242 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2244 Handle<Object> object = args.at<Object>(0); 2243 Handle<Object> object = args.at<Object>(0);
2245 Handle<Object> key = args.at<Object>(1); 2244 Handle<Object> key = args.at<Object>(1);
2246 Handle<Object> value = args.at<Object>(2); 2245 Handle<Object> value = args.at<Object>(2);
2247 StrictModeFlag strict_mode = ic.strict_mode(); 2246 StrictModeFlag strict_mode = ic.strict_mode();
2248 return Runtime::SetObjectProperty(isolate, 2247 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
2249 object, 2248 value,
2250 key, 2249 NONE,
2251 value, 2250 strict_mode);
2252 NONE, 2251 RETURN_IF_EMPTY_HANDLE(isolate, result);
2253 strict_mode); 2252 return *result;
2254 } 2253 }
2255 2254
2256 2255
2257 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { 2256 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2258 HandleScope scope(isolate); 2257 HandleScope scope(isolate);
2259 ASSERT(args.length() == 3); 2258 ASSERT(args.length() == 3);
2260 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2259 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2261 Handle<Object> receiver = args.at<Object>(0); 2260 Handle<Object> receiver = args.at<Object>(0);
2262 Handle<Object> key = args.at<Object>(1); 2261 Handle<Object> key = args.at<Object>(1);
2263 ic.UpdateState(receiver, key); 2262 ic.UpdateState(receiver, key);
2264 return ic.Store(receiver, key, args.at<Object>(2), MISS_FORCE_GENERIC); 2263 return ic.Store(receiver, key, args.at<Object>(2), MISS_FORCE_GENERIC);
2265 } 2264 }
2266 2265
2267 2266
2268 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { 2267 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
2269 HandleScope scope(isolate); 2268 HandleScope scope(isolate);
2270 ASSERT(args.length() == 4); 2269 ASSERT(args.length() == 4);
2271 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2270 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2272 Handle<Object> value = args.at<Object>(0); 2271 Handle<Object> value = args.at<Object>(0);
2272 Handle<Map> map = args.at<Map>(1);
2273 Handle<Object> key = args.at<Object>(2); 2273 Handle<Object> key = args.at<Object>(2);
2274 Handle<Object> object = args.at<Object>(3); 2274 Handle<Object> object = args.at<Object>(3);
2275 StrictModeFlag strict_mode = ic.strict_mode(); 2275 StrictModeFlag strict_mode = ic.strict_mode();
2276 return Runtime::SetObjectProperty(isolate, 2276 if (object->IsJSObject()) {
2277 object, 2277 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
2278 key, 2278 map->elements_kind());
2279 value, 2279 }
2280 NONE, 2280 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
2281 strict_mode); 2281 value,
2282 NONE,
2283 strict_mode);
2284 RETURN_IF_EMPTY_HANDLE(isolate, result);
2285 return *result;
2282 } 2286 }
2283 2287
2284 2288
2285 const char* BinaryOpIC::GetName(TypeInfo type_info) { 2289 const char* BinaryOpIC::GetName(TypeInfo type_info) {
2286 switch (type_info) { 2290 switch (type_info) {
2287 case UNINITIALIZED: return "Uninitialized"; 2291 case UNINITIALIZED: return "Uninitialized";
2288 case SMI: return "Smi"; 2292 case SMI: return "Smi";
2289 case INT32: return "Int32"; 2293 case INT32: return "Int32";
2290 case NUMBER: return "Number"; 2294 case NUMBER: return "Number";
2291 case ODDBALL: return "Oddball"; 2295 case ODDBALL: return "Oddball";
2292 case STRING: return "String"; 2296 case STRING: return "String";
2293 case GENERIC: return "Generic"; 2297 case GENERIC: return "Generic";
2294 default: return "Invalid"; 2298 default: return "Invalid";
2295 } 2299 }
2296 } 2300 }
2297 2301
2298 2302
2299 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) { 2303 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) {
2300 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state(); 2304 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
2301 BinaryOpStub stub(extra_ic_state); 2305 BinaryOpStub stub(extra_ic_state);
2302 2306
2303 Handle<Type> left_type = stub.GetLeftType(isolate()); 2307 Handle<Type> left_type = stub.GetLeftType(isolate());
2304 Handle<Type> right_type = stub.GetRightType(isolate()); 2308 Handle<Type> right_type = stub.GetRightType(isolate());
2305 bool smi_was_enabled = left_type->Maybe(Type::Smi()) && 2309 bool smi_was_enabled = left_type->Maybe(Type::Smi()) &&
2306 right_type->Maybe(Type::Smi()); 2310 right_type->Maybe(Type::Smi());
2307 2311
2308 Maybe<Handle<Object> > result = stub.Result(left, right, isolate()); 2312 Maybe<Handle<Object> > result = stub.Result(left, right, isolate());
2313 if (!result.has_value) return Failure::Exception();
2309 2314
2310 #ifdef DEBUG 2315 #ifdef DEBUG
2311 if (FLAG_trace_ic) { 2316 if (FLAG_trace_ic) {
2312 char buffer[100]; 2317 char buffer[100];
2313 NoAllocationStringAllocator allocator(buffer, 2318 NoAllocationStringAllocator allocator(buffer,
2314 static_cast<unsigned>(sizeof(buffer))); 2319 static_cast<unsigned>(sizeof(buffer)));
2315 StringStream stream(&allocator); 2320 StringStream stream(&allocator);
2316 stream.Add("["); 2321 stream.Add("[");
2317 stub.PrintName(&stream); 2322 stub.PrintName(&stream);
2318 2323
(...skipping 20 matching lines...) Expand all
2339 right_type = stub.GetRightType(isolate()); 2344 right_type = stub.GetRightType(isolate());
2340 bool enable_smi = left_type->Maybe(Type::Smi()) && 2345 bool enable_smi = left_type->Maybe(Type::Smi()) &&
2341 right_type->Maybe(Type::Smi()); 2346 right_type->Maybe(Type::Smi());
2342 2347
2343 if (!smi_was_enabled && enable_smi) { 2348 if (!smi_was_enabled && enable_smi) {
2344 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); 2349 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2345 } else if (smi_was_enabled && !enable_smi) { 2350 } else if (smi_was_enabled && !enable_smi) {
2346 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); 2351 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK);
2347 } 2352 }
2348 2353
2349 return result.has_value 2354 ASSERT(result.has_value);
2350 ? static_cast<MaybeObject*>(*result.value) 2355 return static_cast<MaybeObject*>(*result.value);
2351 : Failure::Exception();
2352 } 2356 }
2353 2357
2354 2358
2355 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) { 2359 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) {
2356 HandleScope scope(isolate); 2360 HandleScope scope(isolate);
2357 Handle<Object> left = args.at<Object>(0); 2361 Handle<Object> left = args.at<Object>(0);
2358 Handle<Object> right = args.at<Object>(1); 2362 Handle<Object> right = args.at<Object>(1);
2359 BinaryOpIC ic(isolate); 2363 BinaryOpIC ic(isolate);
2360 return ic.Transition(left, right); 2364 return ic.Transition(left, right);
2361 } 2365 }
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
2726 #undef ADDR 2730 #undef ADDR
2727 }; 2731 };
2728 2732
2729 2733
2730 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2734 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2731 return IC_utilities[id]; 2735 return IC_utilities[id];
2732 } 2736 }
2733 2737
2734 2738
2735 } } // namespace v8::internal 2739 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/stub-cache-ia32.cc ('k') | src/incremental-marking.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698