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

Side by Side Diff: src/ic.cc

Issue 110573004: Merge bleeding_edge 17696:18016. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years 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
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 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 // 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.
777 // 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,
778 // and deopting Crankshaft code. 778 // and deopting Crankshaft code.
779 if (code.is_null()) return; 779 if (code.is_null()) return;
780 780
781 Handle<JSObject> cache_object = object->IsJSObject() 781 Handle<JSObject> cache_object = object->IsJSObject()
782 ? Handle<JSObject>::cast(object) 782 ? Handle<JSObject>::cast(object)
783 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), 783 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
784 isolate()); 784 isolate());
785 785
786 PatchCache(cache_object, name, code); 786 PatchCache(handle(Type::OfCurrently(cache_object), isolate()), name, code);
787 TRACE_IC("CallIC", name); 787 TRACE_IC("CallIC", name);
788 } 788 }
789 789
790 790
791 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, 791 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object,
792 Handle<Object> key) { 792 Handle<Object> key) {
793 if (key->IsInternalizedString()) { 793 if (key->IsInternalizedString()) {
794 return CallICBase::LoadFunction(object, Handle<String>::cast(key)); 794 return CallICBase::LoadFunction(object, Handle<String>::cast(key));
795 } 795 }
796 796
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
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<Type> type,
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 TypeHandleList types;
957 CodeHandleList handlers; 975 CodeHandleList handlers;
958 976
959 int number_of_valid_maps; 977 int number_of_valid_types;
960 int handler_to_overwrite = -1; 978 int handler_to_overwrite = -1;
961 Handle<Map> new_receiver_map(receiver->map());
962 979
963 target()->FindAllMaps(&receiver_maps); 980 target()->FindAllTypes(&types);
964 int number_of_maps = receiver_maps.length(); 981 int number_of_types = types.length();
965 number_of_valid_maps = number_of_maps; 982 number_of_valid_types = number_of_types;
966 983
967 for (int i = 0; i < number_of_maps; i++) { 984 for (int i = 0; i < number_of_types; i++) {
968 Handle<Map> map = receiver_maps.at(i); 985 Handle<Type> current_type = types.at(i);
969 // Filter out deprecated maps to ensure its instances get migrated. 986 // Filter out deprecated maps to ensure their instances get migrated.
970 if (map->is_deprecated()) { 987 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) {
971 number_of_valid_maps--; 988 number_of_valid_types--;
972 // If the receiver map is already in the polymorphic IC, this indicates 989 // If the receiver type is already in the polymorphic IC, this indicates
973 // there was a prototoype chain failure. In that case, just overwrite the 990 // there was a prototoype chain failure. In that case, just overwrite the
974 // handler. 991 // handler.
975 } else if (map.is_identical_to(new_receiver_map)) { 992 } else if (type->Is(current_type)) {
976 number_of_valid_maps--; 993 ASSERT(handler_to_overwrite == -1);
994 number_of_valid_types--;
977 handler_to_overwrite = i; 995 handler_to_overwrite = i;
978 } 996 }
979 } 997 }
980 998
981 if (number_of_valid_maps >= 4) return false; 999 if (number_of_valid_types >= 4) return false;
982 if (number_of_maps == 0) return false; 1000 if (number_of_types == 0) return false;
1001 if (!target()->FindHandlers(&handlers, types.length())) return false;
983 1002
984 if (!target()->FindHandlers(&handlers, receiver_maps.length())) { 1003 number_of_valid_types++;
985 return false;
986 }
987
988 number_of_valid_maps++;
989 if (handler_to_overwrite >= 0) { 1004 if (handler_to_overwrite >= 0) {
990 handlers.Set(handler_to_overwrite, code); 1005 handlers.Set(handler_to_overwrite, code);
991 } else { 1006 } else {
992 receiver_maps.Add(new_receiver_map); 1007 types.Add(type);
993 handlers.Add(code); 1008 handlers.Add(code);
994 } 1009 }
995 1010
996 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( 1011 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
997 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode()); 1012 &types, &handlers, number_of_valid_types, name, strict_mode());
998 set_target(*ic); 1013 set_target(*ic);
999 return true; 1014 return true;
1000 } 1015 }
1001 1016
1002 1017
1003 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver, 1018 Handle<Map> IC::TypeToMap(Type* type, Isolate* isolate) {
1019 if (type->Is(Type::Number())) return isolate->factory()->heap_number_map();
1020 if (type->Is(Type::Boolean())) return isolate->factory()->oddball_map();
1021 ASSERT(type->IsClass());
1022 return type->AsClass();
1023 }
1024
1025
1026 Type* IC::MapToType(Handle<Map> map) {
1027 if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number();
1028 // The only oddballs that can be recorded in ICs are booleans.
1029 if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean();
1030 return Type::Class(map);
1031 }
1032
1033
1034 void IC::UpdateMonomorphicIC(Handle<Type> type,
1004 Handle<Code> handler, 1035 Handle<Code> handler,
1005 Handle<String> name) { 1036 Handle<String> name) {
1006 if (!handler->is_handler()) return set_target(*handler); 1037 if (!handler->is_handler()) return set_target(*handler);
1007 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( 1038 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
1008 receiver, handler, name, strict_mode()); 1039 name, type, handler, strict_mode());
1009 set_target(*ic); 1040 set_target(*ic);
1010 } 1041 }
1011 1042
1012 1043
1013 void IC::CopyICToMegamorphicCache(Handle<String> name) { 1044 void IC::CopyICToMegamorphicCache(Handle<String> name) {
1014 MapHandleList receiver_maps; 1045 TypeHandleList types;
1015 CodeHandleList handlers; 1046 CodeHandleList handlers;
1016 target()->FindAllMaps(&receiver_maps); 1047 target()->FindAllTypes(&types);
1017 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return; 1048 if (!target()->FindHandlers(&handlers, types.length())) return;
1018 for (int i = 0; i < receiver_maps.length(); i++) { 1049 for (int i = 0; i < types.length(); i++) {
1019 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); 1050 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
1020 } 1051 }
1021 } 1052 }
1022 1053
1023 1054
1024 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { 1055 bool IC::IsTransitionOfMonomorphicTarget(Type* type) {
1056 if (!type->IsClass()) return false;
1057 Map* receiver_map = *type->AsClass();
1025 Map* current_map = target()->FindFirstMap(); 1058 Map* current_map = target()->FindFirstMap();
1026 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); 1059 ElementsKind receiver_elements_kind = receiver_map->elements_kind();
1027 bool more_general_transition = 1060 bool more_general_transition =
1028 IsMoreGeneralElementsKindTransition( 1061 IsMoreGeneralElementsKindTransition(
1029 current_map->elements_kind(), receiver_elements_kind); 1062 current_map->elements_kind(), receiver_elements_kind);
1030 Map* transitioned_map = more_general_transition 1063 Map* transitioned_map = more_general_transition
1031 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) 1064 ? current_map->LookupElementsTransitionMap(receiver_elements_kind)
1032 : NULL; 1065 : NULL;
1033 1066
1034 return transitioned_map == receiver_map; 1067 return transitioned_map == receiver_map;
1035 } 1068 }
1036 1069
1037 1070
1038 void IC::PatchCache(Handle<HeapObject> receiver, 1071 void IC::PatchCache(Handle<Type> type,
1039 Handle<String> name, 1072 Handle<String> name,
1040 Handle<Code> code) { 1073 Handle<Code> code) {
1041 switch (state()) { 1074 switch (state()) {
1042 case UNINITIALIZED: 1075 case UNINITIALIZED:
1043 case PREMONOMORPHIC: 1076 case PREMONOMORPHIC:
1044 case MONOMORPHIC_PROTOTYPE_FAILURE: 1077 case MONOMORPHIC_PROTOTYPE_FAILURE:
1045 UpdateMonomorphicIC(receiver, code, name); 1078 UpdateMonomorphicIC(type, code, name);
1046 break; 1079 break;
1047 case MONOMORPHIC: 1080 case MONOMORPHIC: {
1048 // For now, call stubs are allowed to rewrite to the same stub. This 1081 // 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. 1082 // happens e.g., when the field does not contain a function.
1050 ASSERT(target()->is_call_stub() || 1083 ASSERT(target()->is_call_stub() ||
1051 target()->is_keyed_call_stub() || 1084 target()->is_keyed_call_stub() ||
1052 !target().is_identical_to(code)); 1085 !target().is_identical_to(code));
1053 if (!target()->is_keyed_stub()) { 1086 Code* old_handler = target()->FindFirstHandler();
1054 bool is_same_handler = false; 1087 if (old_handler == *code && IsTransitionOfMonomorphicTarget(*type)) {
1055 Code* old_handler = target()->FindFirstHandler(); 1088 UpdateMonomorphicIC(type, code, name);
1056 is_same_handler = old_handler == *code; 1089 break;
1057
1058 if (is_same_handler &&
1059 IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
1060 UpdateMonomorphicIC(receiver, code, name);
1061 break;
1062 }
1063 } 1090 }
1064 // Fall through. 1091 // Fall through.
1092 }
1065 case POLYMORPHIC: 1093 case POLYMORPHIC:
1066 if (!target()->is_keyed_stub()) { 1094 if (!target()->is_keyed_stub()) {
1067 if (UpdatePolymorphicIC(receiver, name, code)) break; 1095 if (UpdatePolymorphicIC(type, name, code)) break;
1068 CopyICToMegamorphicCache(name); 1096 CopyICToMegamorphicCache(name);
1069 } 1097 }
1070 set_target(*megamorphic_stub()); 1098 set_target(*megamorphic_stub());
1071 // Fall through. 1099 // Fall through.
1072 case MEGAMORPHIC: 1100 case MEGAMORPHIC:
1073 UpdateMegamorphicCache(receiver->map(), *name, *code); 1101 UpdateMegamorphicCache(*type, *name, *code);
1074 break; 1102 break;
1075 case DEBUG_STUB: 1103 case DEBUG_STUB:
1076 break; 1104 break;
1077 case GENERIC: 1105 case GENERIC:
1078 UNREACHABLE(); 1106 UNREACHABLE();
1079 break; 1107 break;
1080 } 1108 }
1081 } 1109 }
1082 1110
1083 1111
1084 Handle<Code> LoadIC::SimpleFieldLoad(int offset, 1112 Handle<Code> LoadIC::SimpleFieldLoad(int offset,
1085 bool inobject, 1113 bool inobject,
1086 Representation representation) { 1114 Representation representation) {
1087 if (kind() == Code::LOAD_IC) { 1115 if (kind() == Code::LOAD_IC) {
1088 LoadFieldStub stub(inobject, offset, representation); 1116 LoadFieldStub stub(inobject, offset, representation);
1089 return stub.GetCode(isolate()); 1117 return stub.GetCode(isolate());
1090 } else { 1118 } else {
1091 KeyedLoadFieldStub stub(inobject, offset, representation); 1119 KeyedLoadFieldStub stub(inobject, offset, representation);
1092 return stub.GetCode(isolate()); 1120 return stub.GetCode(isolate());
1093 } 1121 }
1094 } 1122 }
1095 1123
1096 1124
1097 void LoadIC::UpdateCaches(LookupResult* lookup, 1125 void LoadIC::UpdateCaches(LookupResult* lookup,
1098 Handle<Object> object, 1126 Handle<Object> object,
1099 Handle<String> name) { 1127 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) { 1128 if (state() == UNINITIALIZED) {
1108 // This is the first time we execute this inline cache. 1129 // This is the first time we execute this inline cache.
1109 // Set the target to the pre monomorphic stub to delay 1130 // Set the target to the pre monomorphic stub to delay
1110 // setting the monomorphic state. 1131 // setting the monomorphic state.
1111 set_target(*pre_monomorphic_stub()); 1132 set_target(*pre_monomorphic_stub());
1112 TRACE_IC("LoadIC", name); 1133 TRACE_IC("LoadIC", name);
1113 return; 1134 return;
1114 } else if (!lookup->IsCacheable()) { 1135 }
1136
1137 Handle<Code> code;
1138 if (!lookup->IsCacheable()) {
1115 // Bail out if the result is not cacheable. 1139 // Bail out if the result is not cacheable.
1116 code = slow_stub(); 1140 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()) { 1141 } else if (!lookup->IsProperty()) {
1126 code = kind() == Code::LOAD_IC 1142 if (kind() == Code::LOAD_IC) {
1127 ? isolate()->stub_cache()->ComputeLoadNonexistent( 1143 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object);
1128 name, Handle<JSObject>::cast(receiver)) 1144 } else {
1129 : slow_stub(); 1145 code = slow_stub();
1146 }
1130 } else { 1147 } else {
1131 code = ComputeHandler(lookup, Handle<JSObject>::cast(receiver), name); 1148 code = ComputeHandler(lookup, object, name);
1132 } 1149 }
1133 1150
1134 PatchCache(receiver, name, code); 1151 PatchCache(handle(Type::OfCurrently(object), isolate()), name, code);
1135 TRACE_IC("LoadIC", name); 1152 TRACE_IC("LoadIC", name);
1136 } 1153 }
1137 1154
1138 1155
1139 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { 1156 void IC::UpdateMegamorphicCache(Type* type, Name* name, Code* code) {
1140 // Cache code holding map should be consistent with 1157 // Cache code holding map should be consistent with
1141 // GenerateMonomorphicCacheProbe. 1158 // GenerateMonomorphicCacheProbe.
1159 Map* map = *TypeToMap(type, isolate());
1142 isolate()->stub_cache()->Set(name, map, code); 1160 isolate()->stub_cache()->Set(name, map, code);
1143 } 1161 }
1144 1162
1145 1163
1146 Handle<Code> IC::ComputeHandler(LookupResult* lookup, 1164 Handle<Code> IC::ComputeHandler(LookupResult* lookup,
1147 Handle<JSObject> receiver, 1165 Handle<Object> object,
1148 Handle<String> name, 1166 Handle<String> name,
1149 Handle<Object> value) { 1167 Handle<Object> value) {
1168 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object);
1169 Handle<HeapObject> stub_holder(GetCodeCacheHolder(
1170 isolate(), *object, cache_holder));
1171
1150 Handle<Code> code = isolate()->stub_cache()->FindHandler( 1172 Handle<Code> code = isolate()->stub_cache()->FindHandler(
1151 name, receiver, kind()); 1173 name, stub_holder, kind(), cache_holder, strict_mode());
1152 if (!code.is_null()) return code; 1174 if (!code.is_null()) return code;
1153 1175
1154 code = CompileHandler(lookup, receiver, name, value); 1176 code = CompileHandler(lookup, object, name, value, cache_holder);
1155 ASSERT(code->is_handler()); 1177 ASSERT(code->is_handler());
1156 1178
1157 if (code->type() != Code::NORMAL) { 1179 if (code->type() != Code::NORMAL) {
1158 HeapObject::UpdateMapCodeCache(receiver, name, code); 1180 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
1159 } 1181 }
1160 1182
1161 return code; 1183 return code;
1162 } 1184 }
1163 1185
1164 1186
1165 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, 1187 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
1166 Handle<JSObject> receiver, 1188 Handle<Object> object,
1167 Handle<String> name, 1189 Handle<String> name,
1168 Handle<Object> unused) { 1190 Handle<Object> unused,
1191 InlineCacheHolderFlag cache_holder) {
1192 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
1193 int length_index = String::kLengthOffset / kPointerSize;
1194 return SimpleFieldLoad(length_index);
1195 }
1196
1169 Handle<JSObject> holder(lookup->holder()); 1197 Handle<JSObject> holder(lookup->holder());
1170 LoadStubCompiler compiler(isolate(), kind()); 1198 LoadStubCompiler compiler(isolate(), cache_holder, kind());
1171 1199
1172 switch (lookup->type()) { 1200 switch (lookup->type()) {
1173 case FIELD: { 1201 case FIELD: {
1174 PropertyIndex field = lookup->GetFieldIndex(); 1202 PropertyIndex field = lookup->GetFieldIndex();
1175 if (receiver.is_identical_to(holder)) { 1203 if (object.is_identical_to(holder)) {
1176 return SimpleFieldLoad(field.translate(holder), 1204 return SimpleFieldLoad(field.translate(holder),
1177 field.is_inobject(holder), 1205 field.is_inobject(holder),
1178 lookup->representation()); 1206 lookup->representation());
1179 } 1207 }
1180 return compiler.CompileLoadField( 1208 return compiler.CompileLoadField(
1181 receiver, holder, name, field, lookup->representation()); 1209 object, holder, name, field, lookup->representation());
1182 } 1210 }
1183 case CONSTANT: { 1211 case CONSTANT: {
1184 Handle<Object> constant(lookup->GetConstant(), isolate()); 1212 Handle<Object> constant(lookup->GetConstant(), isolate());
1185 // TODO(2803): Don't compute a stub for cons strings because they cannot 1213 // TODO(2803): Don't compute a stub for cons strings because they cannot
1186 // be embedded into code. 1214 // be embedded into code.
1187 if (constant->IsConsString()) break; 1215 if (constant->IsConsString()) break;
1188 return compiler.CompileLoadConstant(receiver, holder, name, constant); 1216 return compiler.CompileLoadConstant(object, holder, name, constant);
1189 } 1217 }
1190 case NORMAL: 1218 case NORMAL:
1191 if (kind() != Code::LOAD_IC) break; 1219 if (kind() != Code::LOAD_IC) break;
1192 if (holder->IsGlobalObject()) { 1220 if (holder->IsGlobalObject()) {
1193 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); 1221 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1194 Handle<PropertyCell> cell( 1222 Handle<PropertyCell> cell(
1195 global->GetPropertyCell(lookup), isolate()); 1223 global->GetPropertyCell(lookup), isolate());
1196 Handle<Code> code = compiler.CompileLoadGlobal( 1224 Handle<Code> code = compiler.CompileLoadGlobal(
1197 receiver, global, cell, name, lookup->IsDontDelete()); 1225 object, global, cell, name, lookup->IsDontDelete());
1198 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. 1226 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1199 HeapObject::UpdateMapCodeCache(receiver, name, code); 1227 Handle<HeapObject> stub_holder(GetCodeCacheHolder(
1228 isolate(), *object, cache_holder));
1229 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
1200 return code; 1230 return code;
1201 } 1231 }
1202 // There is only one shared stub for loading normalized 1232 // There is only one shared stub for loading normalized
1203 // properties. It does not traverse the prototype chain, so the 1233 // properties. It does not traverse the prototype chain, so the
1204 // property must be found in the receiver for the stub to be 1234 // property must be found in the object for the stub to be
1205 // applicable. 1235 // applicable.
1206 if (!holder.is_identical_to(receiver)) break; 1236 if (!object.is_identical_to(holder)) break;
1207 return isolate()->builtins()->LoadIC_Normal(); 1237 return isolate()->builtins()->LoadIC_Normal();
1208 case CALLBACKS: { 1238 case CALLBACKS: {
1209 // Use simple field loads for some well-known callback properties. 1239 // Use simple field loads for some well-known callback properties.
1210 int object_offset; 1240 if (object->IsJSObject()) {
1211 Handle<Map> map(receiver->map()); 1241 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1212 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { 1242 Handle<Map> map(receiver->map());
1213 PropertyIndex index = 1243 int object_offset;
1214 PropertyIndex::NewHeaderIndex(object_offset / kPointerSize); 1244 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
1215 return compiler.CompileLoadField( 1245 return SimpleFieldLoad(object_offset / kPointerSize);
1216 receiver, receiver, name, index, Representation::Tagged()); 1246 }
1217 } 1247 }
1218 1248
1219 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1249 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1220 if (callback->IsExecutableAccessorInfo()) { 1250 if (callback->IsExecutableAccessorInfo()) {
1221 Handle<ExecutableAccessorInfo> info = 1251 Handle<ExecutableAccessorInfo> info =
1222 Handle<ExecutableAccessorInfo>::cast(callback); 1252 Handle<ExecutableAccessorInfo>::cast(callback);
1223 if (v8::ToCData<Address>(info->getter()) == 0) break; 1253 if (v8::ToCData<Address>(info->getter()) == 0) break;
1224 if (!info->IsCompatibleReceiver(*receiver)) break; 1254 if (!info->IsCompatibleReceiver(*object)) break;
1225 return compiler.CompileLoadCallback(receiver, holder, name, info); 1255 return compiler.CompileLoadCallback(object, holder, name, info);
1226 } else if (callback->IsAccessorPair()) { 1256 } else if (callback->IsAccessorPair()) {
1227 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), 1257 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
1228 isolate()); 1258 isolate());
1229 if (!getter->IsJSFunction()) break; 1259 if (!getter->IsJSFunction()) break;
1230 if (holder->IsGlobalObject()) break; 1260 if (holder->IsGlobalObject()) break;
1231 if (!holder->HasFastProperties()) break; 1261 if (!holder->HasFastProperties()) break;
1232 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); 1262 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1263 if (!object->IsJSObject() &&
1264 !function->IsBuiltin() &&
1265 function->shared()->is_classic_mode()) {
1266 // Calling non-strict non-builtins with a value as the receiver
1267 // requires boxing.
1268 break;
1269 }
1233 CallOptimization call_optimization(function); 1270 CallOptimization call_optimization(function);
1234 if (call_optimization.is_simple_api_call() && 1271 if (call_optimization.is_simple_api_call() &&
1235 call_optimization.IsCompatibleReceiver(*receiver)) { 1272 call_optimization.IsCompatibleReceiver(*object)) {
1236 return compiler.CompileLoadCallback( 1273 return compiler.CompileLoadCallback(
1237 receiver, holder, name, call_optimization); 1274 object, holder, name, call_optimization);
1238 } 1275 }
1239 return compiler.CompileLoadViaGetter(receiver, holder, name, function); 1276 return compiler.CompileLoadViaGetter(object, holder, name, function);
1240 } 1277 }
1241 // TODO(dcarney): Handle correctly. 1278 // TODO(dcarney): Handle correctly.
1242 if (callback->IsDeclaredAccessorInfo()) break; 1279 if (callback->IsDeclaredAccessorInfo()) break;
1243 ASSERT(callback->IsForeign()); 1280 ASSERT(callback->IsForeign());
1244 // No IC support for old-style native accessors. 1281 // No IC support for old-style native accessors.
1245 break; 1282 break;
1246 } 1283 }
1247 case INTERCEPTOR: 1284 case INTERCEPTOR:
1248 ASSERT(HasInterceptorGetter(*holder)); 1285 ASSERT(HasInterceptorGetter(*holder));
1249 return compiler.CompileLoadInterceptor(receiver, holder, name); 1286 return compiler.CompileLoadInterceptor(object, holder, name);
1250 default: 1287 default:
1251 break; 1288 break;
1252 } 1289 }
1253 1290
1254 return slow_stub(); 1291 return slow_stub();
1255 } 1292 }
1256 1293
1257 1294
1258 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { 1295 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1259 // This helper implements a few common fast cases for converting 1296 // This helper implements a few common fast cases for converting
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { 1368 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1332 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); 1369 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded");
1333 return generic_stub(); 1370 return generic_stub();
1334 } 1371 }
1335 1372
1336 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( 1373 return isolate()->stub_cache()->ComputeLoadElementPolymorphic(
1337 &target_receiver_maps); 1374 &target_receiver_maps);
1338 } 1375 }
1339 1376
1340 1377
1341 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, 1378 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, Handle<Object> key) {
1342 Handle<Object> key,
1343 ICMissMode miss_mode) {
1344 if (MigrateDeprecated(object)) { 1379 if (MigrateDeprecated(object)) {
1345 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); 1380 return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1346 } 1381 }
1347 1382
1348 MaybeObject* maybe_object = NULL; 1383 MaybeObject* maybe_object = NULL;
1349 Handle<Code> stub = generic_stub(); 1384 Handle<Code> stub = generic_stub();
1350 1385
1351 // Check for values that can be converted into an internalized string directly 1386 // Check for values that can be converted into an internalized string directly
1352 // or is representable as a smi. 1387 // or is representable as a smi.
1353 key = TryConvertKey(key, isolate()); 1388 key = TryConvertKey(key, isolate());
1354 1389
1355 if (key->IsInternalizedString()) { 1390 if (key->IsInternalizedString()) {
1356 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); 1391 maybe_object = LoadIC::Load(object, Handle<String>::cast(key));
1357 if (maybe_object->IsFailure()) return maybe_object; 1392 if (maybe_object->IsFailure()) return maybe_object;
1358 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { 1393 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
1359 ASSERT(!object->IsJSGlobalProxy()); 1394 ASSERT(!object->IsJSGlobalProxy());
1360 if (miss_mode != MISS_FORCE_GENERIC) { 1395 if (object->IsString() && key->IsNumber()) {
1361 if (object->IsString() && key->IsNumber()) { 1396 if (state() == UNINITIALIZED) stub = string_stub();
1362 if (state() == UNINITIALIZED) stub = string_stub(); 1397 } else if (object->IsJSObject()) {
1363 } else if (object->IsJSObject()) { 1398 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1364 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1399 if (receiver->elements()->map() ==
1365 if (receiver->elements()->map() == 1400 isolate()->heap()->non_strict_arguments_elements_map()) {
1366 isolate()->heap()->non_strict_arguments_elements_map()) { 1401 stub = non_strict_arguments_stub();
1367 stub = non_strict_arguments_stub(); 1402 } else if (receiver->HasIndexedInterceptor()) {
1368 } else if (receiver->HasIndexedInterceptor()) { 1403 stub = indexed_interceptor_stub();
1369 stub = indexed_interceptor_stub(); 1404 } else if (!key->ToSmi()->IsFailure() &&
1370 } else if (!key->ToSmi()->IsFailure() && 1405 (!target().is_identical_to(non_strict_arguments_stub()))) {
1371 (!target().is_identical_to(non_strict_arguments_stub()))) { 1406 stub = LoadElementStub(receiver);
1372 stub = LoadElementStub(receiver);
1373 }
1374 } 1407 }
1375 } 1408 }
1376 } 1409 }
1377 1410
1378 if (!is_target_set()) { 1411 if (!is_target_set()) {
1379 if (*stub == *generic_stub()) { 1412 if (*stub == *generic_stub()) {
1380 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); 1413 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
1381 } 1414 }
1382 ASSERT(!stub.is_null()); 1415 ASSERT(!stub.is_null());
1383 set_target(*stub); 1416 set_target(*stub);
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 Handle<String> name, 1602 Handle<String> name,
1570 Handle<Object> value) { 1603 Handle<Object> value) {
1571 ASSERT(!receiver->IsJSGlobalProxy()); 1604 ASSERT(!receiver->IsJSGlobalProxy());
1572 ASSERT(lookup->IsFound()); 1605 ASSERT(lookup->IsFound());
1573 1606
1574 // These are not cacheable, so we never see such LookupResults here. 1607 // These are not cacheable, so we never see such LookupResults here.
1575 ASSERT(!lookup->IsHandler()); 1608 ASSERT(!lookup->IsHandler());
1576 1609
1577 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); 1610 Handle<Code> code = ComputeHandler(lookup, receiver, name, value);
1578 1611
1579 PatchCache(receiver, name, code); 1612 PatchCache(handle(Type::OfCurrently(receiver), isolate()), name, code);
1580 TRACE_IC("StoreIC", name); 1613 TRACE_IC("StoreIC", name);
1581 } 1614 }
1582 1615
1583 1616
1584 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, 1617 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
1585 Handle<JSObject> receiver, 1618 Handle<Object> object,
1586 Handle<String> name, 1619 Handle<String> name,
1587 Handle<Object> value) { 1620 Handle<Object> value,
1621 InlineCacheHolderFlag cache_holder) {
1622 ASSERT(cache_holder == OWN_MAP);
1623 // This is currently guaranteed by checks in StoreIC::Store.
1624 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1625
1588 Handle<JSObject> holder(lookup->holder()); 1626 Handle<JSObject> holder(lookup->holder());
1589 StoreStubCompiler compiler(isolate(), strict_mode(), kind()); 1627 StoreStubCompiler compiler(isolate(), strict_mode(), kind());
1590 switch (lookup->type()) { 1628 switch (lookup->type()) {
1591 case FIELD: 1629 case FIELD:
1592 return compiler.CompileStoreField(receiver, lookup, name); 1630 return compiler.CompileStoreField(receiver, lookup, name);
1593 case TRANSITION: { 1631 case TRANSITION: {
1594 // Explicitly pass in the receiver map since LookupForWrite may have 1632 // Explicitly pass in the receiver map since LookupForWrite may have
1595 // stored something else than the receiver in the holder. 1633 // stored something else than the receiver in the holder.
1596 Handle<Map> transition( 1634 Handle<Map> transition(
1597 lookup->GetTransitionTarget(receiver->map()), isolate()); 1635 lookup->GetTransitionTarget(receiver->map()), isolate());
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1710 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); 1748 Code::GetKeyedAccessStoreMode(target()->extra_ic_state());
1711 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); 1749 Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1712 if (state() == MONOMORPHIC) { 1750 if (state() == MONOMORPHIC) {
1713 // If the "old" and "new" maps are in the same elements map family, stay 1751 // If the "old" and "new" maps are in the same elements map family, stay
1714 // MONOMORPHIC and use the map for the most generic ElementsKind. 1752 // MONOMORPHIC and use the map for the most generic ElementsKind.
1715 Handle<Map> transitioned_receiver_map = receiver_map; 1753 Handle<Map> transitioned_receiver_map = receiver_map;
1716 if (IsTransitionStoreMode(store_mode)) { 1754 if (IsTransitionStoreMode(store_mode)) {
1717 transitioned_receiver_map = 1755 transitioned_receiver_map =
1718 ComputeTransitionedMap(receiver, store_mode); 1756 ComputeTransitionedMap(receiver, store_mode);
1719 } 1757 }
1720 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { 1758 if (IsTransitionOfMonomorphicTarget(MapToType(transitioned_receiver_map))) {
1721 // Element family is the same, use the "worst" case map. 1759 // Element family is the same, use the "worst" case map.
1722 store_mode = GetNonTransitioningStoreMode(store_mode); 1760 store_mode = GetNonTransitioningStoreMode(store_mode);
1723 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1761 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1724 transitioned_receiver_map, strict_mode(), store_mode); 1762 transitioned_receiver_map, strict_mode(), store_mode);
1725 } else if (*previous_receiver_map == receiver->map() && 1763 } else if (*previous_receiver_map == receiver->map() &&
1726 old_store_mode == STANDARD_STORE && 1764 old_store_mode == STANDARD_STORE &&
1727 (IsGrowStoreMode(store_mode) || 1765 (IsGrowStoreMode(store_mode) ||
1728 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || 1766 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1729 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { 1767 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1730 // A "normal" IC that handles stores can switch to a version that can 1768 // A "normal" IC that handles stores can switch to a version that can
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1910 return STORE_NO_TRANSITION_HANDLE_COW; 1948 return STORE_NO_TRANSITION_HANDLE_COW;
1911 } else { 1949 } else {
1912 return STANDARD_STORE; 1950 return STANDARD_STORE;
1913 } 1951 }
1914 } 1952 }
1915 } 1953 }
1916 1954
1917 1955
1918 MaybeObject* KeyedStoreIC::Store(Handle<Object> object, 1956 MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
1919 Handle<Object> key, 1957 Handle<Object> key,
1920 Handle<Object> value, 1958 Handle<Object> value) {
1921 ICMissMode miss_mode) {
1922 if (MigrateDeprecated(object)) { 1959 if (MigrateDeprecated(object)) {
1923 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, 1960 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object,
1924 key, 1961 key,
1925 value, 1962 value,
1926 NONE, 1963 NONE,
1927 strict_mode()); 1964 strict_mode());
1928 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1965 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1929 return *result; 1966 return *result;
1930 } 1967 }
1931 1968
(...skipping 18 matching lines...) Expand all
1950 // Don't use ICs for maps of the objects in Array's prototype chain. We 1987 // 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 1988 // expect to be able to trap element sets to objects with those maps in
1952 // the runtime to enable optimization of element hole access. 1989 // the runtime to enable optimization of element hole access.
1953 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); 1990 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
1954 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; 1991 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false;
1955 } 1992 }
1956 1993
1957 if (use_ic) { 1994 if (use_ic) {
1958 ASSERT(!object->IsJSGlobalProxy()); 1995 ASSERT(!object->IsJSGlobalProxy());
1959 1996
1960 if (miss_mode != MISS_FORCE_GENERIC) { 1997 if (object->IsJSObject()) {
1961 if (object->IsJSObject()) { 1998 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1962 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1999 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure();
1963 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); 2000 if (receiver->elements()->map() ==
1964 if (receiver->elements()->map() == 2001 isolate()->heap()->non_strict_arguments_elements_map()) {
1965 isolate()->heap()->non_strict_arguments_elements_map()) { 2002 stub = non_strict_arguments_stub();
1966 stub = non_strict_arguments_stub(); 2003 } else if (key_is_smi_like &&
1967 } else if (key_is_smi_like && 2004 !(target().is_identical_to(non_strict_arguments_stub()))) {
1968 !(target().is_identical_to(non_strict_arguments_stub()))) { 2005 // 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 2006 // prototype chain does have dictionary elements. This ensures that
1970 // prototype chain does have dictionary elements. This ensures that 2007 // other non-dictionary receivers in the polymorphic case benefit
1971 // other non-dictionary receivers in the polymorphic case benefit 2008 // from fast path keyed stores.
1972 // from fast path keyed stores. 2009 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) {
1973 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { 2010 KeyedAccessStoreMode store_mode =
1974 KeyedAccessStoreMode store_mode = 2011 GetStoreMode(receiver, key, value);
1975 GetStoreMode(receiver, key, value); 2012 stub = StoreElementStub(receiver, store_mode);
1976 stub = StoreElementStub(receiver, store_mode);
1977 }
1978 } 2013 }
1979 } 2014 }
1980 } 2015 }
1981 } 2016 }
1982 } 2017 }
1983 2018
1984 if (!is_target_set()) { 2019 if (!is_target_set()) {
1985 if (*stub == *generic_stub()) { 2020 if (*stub == *generic_stub()) {
1986 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); 2021 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
1987 } 2022 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2066 2101
2067 2102
2068 // Used from ic-<arch>.cc 2103 // Used from ic-<arch>.cc
2069 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { 2104 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
2070 HandleScope scope(isolate); 2105 HandleScope scope(isolate);
2071 ASSERT(args.length() == 2); 2106 ASSERT(args.length() == 2);
2072 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); 2107 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2073 Handle<Object> receiver = args.at<Object>(0); 2108 Handle<Object> receiver = args.at<Object>(0);
2074 Handle<Object> key = args.at<Object>(1); 2109 Handle<Object> key = args.at<Object>(1);
2075 ic.UpdateState(receiver, key); 2110 ic.UpdateState(receiver, key);
2076 return ic.Load(receiver, key, MISS); 2111 return ic.Load(receiver, key);
2077 } 2112 }
2078 2113
2079 2114
2080 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { 2115 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) {
2081 HandleScope scope(isolate); 2116 HandleScope scope(isolate);
2082 ASSERT(args.length() == 2); 2117 ASSERT(args.length() == 2);
2083 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); 2118 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
2084 Handle<Object> receiver = args.at<Object>(0); 2119 Handle<Object> receiver = args.at<Object>(0);
2085 Handle<Object> key = args.at<Object>(1); 2120 Handle<Object> key = args.at<Object>(1);
2086 ic.UpdateState(receiver, key); 2121 ic.UpdateState(receiver, key);
2087 return ic.Load(receiver, key, MISS); 2122 return ic.Load(receiver, key);
2088 } 2123 }
2089 2124
2090 2125
2091 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2092 HandleScope scope(isolate);
2093 ASSERT(args.length() == 2);
2094 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2095 Handle<Object> receiver = args.at<Object>(0);
2096 Handle<Object> key = args.at<Object>(1);
2097 ic.UpdateState(receiver, key);
2098 return ic.Load(receiver, key, MISS_FORCE_GENERIC);
2099 }
2100
2101
2102 // Used from ic-<arch>.cc. 2126 // Used from ic-<arch>.cc.
2103 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { 2127 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
2104 HandleScope scope(isolate); 2128 HandleScope scope(isolate);
2105 ASSERT(args.length() == 3); 2129 ASSERT(args.length() == 3);
2106 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2130 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2107 Handle<Object> receiver = args.at<Object>(0); 2131 Handle<Object> receiver = args.at<Object>(0);
2108 Handle<String> key = args.at<String>(1); 2132 Handle<String> key = args.at<String>(1);
2109 ic.UpdateState(receiver, key); 2133 ic.UpdateState(receiver, key);
2110 return ic.Store(receiver, key, args.at<Object>(2)); 2134 return ic.Store(receiver, key, args.at<Object>(2));
2111 } 2135 }
2112 2136
2113 2137
2114 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { 2138 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) {
2115 HandleScope scope(isolate); 2139 HandleScope scope(isolate);
2116 ASSERT(args.length() == 3); 2140 ASSERT(args.length() == 3);
2117 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2141 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2118 Handle<Object> receiver = args.at<Object>(0); 2142 Handle<Object> receiver = args.at<Object>(0);
2119 Handle<String> key = args.at<String>(1); 2143 Handle<String> key = args.at<String>(1);
2120 ic.UpdateState(receiver, key); 2144 ic.UpdateState(receiver, key);
2121 return ic.Store(receiver, key, args.at<Object>(2)); 2145 return ic.Store(receiver, key, args.at<Object>(2));
2122 } 2146 }
2123 2147
2124 2148
2149 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_MissFromStubFailure) {
2150 HandleScope scope(isolate);
2151 ASSERT(args.length() == 2);
2152 KeyedCallIC ic(isolate);
2153 Arguments* caller_args = reinterpret_cast<Arguments*>(args[0]);
2154 Handle<Object> key = args.at<Object>(1);
2155 Handle<Object> receiver((*caller_args)[0], isolate);
2156
2157 ic.UpdateState(receiver, key);
2158 MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2159 // Result could be a function or a failure.
2160 JSFunction* raw_function = NULL;
2161 if (!maybe_result->To(&raw_function)) return maybe_result;
2162
2163 if (raw_function->is_compiled()) return raw_function;
2164
2165 Handle<JSFunction> function(raw_function, isolate);
2166 JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
2167 return *function;
2168 }
2169
2170
2125 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { 2171 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
2126 SealHandleScope shs(isolate); 2172 SealHandleScope shs(isolate);
2127 2173
2128 ASSERT(args.length() == 2); 2174 ASSERT(args.length() == 2);
2129 JSArray* receiver = JSArray::cast(args[0]); 2175 JSArray* receiver = JSArray::cast(args[0]);
2130 Object* len = args[1]; 2176 Object* len = args[1];
2131 2177
2132 // The generated code should filter out non-Smis before we get here. 2178 // The generated code should filter out non-Smis before we get here.
2133 ASSERT(len->IsSmi()); 2179 ASSERT(len->IsSmi());
2134 2180
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2197 2243
2198 2244
2199 // Used from ic-<arch>.cc. 2245 // Used from ic-<arch>.cc.
2200 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { 2246 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
2201 HandleScope scope(isolate); 2247 HandleScope scope(isolate);
2202 ASSERT(args.length() == 3); 2248 ASSERT(args.length() == 3);
2203 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2249 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2204 Handle<Object> receiver = args.at<Object>(0); 2250 Handle<Object> receiver = args.at<Object>(0);
2205 Handle<Object> key = args.at<Object>(1); 2251 Handle<Object> key = args.at<Object>(1);
2206 ic.UpdateState(receiver, key); 2252 ic.UpdateState(receiver, key);
2207 return ic.Store(receiver, key, args.at<Object>(2), MISS); 2253 return ic.Store(receiver, key, args.at<Object>(2));
2208 } 2254 }
2209 2255
2210 2256
2211 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { 2257 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
2212 HandleScope scope(isolate); 2258 HandleScope scope(isolate);
2213 ASSERT(args.length() == 3); 2259 ASSERT(args.length() == 3);
2214 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2260 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2215 Handle<Object> receiver = args.at<Object>(0); 2261 Handle<Object> receiver = args.at<Object>(0);
2216 Handle<Object> key = args.at<Object>(1); 2262 Handle<Object> key = args.at<Object>(1);
2217 ic.UpdateState(receiver, key); 2263 ic.UpdateState(receiver, key);
2218 return ic.Store(receiver, key, args.at<Object>(2), MISS); 2264 return ic.Store(receiver, key, args.at<Object>(2));
2219 } 2265 }
2220 2266
2221 2267
2222 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { 2268 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) {
2223 HandleScope scope(isolate); 2269 HandleScope scope(isolate);
2224 ASSERT(args.length() == 3); 2270 ASSERT(args.length() == 3);
2225 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2271 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2226 Handle<Object> object = args.at<Object>(0); 2272 Handle<Object> object = args.at<Object>(0);
2227 Handle<Object> key = args.at<Object>(1); 2273 Handle<Object> key = args.at<Object>(1);
2228 Handle<Object> value = args.at<Object>(2); 2274 Handle<Object> value = args.at<Object>(2);
(...skipping 17 matching lines...) Expand all
2246 StrictModeFlag strict_mode = ic.strict_mode(); 2292 StrictModeFlag strict_mode = ic.strict_mode();
2247 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, 2293 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
2248 value, 2294 value,
2249 NONE, 2295 NONE,
2250 strict_mode); 2296 strict_mode);
2251 RETURN_IF_EMPTY_HANDLE(isolate, result); 2297 RETURN_IF_EMPTY_HANDLE(isolate, result);
2252 return *result; 2298 return *result;
2253 } 2299 }
2254 2300
2255 2301
2256 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2257 HandleScope scope(isolate);
2258 ASSERT(args.length() == 3);
2259 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2260 Handle<Object> receiver = args.at<Object>(0);
2261 Handle<Object> key = args.at<Object>(1);
2262 ic.UpdateState(receiver, key);
2263 return ic.Store(receiver, key, args.at<Object>(2), MISS_FORCE_GENERIC);
2264 }
2265
2266
2267 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { 2302 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
2268 HandleScope scope(isolate); 2303 HandleScope scope(isolate);
2269 ASSERT(args.length() == 4); 2304 ASSERT(args.length() == 4);
2270 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2305 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2271 Handle<Object> value = args.at<Object>(0); 2306 Handle<Object> value = args.at<Object>(0);
2272 Handle<Map> map = args.at<Map>(1); 2307 Handle<Map> map = args.at<Map>(1);
2273 Handle<Object> key = args.at<Object>(2); 2308 Handle<Object> key = args.at<Object>(2);
2274 Handle<Object> object = args.at<Object>(3); 2309 Handle<Object> object = args.at<Object>(3);
2275 StrictModeFlag strict_mode = ic.strict_mode(); 2310 StrictModeFlag strict_mode = ic.strict_mode();
2276 if (object->IsJSObject()) { 2311 if (object->IsJSObject()) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
2540 case UNIQUE_NAME: 2575 case UNIQUE_NAME:
2541 case OBJECT: 2576 case OBJECT:
2542 case GENERIC: 2577 case GENERIC:
2543 return GENERIC; 2578 return GENERIC;
2544 } 2579 }
2545 UNREACHABLE(); 2580 UNREACHABLE();
2546 return GENERIC; // Make the compiler happy. 2581 return GENERIC; // Make the compiler happy.
2547 } 2582 }
2548 2583
2549 2584
2550 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { 2585 Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
2551 HandleScope scope(isolate()); 2586 HandleScope scope(isolate());
2552 State previous_left, previous_right, previous_state; 2587 State previous_left, previous_right, previous_state;
2553 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, 2588 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left,
2554 &previous_right, &previous_state, NULL); 2589 &previous_right, &previous_state, NULL);
2555 State new_left = NewInputState(previous_left, x); 2590 State new_left = NewInputState(previous_left, x);
2556 State new_right = NewInputState(previous_right, y); 2591 State new_right = NewInputState(previous_right, y);
2557 State state = TargetState(previous_state, previous_left, previous_right, 2592 State state = TargetState(previous_state, previous_left, previous_right,
2558 HasInlinedSmiCode(address()), x, y); 2593 HasInlinedSmiCode(address()), x, y);
2559 ICCompareStub stub(op_, new_left, new_right, state); 2594 ICCompareStub stub(op_, new_left, new_right, state);
2560 if (state == KNOWN_OBJECT) { 2595 if (state == KNOWN_OBJECT) {
2561 stub.set_known_map( 2596 stub.set_known_map(
2562 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); 2597 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate()));
2563 } 2598 }
2564 set_target(*stub.GetCode(isolate())); 2599 Handle<Code> new_target = stub.GetCode(isolate());
2600 set_target(*new_target);
2565 2601
2566 #ifdef DEBUG 2602 #ifdef DEBUG
2567 if (FLAG_trace_ic) { 2603 if (FLAG_trace_ic) {
2568 PrintF("[CompareIC in "); 2604 PrintF("[CompareIC in ");
2569 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); 2605 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2570 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", 2606 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
2571 GetStateName(previous_left), 2607 GetStateName(previous_left),
2572 GetStateName(previous_right), 2608 GetStateName(previous_right),
2573 GetStateName(previous_state), 2609 GetStateName(previous_state),
2574 GetStateName(new_left), 2610 GetStateName(new_left),
2575 GetStateName(new_right), 2611 GetStateName(new_right),
2576 GetStateName(state), 2612 GetStateName(state),
2577 Token::Name(op_), 2613 Token::Name(op_),
2578 static_cast<void*>(*stub.GetCode(isolate()))); 2614 static_cast<void*>(*stub.GetCode(isolate())));
2579 } 2615 }
2580 #endif 2616 #endif
2581 2617
2582 // Activate inlined smi code. 2618 // Activate inlined smi code.
2583 if (previous_state == UNINITIALIZED) { 2619 if (previous_state == UNINITIALIZED) {
2584 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); 2620 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2585 } 2621 }
2622
2623 return *new_target;
2586 } 2624 }
2587 2625
2588 2626
2589 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. 2627 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
2590 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { 2628 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2591 HandleScope scope(isolate); 2629 HandleScope scope(isolate);
2592 ASSERT(args.length() == 3); 2630 ASSERT(args.length() == 3);
2593 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); 2631 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2594 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); 2632 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2595 return ic.raw_target();
2596 } 2633 }
2597 2634
2598 2635
2599 void CompareNilIC::Clear(Address address, Code* target) { 2636 void CompareNilIC::Clear(Address address, Code* target) {
2600 if (IsCleared(target)) return; 2637 if (IsCleared(target)) return;
2601 Code::ExtraICState state = target->extended_extra_ic_state(); 2638 Code::ExtraICState state = target->extended_extra_ic_state();
2602 2639
2603 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); 2640 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
2604 stub.ClearState(); 2641 stub.ClearState();
2605 2642
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
2696 case Token::SHR: 2733 case Token::SHR:
2697 return Builtins::SHR; 2734 return Builtins::SHR;
2698 break; 2735 break;
2699 case Token::SHL: 2736 case Token::SHL:
2700 return Builtins::SHL; 2737 return Builtins::SHL;
2701 break; 2738 break;
2702 } 2739 }
2703 } 2740 }
2704 2741
2705 2742
2706 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object, 2743 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object) {
2707 Code::ExtraICState extra_ic_state) { 2744 ToBooleanStub stub(target()->extended_extra_ic_state());
2708 ToBooleanStub stub(extra_ic_state);
2709 bool to_boolean_value = stub.UpdateStatus(object); 2745 bool to_boolean_value = stub.UpdateStatus(object);
2710 Handle<Code> code = stub.GetCode(isolate()); 2746 Handle<Code> code = stub.GetCode(isolate());
2711 set_target(*code); 2747 set_target(*code);
2712 return Smi::FromInt(to_boolean_value ? 1 : 0); 2748 return Smi::FromInt(to_boolean_value ? 1 : 0);
2713 } 2749 }
2714 2750
2715 2751
2716 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) { 2752 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
2717 ASSERT(args.length() == 1); 2753 ASSERT(args.length() == 1);
2718 HandleScope scope(isolate); 2754 HandleScope scope(isolate);
2719 Handle<Object> object = args.at<Object>(0); 2755 Handle<Object> object = args.at<Object>(0);
2720 ToBooleanIC ic(isolate); 2756 ToBooleanIC ic(isolate);
2721 Code::ExtraICState extra_ic_state = ic.target()->extended_extra_ic_state(); 2757 return ic.ToBoolean(object);
2722 return ic.ToBoolean(object, extra_ic_state);
2723 } 2758 }
2724 2759
2725 2760
2726 static const Address IC_utilities[] = { 2761 static const Address IC_utilities[] = {
2727 #define ADDR(name) FUNCTION_ADDR(name), 2762 #define ADDR(name) FUNCTION_ADDR(name),
2728 IC_UTIL_LIST(ADDR) 2763 IC_UTIL_LIST(ADDR)
2729 NULL 2764 NULL
2730 #undef ADDR 2765 #undef ADDR
2731 }; 2766 };
2732 2767
2733 2768
2734 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2769 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2735 return IC_utilities[id]; 2770 return IC_utilities[id];
2736 } 2771 }
2737 2772
2738 2773
2739 } } // namespace v8::internal 2774 } } // namespace v8::internal
OLDNEW
« include/v8-platform.h ('K') | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698