| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 if (object->IsUndefined() || object->IsNull()) { | 797 if (object->IsUndefined() || object->IsNull()) { |
| 798 return TypeError("non_object_property_call", object, key); | 798 return TypeError("non_object_property_call", object, key); |
| 799 } | 799 } |
| 800 | 800 |
| 801 bool use_ic = MigrateDeprecated(object) | 801 bool use_ic = MigrateDeprecated(object) |
| 802 ? false : FLAG_use_ic && !object->IsAccessCheckNeeded(); | 802 ? false : FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 803 | 803 |
| 804 if (use_ic && state() != MEGAMORPHIC) { | 804 if (use_ic && state() != MEGAMORPHIC) { |
| 805 ASSERT(!object->IsJSGlobalProxy()); | 805 ASSERT(!object->IsJSGlobalProxy()); |
| 806 int argc = target()->arguments_count(); | 806 int argc = target()->arguments_count(); |
| 807 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( | 807 Handle<Code> stub; |
| 808 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 808 |
| 809 if (object->IsJSObject()) { | 809 // Use the KeyedArrayCallStub if the call is of the form array[smi](...), |
| 810 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 810 // where array is an instance of one of the initial array maps (without |
| 811 if (receiver->elements()->map() == | 811 // extra named properties). |
| 812 isolate()->heap()->non_strict_arguments_elements_map()) { | 812 // TODO(verwaest): Also support keyed calls on instances of other maps. |
| 813 stub = isolate()->stub_cache()->ComputeCallArguments(argc); | 813 if (object->IsJSArray() && key->IsSmi()) { |
| 814 Handle<JSArray> array = Handle<JSArray>::cast(object); |
| 815 ElementsKind kind = array->map()->elements_kind(); |
| 816 if (IsFastObjectElementsKind(kind) && |
| 817 array->map() == isolate()->get_initial_js_array_map(kind)) { |
| 818 KeyedArrayCallStub stub_gen(IsHoleyElementsKind(kind), argc); |
| 819 stub = stub_gen.GetCode(isolate()); |
| 814 } | 820 } |
| 815 } | 821 } |
| 816 ASSERT(!stub.is_null()); | 822 |
| 823 if (stub.is_null()) { |
| 824 stub = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 825 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
| 826 if (object->IsJSObject()) { |
| 827 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 828 if (receiver->elements()->map() == |
| 829 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 830 stub = isolate()->stub_cache()->ComputeCallArguments(argc); |
| 831 } |
| 832 } |
| 833 ASSERT(!stub.is_null()); |
| 834 } |
| 817 set_target(*stub); | 835 set_target(*stub); |
| 818 TRACE_IC("CallIC", key); | 836 TRACE_IC("CallIC", key); |
| 819 } | 837 } |
| 820 | 838 |
| 821 Handle<Object> result = GetProperty(isolate(), object, key); | 839 Handle<Object> result = GetProperty(isolate(), object, key); |
| 822 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 840 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 823 | 841 |
| 824 // Make receiver an object if the callee requires it. Strict mode or builtin | 842 // Make receiver an object if the callee requires it. Strict mode or builtin |
| 825 // functions do not wrap the receiver, non-strict functions and objects | 843 // functions do not wrap the receiver, non-strict functions and objects |
| 826 // called as functions do. | 844 // called as functions do. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 if (!receiver_maps->at(current).is_null() && | 960 if (!receiver_maps->at(current).is_null() && |
| 943 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 961 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
| 944 return false; | 962 return false; |
| 945 } | 963 } |
| 946 } | 964 } |
| 947 receiver_maps->Add(new_receiver_map); | 965 receiver_maps->Add(new_receiver_map); |
| 948 return true; | 966 return true; |
| 949 } | 967 } |
| 950 | 968 |
| 951 | 969 |
| 952 bool IC::UpdatePolymorphicIC(Handle<HeapObject> receiver, | 970 bool IC::UpdatePolymorphicIC(Handle<Object> receiver, |
| 953 Handle<String> name, | 971 Handle<String> name, |
| 954 Handle<Code> code) { | 972 Handle<Code> code) { |
| 955 if (!code->is_handler()) return false; | 973 if (!code->is_handler()) return false; |
| 956 MapHandleList receiver_maps; | 974 MapHandleList receiver_maps; |
| 957 CodeHandleList handlers; | 975 CodeHandleList handlers; |
| 958 | 976 |
| 959 int number_of_valid_maps; | 977 int number_of_valid_maps; |
| 960 int handler_to_overwrite = -1; | 978 int handler_to_overwrite = -1; |
| 961 Handle<Map> new_receiver_map(receiver->map()); | 979 Handle<Map> new_receiver_map(receiver->GetMarkerMap(isolate())); |
| 962 | 980 |
| 963 target()->FindAllMaps(&receiver_maps); | 981 target()->FindAllMaps(&receiver_maps); |
| 964 int number_of_maps = receiver_maps.length(); | 982 int number_of_maps = receiver_maps.length(); |
| 965 number_of_valid_maps = number_of_maps; | 983 number_of_valid_maps = number_of_maps; |
| 966 | 984 |
| 967 for (int i = 0; i < number_of_maps; i++) { | 985 for (int i = 0; i < number_of_maps; i++) { |
| 968 Handle<Map> map = receiver_maps.at(i); | 986 Handle<Map> map = receiver_maps.at(i); |
| 969 // Filter out deprecated maps to ensure its instances get migrated. | 987 // Filter out deprecated maps to ensure its instances get migrated. |
| 970 if (map->is_deprecated()) { | 988 if (map->is_deprecated()) { |
| 971 number_of_valid_maps--; | 989 number_of_valid_maps--; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 993 handlers.Add(code); | 1011 handlers.Add(code); |
| 994 } | 1012 } |
| 995 | 1013 |
| 996 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 1014 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
| 997 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode()); | 1015 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode()); |
| 998 set_target(*ic); | 1016 set_target(*ic); |
| 999 return true; | 1017 return true; |
| 1000 } | 1018 } |
| 1001 | 1019 |
| 1002 | 1020 |
| 1003 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver, | 1021 void IC::UpdateMonomorphicIC(Handle<Object> receiver, |
| 1004 Handle<Code> handler, | 1022 Handle<Code> handler, |
| 1005 Handle<String> name) { | 1023 Handle<String> name) { |
| 1006 if (!handler->is_handler()) return set_target(*handler); | 1024 if (!handler->is_handler()) return set_target(*handler); |
| 1007 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 1025 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
| 1008 receiver, handler, name, strict_mode()); | 1026 name, receiver, handler, strict_mode()); |
| 1009 set_target(*ic); | 1027 set_target(*ic); |
| 1010 } | 1028 } |
| 1011 | 1029 |
| 1012 | 1030 |
| 1013 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 1031 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
| 1014 MapHandleList receiver_maps; | 1032 MapHandleList receiver_maps; |
| 1015 CodeHandleList handlers; | 1033 CodeHandleList handlers; |
| 1016 target()->FindAllMaps(&receiver_maps); | 1034 target()->FindAllMaps(&receiver_maps); |
| 1017 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return; | 1035 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return; |
| 1018 for (int i = 0; i < receiver_maps.length(); i++) { | 1036 for (int i = 0; i < receiver_maps.length(); i++) { |
| 1019 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); | 1037 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); |
| 1020 } | 1038 } |
| 1021 } | 1039 } |
| 1022 | 1040 |
| 1023 | 1041 |
| 1024 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { | 1042 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { |
| 1025 Map* current_map = target()->FindFirstMap(); | 1043 Map* current_map = target()->FindFirstMap(); |
| 1026 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); | 1044 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); |
| 1027 bool more_general_transition = | 1045 bool more_general_transition = |
| 1028 IsMoreGeneralElementsKindTransition( | 1046 IsMoreGeneralElementsKindTransition( |
| 1029 current_map->elements_kind(), receiver_elements_kind); | 1047 current_map->elements_kind(), receiver_elements_kind); |
| 1030 Map* transitioned_map = more_general_transition | 1048 Map* transitioned_map = more_general_transition |
| 1031 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) | 1049 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) |
| 1032 : NULL; | 1050 : NULL; |
| 1033 | 1051 |
| 1034 return transitioned_map == receiver_map; | 1052 return transitioned_map == receiver_map; |
| 1035 } | 1053 } |
| 1036 | 1054 |
| 1037 | 1055 |
| 1038 void IC::PatchCache(Handle<HeapObject> receiver, | 1056 void IC::PatchCache(Handle<Object> object, |
| 1039 Handle<String> name, | 1057 Handle<String> name, |
| 1040 Handle<Code> code) { | 1058 Handle<Code> code) { |
| 1041 switch (state()) { | 1059 switch (state()) { |
| 1042 case UNINITIALIZED: | 1060 case UNINITIALIZED: |
| 1043 case PREMONOMORPHIC: | 1061 case PREMONOMORPHIC: |
| 1044 case MONOMORPHIC_PROTOTYPE_FAILURE: | 1062 case MONOMORPHIC_PROTOTYPE_FAILURE: |
| 1045 UpdateMonomorphicIC(receiver, code, name); | 1063 UpdateMonomorphicIC(object, code, name); |
| 1046 break; | 1064 break; |
| 1047 case MONOMORPHIC: | 1065 case MONOMORPHIC: { |
| 1048 // For now, call stubs are allowed to rewrite to the same stub. This | 1066 // 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. | 1067 // happens e.g., when the field does not contain a function. |
| 1050 ASSERT(target()->is_call_stub() || | 1068 ASSERT(target()->is_call_stub() || |
| 1051 target()->is_keyed_call_stub() || | 1069 target()->is_keyed_call_stub() || |
| 1052 !target().is_identical_to(code)); | 1070 !target().is_identical_to(code)); |
| 1053 if (!target()->is_keyed_stub()) { | 1071 Code* old_handler = target()->FindFirstHandler(); |
| 1054 bool is_same_handler = false; | 1072 if (old_handler == *code && |
| 1055 Code* old_handler = target()->FindFirstHandler(); | 1073 IsTransitionedMapOfMonomorphicTarget( |
| 1056 is_same_handler = old_handler == *code; | 1074 object->GetMarkerMap(isolate()))) { |
| 1057 | 1075 UpdateMonomorphicIC(object, code, name); |
| 1058 if (is_same_handler && | 1076 break; |
| 1059 IsTransitionedMapOfMonomorphicTarget(receiver->map())) { | |
| 1060 UpdateMonomorphicIC(receiver, code, name); | |
| 1061 break; | |
| 1062 } | |
| 1063 } | 1077 } |
| 1064 // Fall through. | 1078 // Fall through. |
| 1079 } |
| 1065 case POLYMORPHIC: | 1080 case POLYMORPHIC: |
| 1066 if (!target()->is_keyed_stub()) { | 1081 if (!target()->is_keyed_stub()) { |
| 1067 if (UpdatePolymorphicIC(receiver, name, code)) break; | 1082 if (UpdatePolymorphicIC(object, name, code)) break; |
| 1068 CopyICToMegamorphicCache(name); | 1083 CopyICToMegamorphicCache(name); |
| 1069 } | 1084 } |
| 1070 set_target(*megamorphic_stub()); | 1085 set_target(*megamorphic_stub()); |
| 1071 // Fall through. | 1086 // Fall through. |
| 1072 case MEGAMORPHIC: | 1087 case MEGAMORPHIC: |
| 1073 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1088 UpdateMegamorphicCache(object->GetMarkerMap(isolate()), *name, *code); |
| 1074 break; | 1089 break; |
| 1075 case DEBUG_STUB: | 1090 case DEBUG_STUB: |
| 1076 break; | 1091 break; |
| 1077 case GENERIC: | 1092 case GENERIC: |
| 1078 UNREACHABLE(); | 1093 UNREACHABLE(); |
| 1079 break; | 1094 break; |
| 1080 } | 1095 } |
| 1081 } | 1096 } |
| 1082 | 1097 |
| 1083 | 1098 |
| 1084 Handle<Code> LoadIC::SimpleFieldLoad(int offset, | 1099 Handle<Code> LoadIC::SimpleFieldLoad(int offset, |
| 1085 bool inobject, | 1100 bool inobject, |
| 1086 Representation representation) { | 1101 Representation representation) { |
| 1087 if (kind() == Code::LOAD_IC) { | 1102 if (kind() == Code::LOAD_IC) { |
| 1088 LoadFieldStub stub(inobject, offset, representation); | 1103 LoadFieldStub stub(inobject, offset, representation); |
| 1089 return stub.GetCode(isolate()); | 1104 return stub.GetCode(isolate()); |
| 1090 } else { | 1105 } else { |
| 1091 KeyedLoadFieldStub stub(inobject, offset, representation); | 1106 KeyedLoadFieldStub stub(inobject, offset, representation); |
| 1092 return stub.GetCode(isolate()); | 1107 return stub.GetCode(isolate()); |
| 1093 } | 1108 } |
| 1094 } | 1109 } |
| 1095 | 1110 |
| 1096 | 1111 |
| 1097 void LoadIC::UpdateCaches(LookupResult* lookup, | 1112 void LoadIC::UpdateCaches(LookupResult* lookup, |
| 1098 Handle<Object> object, | 1113 Handle<Object> object, |
| 1099 Handle<String> name) { | 1114 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) { | 1115 if (state() == UNINITIALIZED) { |
| 1108 // This is the first time we execute this inline cache. | 1116 // This is the first time we execute this inline cache. |
| 1109 // Set the target to the pre monomorphic stub to delay | 1117 // Set the target to the pre monomorphic stub to delay |
| 1110 // setting the monomorphic state. | 1118 // setting the monomorphic state. |
| 1111 set_target(*pre_monomorphic_stub()); | 1119 set_target(*pre_monomorphic_stub()); |
| 1112 TRACE_IC("LoadIC", name); | 1120 TRACE_IC("LoadIC", name); |
| 1113 return; | 1121 return; |
| 1114 } else if (!lookup->IsCacheable()) { | 1122 } |
| 1123 |
| 1124 Handle<Code> code; |
| 1125 if (!lookup->IsCacheable()) { |
| 1115 // Bail out if the result is not cacheable. | 1126 // Bail out if the result is not cacheable. |
| 1116 code = slow_stub(); | 1127 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()) { | 1128 } else if (!lookup->IsProperty()) { |
| 1126 code = kind() == Code::LOAD_IC | 1129 if (kind() == Code::LOAD_IC) { |
| 1127 ? isolate()->stub_cache()->ComputeLoadNonexistent( | 1130 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object); |
| 1128 name, Handle<JSObject>::cast(receiver)) | 1131 } else { |
| 1129 : slow_stub(); | 1132 code = slow_stub(); |
| 1133 } |
| 1130 } else { | 1134 } else { |
| 1131 code = ComputeHandler(lookup, Handle<JSObject>::cast(receiver), name); | 1135 code = ComputeHandler(lookup, object, name); |
| 1132 } | 1136 } |
| 1133 | 1137 |
| 1134 PatchCache(receiver, name, code); | 1138 PatchCache(object, name, code); |
| 1135 TRACE_IC("LoadIC", name); | 1139 TRACE_IC("LoadIC", name); |
| 1136 } | 1140 } |
| 1137 | 1141 |
| 1138 | 1142 |
| 1139 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { | 1143 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { |
| 1140 // Cache code holding map should be consistent with | 1144 // Cache code holding map should be consistent with |
| 1141 // GenerateMonomorphicCacheProbe. | 1145 // GenerateMonomorphicCacheProbe. |
| 1142 isolate()->stub_cache()->Set(name, map, code); | 1146 isolate()->stub_cache()->Set(name, map, code); |
| 1143 } | 1147 } |
| 1144 | 1148 |
| 1145 | 1149 |
| 1146 Handle<Code> IC::ComputeHandler(LookupResult* lookup, | 1150 Handle<Code> IC::ComputeHandler(LookupResult* lookup, |
| 1147 Handle<JSObject> receiver, | 1151 Handle<Object> object, |
| 1148 Handle<String> name, | 1152 Handle<String> name, |
| 1149 Handle<Object> value) { | 1153 Handle<Object> value) { |
| 1154 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); |
| 1155 Handle<HeapObject> stub_holder(GetCodeCacheHolder( |
| 1156 isolate(), *object, cache_holder)); |
| 1157 |
| 1150 Handle<Code> code = isolate()->stub_cache()->FindHandler( | 1158 Handle<Code> code = isolate()->stub_cache()->FindHandler( |
| 1151 name, receiver, kind()); | 1159 name, stub_holder, kind(), cache_holder, strict_mode()); |
| 1152 if (!code.is_null()) return code; | 1160 if (!code.is_null()) return code; |
| 1153 | 1161 |
| 1154 code = CompileHandler(lookup, receiver, name, value); | 1162 code = CompileHandler(lookup, object, name, value, cache_holder); |
| 1155 ASSERT(code->is_handler()); | 1163 ASSERT(code->is_handler()); |
| 1156 | 1164 |
| 1157 if (code->type() != Code::NORMAL) { | 1165 if (code->type() != Code::NORMAL) { |
| 1158 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1166 HeapObject::UpdateMapCodeCache(stub_holder, name, code); |
| 1159 } | 1167 } |
| 1160 | 1168 |
| 1161 return code; | 1169 return code; |
| 1162 } | 1170 } |
| 1163 | 1171 |
| 1164 | 1172 |
| 1165 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, | 1173 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, |
| 1166 Handle<JSObject> receiver, | 1174 Handle<Object> object, |
| 1167 Handle<String> name, | 1175 Handle<String> name, |
| 1168 Handle<Object> unused) { | 1176 Handle<Object> unused, |
| 1177 InlineCacheHolderFlag cache_holder) { |
| 1178 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { |
| 1179 int length_index = String::kLengthOffset / kPointerSize; |
| 1180 return SimpleFieldLoad(length_index); |
| 1181 } |
| 1182 |
| 1169 Handle<JSObject> holder(lookup->holder()); | 1183 Handle<JSObject> holder(lookup->holder()); |
| 1170 LoadStubCompiler compiler(isolate(), kind()); | 1184 LoadStubCompiler compiler(isolate(), cache_holder, kind()); |
| 1171 | 1185 |
| 1172 switch (lookup->type()) { | 1186 switch (lookup->type()) { |
| 1173 case FIELD: { | 1187 case FIELD: { |
| 1174 PropertyIndex field = lookup->GetFieldIndex(); | 1188 PropertyIndex field = lookup->GetFieldIndex(); |
| 1175 if (receiver.is_identical_to(holder)) { | 1189 if (object.is_identical_to(holder)) { |
| 1176 return SimpleFieldLoad(field.translate(holder), | 1190 return SimpleFieldLoad(field.translate(holder), |
| 1177 field.is_inobject(holder), | 1191 field.is_inobject(holder), |
| 1178 lookup->representation()); | 1192 lookup->representation()); |
| 1179 } | 1193 } |
| 1180 return compiler.CompileLoadField( | 1194 return compiler.CompileLoadField( |
| 1181 receiver, holder, name, field, lookup->representation()); | 1195 object, holder, name, field, lookup->representation()); |
| 1182 } | 1196 } |
| 1183 case CONSTANT: { | 1197 case CONSTANT: { |
| 1184 Handle<Object> constant(lookup->GetConstant(), isolate()); | 1198 Handle<Object> constant(lookup->GetConstant(), isolate()); |
| 1185 // TODO(2803): Don't compute a stub for cons strings because they cannot | 1199 // TODO(2803): Don't compute a stub for cons strings because they cannot |
| 1186 // be embedded into code. | 1200 // be embedded into code. |
| 1187 if (constant->IsConsString()) break; | 1201 if (constant->IsConsString()) break; |
| 1188 return compiler.CompileLoadConstant(receiver, holder, name, constant); | 1202 return compiler.CompileLoadConstant(object, holder, name, constant); |
| 1189 } | 1203 } |
| 1190 case NORMAL: | 1204 case NORMAL: |
| 1191 if (kind() != Code::LOAD_IC) break; | 1205 if (kind() != Code::LOAD_IC) break; |
| 1192 if (holder->IsGlobalObject()) { | 1206 if (holder->IsGlobalObject()) { |
| 1193 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); | 1207 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 1194 Handle<PropertyCell> cell( | 1208 Handle<PropertyCell> cell( |
| 1195 global->GetPropertyCell(lookup), isolate()); | 1209 global->GetPropertyCell(lookup), isolate()); |
| 1196 Handle<Code> code = compiler.CompileLoadGlobal( | 1210 Handle<Code> code = compiler.CompileLoadGlobal( |
| 1197 receiver, global, cell, name, lookup->IsDontDelete()); | 1211 object, global, cell, name, lookup->IsDontDelete()); |
| 1198 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1212 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1199 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1213 Handle<HeapObject> stub_holder(GetCodeCacheHolder( |
| 1214 isolate(), *object, cache_holder)); |
| 1215 HeapObject::UpdateMapCodeCache(stub_holder, name, code); |
| 1200 return code; | 1216 return code; |
| 1201 } | 1217 } |
| 1202 // There is only one shared stub for loading normalized | 1218 // There is only one shared stub for loading normalized |
| 1203 // properties. It does not traverse the prototype chain, so the | 1219 // properties. It does not traverse the prototype chain, so the |
| 1204 // property must be found in the receiver for the stub to be | 1220 // property must be found in the object for the stub to be |
| 1205 // applicable. | 1221 // applicable. |
| 1206 if (!holder.is_identical_to(receiver)) break; | 1222 if (!object.is_identical_to(holder)) break; |
| 1207 return isolate()->builtins()->LoadIC_Normal(); | 1223 return isolate()->builtins()->LoadIC_Normal(); |
| 1208 case CALLBACKS: { | 1224 case CALLBACKS: { |
| 1209 // Use simple field loads for some well-known callback properties. | 1225 // Use simple field loads for some well-known callback properties. |
| 1210 int object_offset; | 1226 int object_offset; |
| 1211 Handle<Map> map(receiver->map()); | 1227 if (object->IsJSObject()) { |
| 1212 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { | 1228 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1213 PropertyIndex index = | 1229 Handle<Map> map(receiver->map()); |
| 1214 PropertyIndex::NewHeaderIndex(object_offset / kPointerSize); | 1230 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { |
| 1215 return compiler.CompileLoadField( | 1231 PropertyIndex index = |
| 1216 receiver, receiver, name, index, Representation::Tagged()); | 1232 PropertyIndex::NewHeaderIndex(object_offset / kPointerSize); |
| 1233 return compiler.CompileLoadField( |
| 1234 receiver, receiver, name, index, Representation::Tagged()); |
| 1235 } |
| 1217 } | 1236 } |
| 1218 | 1237 |
| 1219 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1238 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
| 1220 if (callback->IsExecutableAccessorInfo()) { | 1239 if (callback->IsExecutableAccessorInfo()) { |
| 1221 Handle<ExecutableAccessorInfo> info = | 1240 Handle<ExecutableAccessorInfo> info = |
| 1222 Handle<ExecutableAccessorInfo>::cast(callback); | 1241 Handle<ExecutableAccessorInfo>::cast(callback); |
| 1223 if (v8::ToCData<Address>(info->getter()) == 0) break; | 1242 if (v8::ToCData<Address>(info->getter()) == 0) break; |
| 1224 if (!info->IsCompatibleReceiver(*receiver)) break; | 1243 if (!info->IsCompatibleReceiver(*object)) break; |
| 1225 return compiler.CompileLoadCallback(receiver, holder, name, info); | 1244 return compiler.CompileLoadCallback(object, holder, name, info); |
| 1226 } else if (callback->IsAccessorPair()) { | 1245 } else if (callback->IsAccessorPair()) { |
| 1227 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), | 1246 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), |
| 1228 isolate()); | 1247 isolate()); |
| 1229 if (!getter->IsJSFunction()) break; | 1248 if (!getter->IsJSFunction()) break; |
| 1230 if (holder->IsGlobalObject()) break; | 1249 if (holder->IsGlobalObject()) break; |
| 1231 if (!holder->HasFastProperties()) break; | 1250 if (!holder->HasFastProperties()) break; |
| 1232 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1251 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 1252 if (!object->IsJSObject() && |
| 1253 !function->IsBuiltin() && |
| 1254 function->shared()->is_classic_mode()) { |
| 1255 // Calling non-strict non-builtins with a value as the receiver |
| 1256 // requires boxing. |
| 1257 break; |
| 1258 } |
| 1233 CallOptimization call_optimization(function); | 1259 CallOptimization call_optimization(function); |
| 1234 if (call_optimization.is_simple_api_call() && | 1260 if (call_optimization.is_simple_api_call() && |
| 1235 call_optimization.IsCompatibleReceiver(*receiver)) { | 1261 call_optimization.IsCompatibleReceiver(*object)) { |
| 1236 return compiler.CompileLoadCallback( | 1262 return compiler.CompileLoadCallback( |
| 1237 receiver, holder, name, call_optimization); | 1263 object, holder, name, call_optimization); |
| 1238 } | 1264 } |
| 1239 return compiler.CompileLoadViaGetter(receiver, holder, name, function); | 1265 return compiler.CompileLoadViaGetter(object, holder, name, function); |
| 1240 } | 1266 } |
| 1241 // TODO(dcarney): Handle correctly. | 1267 // TODO(dcarney): Handle correctly. |
| 1242 if (callback->IsDeclaredAccessorInfo()) break; | 1268 if (callback->IsDeclaredAccessorInfo()) break; |
| 1243 ASSERT(callback->IsForeign()); | 1269 ASSERT(callback->IsForeign()); |
| 1244 // No IC support for old-style native accessors. | 1270 // No IC support for old-style native accessors. |
| 1245 break; | 1271 break; |
| 1246 } | 1272 } |
| 1247 case INTERCEPTOR: | 1273 case INTERCEPTOR: |
| 1248 ASSERT(HasInterceptorGetter(*holder)); | 1274 ASSERT(HasInterceptorGetter(*holder)); |
| 1249 return compiler.CompileLoadInterceptor(receiver, holder, name); | 1275 return compiler.CompileLoadInterceptor(object, holder, name); |
| 1250 default: | 1276 default: |
| 1251 break; | 1277 break; |
| 1252 } | 1278 } |
| 1253 | 1279 |
| 1254 return slow_stub(); | 1280 return slow_stub(); |
| 1255 } | 1281 } |
| 1256 | 1282 |
| 1257 | 1283 |
| 1258 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { | 1284 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
| 1259 // This helper implements a few common fast cases for converting | 1285 // This helper implements a few common fast cases for converting |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1357 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1332 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); | 1358 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); |
| 1333 return generic_stub(); | 1359 return generic_stub(); |
| 1334 } | 1360 } |
| 1335 | 1361 |
| 1336 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( | 1362 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( |
| 1337 &target_receiver_maps); | 1363 &target_receiver_maps); |
| 1338 } | 1364 } |
| 1339 | 1365 |
| 1340 | 1366 |
| 1341 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, | 1367 MaybeObject* KeyedLoadIC::LoadForceGeneric(Handle<Object> object, |
| 1342 Handle<Object> key, | 1368 Handle<Object> key) { |
| 1343 ICMissMode miss_mode) { | 1369 set_target(*generic_stub()); |
| 1370 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
| 1371 } |
| 1372 |
| 1373 |
| 1374 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, Handle<Object> key) { |
| 1344 if (MigrateDeprecated(object)) { | 1375 if (MigrateDeprecated(object)) { |
| 1345 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1376 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
| 1346 } | 1377 } |
| 1347 | 1378 |
| 1348 MaybeObject* maybe_object = NULL; | 1379 MaybeObject* maybe_object = NULL; |
| 1349 Handle<Code> stub = generic_stub(); | 1380 Handle<Code> stub = generic_stub(); |
| 1350 | 1381 |
| 1351 // Check for values that can be converted into an internalized string directly | 1382 // Check for values that can be converted into an internalized string directly |
| 1352 // or is representable as a smi. | 1383 // or is representable as a smi. |
| 1353 key = TryConvertKey(key, isolate()); | 1384 key = TryConvertKey(key, isolate()); |
| 1354 | 1385 |
| 1355 if (key->IsInternalizedString()) { | 1386 if (key->IsInternalizedString()) { |
| 1356 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); | 1387 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); |
| 1357 if (maybe_object->IsFailure()) return maybe_object; | 1388 if (maybe_object->IsFailure()) return maybe_object; |
| 1358 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1389 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
| 1359 ASSERT(!object->IsJSGlobalProxy()); | 1390 ASSERT(!object->IsJSGlobalProxy()); |
| 1360 if (miss_mode != MISS_FORCE_GENERIC) { | 1391 if (object->IsString() && key->IsNumber()) { |
| 1361 if (object->IsString() && key->IsNumber()) { | 1392 if (state() == UNINITIALIZED) stub = string_stub(); |
| 1362 if (state() == UNINITIALIZED) stub = string_stub(); | 1393 } else if (object->IsJSObject()) { |
| 1363 } else if (object->IsJSObject()) { | 1394 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1364 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1395 if (receiver->elements()->map() == |
| 1365 if (receiver->elements()->map() == | 1396 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1366 isolate()->heap()->non_strict_arguments_elements_map()) { | 1397 stub = non_strict_arguments_stub(); |
| 1367 stub = non_strict_arguments_stub(); | 1398 } else if (receiver->HasIndexedInterceptor()) { |
| 1368 } else if (receiver->HasIndexedInterceptor()) { | 1399 stub = indexed_interceptor_stub(); |
| 1369 stub = indexed_interceptor_stub(); | 1400 } else if (!key->ToSmi()->IsFailure() && |
| 1370 } else if (!key->ToSmi()->IsFailure() && | 1401 (!target().is_identical_to(non_strict_arguments_stub()))) { |
| 1371 (!target().is_identical_to(non_strict_arguments_stub()))) { | 1402 stub = LoadElementStub(receiver); |
| 1372 stub = LoadElementStub(receiver); | |
| 1373 } | |
| 1374 } | 1403 } |
| 1375 } | 1404 } |
| 1376 } | 1405 } |
| 1377 | 1406 |
| 1378 if (!is_target_set()) { | 1407 if (!is_target_set()) { |
| 1379 if (*stub == *generic_stub()) { | 1408 if (*stub == *generic_stub()) { |
| 1380 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1409 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1381 } | 1410 } |
| 1382 ASSERT(!stub.is_null()); | 1411 ASSERT(!stub.is_null()); |
| 1383 set_target(*stub); | 1412 set_target(*stub); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1575 ASSERT(!lookup->IsHandler()); | 1604 ASSERT(!lookup->IsHandler()); |
| 1576 | 1605 |
| 1577 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); | 1606 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); |
| 1578 | 1607 |
| 1579 PatchCache(receiver, name, code); | 1608 PatchCache(receiver, name, code); |
| 1580 TRACE_IC("StoreIC", name); | 1609 TRACE_IC("StoreIC", name); |
| 1581 } | 1610 } |
| 1582 | 1611 |
| 1583 | 1612 |
| 1584 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, | 1613 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, |
| 1585 Handle<JSObject> receiver, | 1614 Handle<Object> object, |
| 1586 Handle<String> name, | 1615 Handle<String> name, |
| 1587 Handle<Object> value) { | 1616 Handle<Object> value, |
| 1617 InlineCacheHolderFlag cache_holder) { |
| 1618 ASSERT(cache_holder == OWN_MAP); |
| 1619 // This is currently guaranteed by checks in StoreIC::Store. |
| 1620 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1621 |
| 1588 Handle<JSObject> holder(lookup->holder()); | 1622 Handle<JSObject> holder(lookup->holder()); |
| 1589 StoreStubCompiler compiler(isolate(), strict_mode(), kind()); | 1623 StoreStubCompiler compiler(isolate(), strict_mode(), kind()); |
| 1590 switch (lookup->type()) { | 1624 switch (lookup->type()) { |
| 1591 case FIELD: | 1625 case FIELD: |
| 1592 return compiler.CompileStoreField(receiver, lookup, name); | 1626 return compiler.CompileStoreField(receiver, lookup, name); |
| 1593 case TRANSITION: { | 1627 case TRANSITION: { |
| 1594 // Explicitly pass in the receiver map since LookupForWrite may have | 1628 // Explicitly pass in the receiver map since LookupForWrite may have |
| 1595 // stored something else than the receiver in the holder. | 1629 // stored something else than the receiver in the holder. |
| 1596 Handle<Map> transition( | 1630 Handle<Map> transition( |
| 1597 lookup->GetTransitionTarget(receiver->map()), isolate()); | 1631 lookup->GetTransitionTarget(receiver->map()), isolate()); |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1908 Heap* heap = receiver->GetHeap(); | 1942 Heap* heap = receiver->GetHeap(); |
| 1909 if (receiver->elements()->map() == heap->fixed_cow_array_map()) { | 1943 if (receiver->elements()->map() == heap->fixed_cow_array_map()) { |
| 1910 return STORE_NO_TRANSITION_HANDLE_COW; | 1944 return STORE_NO_TRANSITION_HANDLE_COW; |
| 1911 } else { | 1945 } else { |
| 1912 return STANDARD_STORE; | 1946 return STANDARD_STORE; |
| 1913 } | 1947 } |
| 1914 } | 1948 } |
| 1915 } | 1949 } |
| 1916 | 1950 |
| 1917 | 1951 |
| 1952 MaybeObject* KeyedStoreIC::StoreForceGeneric(Handle<Object> object, |
| 1953 Handle<Object> key, |
| 1954 Handle<Object> value) { |
| 1955 set_target(*generic_stub()); |
| 1956 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, |
| 1957 key, |
| 1958 value, |
| 1959 NONE, |
| 1960 strict_mode()); |
| 1961 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1962 return *result; |
| 1963 } |
| 1964 |
| 1965 |
| 1918 MaybeObject* KeyedStoreIC::Store(Handle<Object> object, | 1966 MaybeObject* KeyedStoreIC::Store(Handle<Object> object, |
| 1919 Handle<Object> key, | 1967 Handle<Object> key, |
| 1920 Handle<Object> value, | 1968 Handle<Object> value) { |
| 1921 ICMissMode miss_mode) { | |
| 1922 if (MigrateDeprecated(object)) { | 1969 if (MigrateDeprecated(object)) { |
| 1923 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, | 1970 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, |
| 1924 key, | 1971 key, |
| 1925 value, | 1972 value, |
| 1926 NONE, | 1973 NONE, |
| 1927 strict_mode()); | 1974 strict_mode()); |
| 1928 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1975 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1929 return *result; | 1976 return *result; |
| 1930 } | 1977 } |
| 1931 | 1978 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1950 // Don't use ICs for maps of the objects in Array's prototype chain. We | 1997 // Don't use ICs for maps of the objects in Array's prototype chain. We |
| 1951 // expect to be able to trap element sets to objects with those maps in | 1998 // expect to be able to trap element sets to objects with those maps in |
| 1952 // the runtime to enable optimization of element hole access. | 1999 // the runtime to enable optimization of element hole access. |
| 1953 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | 2000 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
| 1954 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; | 2001 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; |
| 1955 } | 2002 } |
| 1956 | 2003 |
| 1957 if (use_ic) { | 2004 if (use_ic) { |
| 1958 ASSERT(!object->IsJSGlobalProxy()); | 2005 ASSERT(!object->IsJSGlobalProxy()); |
| 1959 | 2006 |
| 1960 if (miss_mode != MISS_FORCE_GENERIC) { | 2007 if (object->IsJSObject()) { |
| 1961 if (object->IsJSObject()) { | 2008 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1962 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 2009 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); |
| 1963 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); | 2010 if (receiver->elements()->map() == |
| 1964 if (receiver->elements()->map() == | 2011 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1965 isolate()->heap()->non_strict_arguments_elements_map()) { | 2012 stub = non_strict_arguments_stub(); |
| 1966 stub = non_strict_arguments_stub(); | 2013 } else if (key_is_smi_like && |
| 1967 } else if (key_is_smi_like && | 2014 !(target().is_identical_to(non_strict_arguments_stub()))) { |
| 1968 !(target().is_identical_to(non_strict_arguments_stub()))) { | 2015 // We should go generic if receiver isn't a dictionary, but our |
| 1969 // We should go generic if receiver isn't a dictionary, but our | 2016 // prototype chain does have dictionary elements. This ensures that |
| 1970 // prototype chain does have dictionary elements. This ensures that | 2017 // other non-dictionary receivers in the polymorphic case benefit |
| 1971 // other non-dictionary receivers in the polymorphic case benefit | 2018 // from fast path keyed stores. |
| 1972 // from fast path keyed stores. | 2019 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { |
| 1973 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { | 2020 KeyedAccessStoreMode store_mode = |
| 1974 KeyedAccessStoreMode store_mode = | 2021 GetStoreMode(receiver, key, value); |
| 1975 GetStoreMode(receiver, key, value); | 2022 stub = StoreElementStub(receiver, store_mode); |
| 1976 stub = StoreElementStub(receiver, store_mode); | |
| 1977 } | |
| 1978 } | 2023 } |
| 1979 } | 2024 } |
| 1980 } | 2025 } |
| 1981 } | 2026 } |
| 1982 } | 2027 } |
| 1983 | 2028 |
| 1984 if (!is_target_set()) { | 2029 if (!is_target_set()) { |
| 1985 if (*stub == *generic_stub()) { | 2030 if (*stub == *generic_stub()) { |
| 1986 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); | 2031 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
| 1987 } | 2032 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2066 | 2111 |
| 2067 | 2112 |
| 2068 // Used from ic-<arch>.cc | 2113 // Used from ic-<arch>.cc |
| 2069 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { | 2114 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { |
| 2070 HandleScope scope(isolate); | 2115 HandleScope scope(isolate); |
| 2071 ASSERT(args.length() == 2); | 2116 ASSERT(args.length() == 2); |
| 2072 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2117 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2073 Handle<Object> receiver = args.at<Object>(0); | 2118 Handle<Object> receiver = args.at<Object>(0); |
| 2074 Handle<Object> key = args.at<Object>(1); | 2119 Handle<Object> key = args.at<Object>(1); |
| 2075 ic.UpdateState(receiver, key); | 2120 ic.UpdateState(receiver, key); |
| 2076 return ic.Load(receiver, key, MISS); | 2121 return ic.Load(receiver, key); |
| 2077 } | 2122 } |
| 2078 | 2123 |
| 2079 | 2124 |
| 2080 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { | 2125 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { |
| 2081 HandleScope scope(isolate); | 2126 HandleScope scope(isolate); |
| 2082 ASSERT(args.length() == 2); | 2127 ASSERT(args.length() == 2); |
| 2083 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2128 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2084 Handle<Object> receiver = args.at<Object>(0); | 2129 Handle<Object> receiver = args.at<Object>(0); |
| 2085 Handle<Object> key = args.at<Object>(1); | 2130 Handle<Object> key = args.at<Object>(1); |
| 2086 ic.UpdateState(receiver, key); | 2131 ic.UpdateState(receiver, key); |
| 2087 return ic.Load(receiver, key, MISS); | 2132 return ic.Load(receiver, key); |
| 2088 } | 2133 } |
| 2089 | 2134 |
| 2090 | 2135 |
| 2091 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { | 2136 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { |
| 2092 HandleScope scope(isolate); | 2137 HandleScope scope(isolate); |
| 2093 ASSERT(args.length() == 2); | 2138 ASSERT(args.length() == 2); |
| 2094 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2139 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2095 Handle<Object> receiver = args.at<Object>(0); | 2140 Handle<Object> receiver = args.at<Object>(0); |
| 2096 Handle<Object> key = args.at<Object>(1); | 2141 Handle<Object> key = args.at<Object>(1); |
| 2097 ic.UpdateState(receiver, key); | 2142 ic.UpdateState(receiver, key); |
| 2098 return ic.Load(receiver, key, MISS_FORCE_GENERIC); | 2143 return ic.LoadForceGeneric(receiver, key); |
| 2099 } | 2144 } |
| 2100 | 2145 |
| 2101 | 2146 |
| 2102 // Used from ic-<arch>.cc. | 2147 // Used from ic-<arch>.cc. |
| 2103 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { | 2148 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { |
| 2104 HandleScope scope(isolate); | 2149 HandleScope scope(isolate); |
| 2105 ASSERT(args.length() == 3); | 2150 ASSERT(args.length() == 3); |
| 2106 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2151 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2107 Handle<Object> receiver = args.at<Object>(0); | 2152 Handle<Object> receiver = args.at<Object>(0); |
| 2108 Handle<String> key = args.at<String>(1); | 2153 Handle<String> key = args.at<String>(1); |
| 2109 ic.UpdateState(receiver, key); | 2154 ic.UpdateState(receiver, key); |
| 2110 return ic.Store(receiver, key, args.at<Object>(2)); | 2155 return ic.Store(receiver, key, args.at<Object>(2)); |
| 2111 } | 2156 } |
| 2112 | 2157 |
| 2113 | 2158 |
| 2114 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { | 2159 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { |
| 2115 HandleScope scope(isolate); | 2160 HandleScope scope(isolate); |
| 2116 ASSERT(args.length() == 3); | 2161 ASSERT(args.length() == 3); |
| 2117 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2162 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2118 Handle<Object> receiver = args.at<Object>(0); | 2163 Handle<Object> receiver = args.at<Object>(0); |
| 2119 Handle<String> key = args.at<String>(1); | 2164 Handle<String> key = args.at<String>(1); |
| 2120 ic.UpdateState(receiver, key); | 2165 ic.UpdateState(receiver, key); |
| 2121 return ic.Store(receiver, key, args.at<Object>(2)); | 2166 return ic.Store(receiver, key, args.at<Object>(2)); |
| 2122 } | 2167 } |
| 2123 | 2168 |
| 2124 | 2169 |
| 2170 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_MissFromStubFailure) { |
| 2171 HandleScope scope(isolate); |
| 2172 ASSERT(args.length() == 2); |
| 2173 KeyedCallIC ic(isolate); |
| 2174 Arguments* caller_args = reinterpret_cast<Arguments*>(args[0]); |
| 2175 Handle<Object> key = args.at<Object>(1); |
| 2176 Handle<Object> receiver((*caller_args)[0], isolate); |
| 2177 |
| 2178 ic.UpdateState(receiver, key); |
| 2179 MaybeObject* maybe_result = ic.LoadFunction(receiver, key); |
| 2180 // Result could be a function or a failure. |
| 2181 JSFunction* raw_function = NULL; |
| 2182 if (!maybe_result->To(&raw_function)) return maybe_result; |
| 2183 |
| 2184 if (raw_function->is_compiled()) return raw_function; |
| 2185 |
| 2186 Handle<JSFunction> function(raw_function, isolate); |
| 2187 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); |
| 2188 return *function; |
| 2189 } |
| 2190 |
| 2191 |
| 2125 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { | 2192 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { |
| 2126 SealHandleScope shs(isolate); | 2193 SealHandleScope shs(isolate); |
| 2127 | 2194 |
| 2128 ASSERT(args.length() == 2); | 2195 ASSERT(args.length() == 2); |
| 2129 JSArray* receiver = JSArray::cast(args[0]); | 2196 JSArray* receiver = JSArray::cast(args[0]); |
| 2130 Object* len = args[1]; | 2197 Object* len = args[1]; |
| 2131 | 2198 |
| 2132 // The generated code should filter out non-Smis before we get here. | 2199 // The generated code should filter out non-Smis before we get here. |
| 2133 ASSERT(len->IsSmi()); | 2200 ASSERT(len->IsSmi()); |
| 2134 | 2201 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2197 | 2264 |
| 2198 | 2265 |
| 2199 // Used from ic-<arch>.cc. | 2266 // Used from ic-<arch>.cc. |
| 2200 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { | 2267 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { |
| 2201 HandleScope scope(isolate); | 2268 HandleScope scope(isolate); |
| 2202 ASSERT(args.length() == 3); | 2269 ASSERT(args.length() == 3); |
| 2203 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2270 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2204 Handle<Object> receiver = args.at<Object>(0); | 2271 Handle<Object> receiver = args.at<Object>(0); |
| 2205 Handle<Object> key = args.at<Object>(1); | 2272 Handle<Object> key = args.at<Object>(1); |
| 2206 ic.UpdateState(receiver, key); | 2273 ic.UpdateState(receiver, key); |
| 2207 return ic.Store(receiver, key, args.at<Object>(2), MISS); | 2274 return ic.Store(receiver, key, args.at<Object>(2)); |
| 2208 } | 2275 } |
| 2209 | 2276 |
| 2210 | 2277 |
| 2211 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { | 2278 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { |
| 2212 HandleScope scope(isolate); | 2279 HandleScope scope(isolate); |
| 2213 ASSERT(args.length() == 3); | 2280 ASSERT(args.length() == 3); |
| 2214 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2281 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2215 Handle<Object> receiver = args.at<Object>(0); | 2282 Handle<Object> receiver = args.at<Object>(0); |
| 2216 Handle<Object> key = args.at<Object>(1); | 2283 Handle<Object> key = args.at<Object>(1); |
| 2217 ic.UpdateState(receiver, key); | 2284 ic.UpdateState(receiver, key); |
| 2218 return ic.Store(receiver, key, args.at<Object>(2), MISS); | 2285 return ic.Store(receiver, key, args.at<Object>(2)); |
| 2219 } | 2286 } |
| 2220 | 2287 |
| 2221 | 2288 |
| 2222 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { | 2289 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { |
| 2223 HandleScope scope(isolate); | 2290 HandleScope scope(isolate); |
| 2224 ASSERT(args.length() == 3); | 2291 ASSERT(args.length() == 3); |
| 2225 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2292 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2226 Handle<Object> object = args.at<Object>(0); | 2293 Handle<Object> object = args.at<Object>(0); |
| 2227 Handle<Object> key = args.at<Object>(1); | 2294 Handle<Object> key = args.at<Object>(1); |
| 2228 Handle<Object> value = args.at<Object>(2); | 2295 Handle<Object> value = args.at<Object>(2); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2253 } | 2320 } |
| 2254 | 2321 |
| 2255 | 2322 |
| 2256 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { | 2323 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { |
| 2257 HandleScope scope(isolate); | 2324 HandleScope scope(isolate); |
| 2258 ASSERT(args.length() == 3); | 2325 ASSERT(args.length() == 3); |
| 2259 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2326 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2260 Handle<Object> receiver = args.at<Object>(0); | 2327 Handle<Object> receiver = args.at<Object>(0); |
| 2261 Handle<Object> key = args.at<Object>(1); | 2328 Handle<Object> key = args.at<Object>(1); |
| 2262 ic.UpdateState(receiver, key); | 2329 ic.UpdateState(receiver, key); |
| 2263 return ic.Store(receiver, key, args.at<Object>(2), MISS_FORCE_GENERIC); | 2330 return ic.StoreForceGeneric(receiver, key, args.at<Object>(2)); |
| 2264 } | 2331 } |
| 2265 | 2332 |
| 2266 | 2333 |
| 2267 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { | 2334 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { |
| 2268 HandleScope scope(isolate); | 2335 HandleScope scope(isolate); |
| 2269 ASSERT(args.length() == 4); | 2336 ASSERT(args.length() == 4); |
| 2270 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2337 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2271 Handle<Object> value = args.at<Object>(0); | 2338 Handle<Object> value = args.at<Object>(0); |
| 2272 Handle<Map> map = args.at<Map>(1); | 2339 Handle<Map> map = args.at<Map>(1); |
| 2273 Handle<Object> key = args.at<Object>(2); | 2340 Handle<Object> key = args.at<Object>(2); |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2540 case UNIQUE_NAME: | 2607 case UNIQUE_NAME: |
| 2541 case OBJECT: | 2608 case OBJECT: |
| 2542 case GENERIC: | 2609 case GENERIC: |
| 2543 return GENERIC; | 2610 return GENERIC; |
| 2544 } | 2611 } |
| 2545 UNREACHABLE(); | 2612 UNREACHABLE(); |
| 2546 return GENERIC; // Make the compiler happy. | 2613 return GENERIC; // Make the compiler happy. |
| 2547 } | 2614 } |
| 2548 | 2615 |
| 2549 | 2616 |
| 2550 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { | 2617 Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
| 2551 HandleScope scope(isolate()); | 2618 HandleScope scope(isolate()); |
| 2552 State previous_left, previous_right, previous_state; | 2619 State previous_left, previous_right, previous_state; |
| 2553 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, | 2620 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, |
| 2554 &previous_right, &previous_state, NULL); | 2621 &previous_right, &previous_state, NULL); |
| 2555 State new_left = NewInputState(previous_left, x); | 2622 State new_left = NewInputState(previous_left, x); |
| 2556 State new_right = NewInputState(previous_right, y); | 2623 State new_right = NewInputState(previous_right, y); |
| 2557 State state = TargetState(previous_state, previous_left, previous_right, | 2624 State state = TargetState(previous_state, previous_left, previous_right, |
| 2558 HasInlinedSmiCode(address()), x, y); | 2625 HasInlinedSmiCode(address()), x, y); |
| 2559 ICCompareStub stub(op_, new_left, new_right, state); | 2626 ICCompareStub stub(op_, new_left, new_right, state); |
| 2560 if (state == KNOWN_OBJECT) { | 2627 if (state == KNOWN_OBJECT) { |
| 2561 stub.set_known_map( | 2628 stub.set_known_map( |
| 2562 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); | 2629 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); |
| 2563 } | 2630 } |
| 2564 set_target(*stub.GetCode(isolate())); | 2631 Handle<Code> new_target = stub.GetCode(isolate()); |
| 2632 set_target(*new_target); |
| 2565 | 2633 |
| 2566 #ifdef DEBUG | 2634 #ifdef DEBUG |
| 2567 if (FLAG_trace_ic) { | 2635 if (FLAG_trace_ic) { |
| 2568 PrintF("[CompareIC in "); | 2636 PrintF("[CompareIC in "); |
| 2569 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2637 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 2570 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | 2638 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |
| 2571 GetStateName(previous_left), | 2639 GetStateName(previous_left), |
| 2572 GetStateName(previous_right), | 2640 GetStateName(previous_right), |
| 2573 GetStateName(previous_state), | 2641 GetStateName(previous_state), |
| 2574 GetStateName(new_left), | 2642 GetStateName(new_left), |
| 2575 GetStateName(new_right), | 2643 GetStateName(new_right), |
| 2576 GetStateName(state), | 2644 GetStateName(state), |
| 2577 Token::Name(op_), | 2645 Token::Name(op_), |
| 2578 static_cast<void*>(*stub.GetCode(isolate()))); | 2646 static_cast<void*>(*stub.GetCode(isolate()))); |
| 2579 } | 2647 } |
| 2580 #endif | 2648 #endif |
| 2581 | 2649 |
| 2582 // Activate inlined smi code. | 2650 // Activate inlined smi code. |
| 2583 if (previous_state == UNINITIALIZED) { | 2651 if (previous_state == UNINITIALIZED) { |
| 2584 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); | 2652 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); |
| 2585 } | 2653 } |
| 2654 |
| 2655 return *new_target; |
| 2586 } | 2656 } |
| 2587 | 2657 |
| 2588 | 2658 |
| 2589 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. | 2659 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. |
| 2590 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { | 2660 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { |
| 2591 HandleScope scope(isolate); | 2661 HandleScope scope(isolate); |
| 2592 ASSERT(args.length() == 3); | 2662 ASSERT(args.length() == 3); |
| 2593 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); | 2663 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); |
| 2594 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2664 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
| 2595 return ic.raw_target(); | |
| 2596 } | 2665 } |
| 2597 | 2666 |
| 2598 | 2667 |
| 2599 void CompareNilIC::Clear(Address address, Code* target) { | 2668 void CompareNilIC::Clear(Address address, Code* target) { |
| 2600 if (IsCleared(target)) return; | 2669 if (IsCleared(target)) return; |
| 2601 Code::ExtraICState state = target->extended_extra_ic_state(); | 2670 Code::ExtraICState state = target->extended_extra_ic_state(); |
| 2602 | 2671 |
| 2603 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); | 2672 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); |
| 2604 stub.ClearState(); | 2673 stub.ClearState(); |
| 2605 | 2674 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2696 case Token::SHR: | 2765 case Token::SHR: |
| 2697 return Builtins::SHR; | 2766 return Builtins::SHR; |
| 2698 break; | 2767 break; |
| 2699 case Token::SHL: | 2768 case Token::SHL: |
| 2700 return Builtins::SHL; | 2769 return Builtins::SHL; |
| 2701 break; | 2770 break; |
| 2702 } | 2771 } |
| 2703 } | 2772 } |
| 2704 | 2773 |
| 2705 | 2774 |
| 2706 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object, | 2775 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object) { |
| 2707 Code::ExtraICState extra_ic_state) { | 2776 ToBooleanStub stub(target()->extended_extra_ic_state()); |
| 2708 ToBooleanStub stub(extra_ic_state); | |
| 2709 bool to_boolean_value = stub.UpdateStatus(object); | 2777 bool to_boolean_value = stub.UpdateStatus(object); |
| 2710 Handle<Code> code = stub.GetCode(isolate()); | 2778 Handle<Code> code = stub.GetCode(isolate()); |
| 2711 set_target(*code); | 2779 set_target(*code); |
| 2712 return Smi::FromInt(to_boolean_value ? 1 : 0); | 2780 return Smi::FromInt(to_boolean_value ? 1 : 0); |
| 2713 } | 2781 } |
| 2714 | 2782 |
| 2715 | 2783 |
| 2716 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) { | 2784 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) { |
| 2717 ASSERT(args.length() == 1); | 2785 ASSERT(args.length() == 1); |
| 2718 HandleScope scope(isolate); | 2786 HandleScope scope(isolate); |
| 2719 Handle<Object> object = args.at<Object>(0); | 2787 Handle<Object> object = args.at<Object>(0); |
| 2720 ToBooleanIC ic(isolate); | 2788 ToBooleanIC ic(isolate); |
| 2721 Code::ExtraICState extra_ic_state = ic.target()->extended_extra_ic_state(); | 2789 return ic.ToBoolean(object); |
| 2722 return ic.ToBoolean(object, extra_ic_state); | |
| 2723 } | 2790 } |
| 2724 | 2791 |
| 2725 | 2792 |
| 2726 static const Address IC_utilities[] = { | 2793 static const Address IC_utilities[] = { |
| 2727 #define ADDR(name) FUNCTION_ADDR(name), | 2794 #define ADDR(name) FUNCTION_ADDR(name), |
| 2728 IC_UTIL_LIST(ADDR) | 2795 IC_UTIL_LIST(ADDR) |
| 2729 NULL | 2796 NULL |
| 2730 #undef ADDR | 2797 #undef ADDR |
| 2731 }; | 2798 }; |
| 2732 | 2799 |
| 2733 | 2800 |
| 2734 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2801 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2735 return IC_utilities[id]; | 2802 return IC_utilities[id]; |
| 2736 } | 2803 } |
| 2737 | 2804 |
| 2738 | 2805 |
| 2739 } } // namespace v8::internal | 2806 } } // namespace v8::internal |
| OLD | NEW |