| 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 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 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<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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |