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 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
825 ReceiverToObjectIfRequired(result, object); | 825 ReceiverToObjectIfRequired(result, object); |
826 if (result->IsJSFunction()) return *result; | 826 if (result->IsJSFunction()) return *result; |
827 | 827 |
828 result = TryCallAsFunction(result); | 828 result = TryCallAsFunction(result); |
829 if (result->IsJSFunction()) return *result; | 829 if (result->IsJSFunction()) return *result; |
830 | 830 |
831 return TypeError("property_not_function", object, key); | 831 return TypeError("property_not_function", object, key); |
832 } | 832 } |
833 | 833 |
834 | 834 |
835 bool IC::HandleLoad(State state, | 835 MaybeObject* IC::Load(State state, |
836 Handle<Object> object, | 836 Handle<Object> object, |
837 Handle<String> name, | 837 Handle<String> name) { |
838 MaybeObject** result) { | 838 // If the object is undefined or null it's illegal to try to get any |
839 // of its properties; throw a TypeError in that case. | |
840 if (object->IsUndefined() || object->IsNull()) { | |
841 return TypeError("non_object_property_load", object, name); | |
842 } | |
843 | |
839 if (FLAG_use_ic) { | 844 if (FLAG_use_ic) { |
840 // Use specialized code for getting the length of strings and | 845 // Use specialized code for getting the length of strings and |
841 // string wrapper objects. The length property of string wrapper | 846 // string wrapper objects. The length property of string wrapper |
842 // objects is read-only and therefore always returns the length of | 847 // objects is read-only and therefore always returns the length of |
843 // the underlying string value. See ECMA-262 15.5.5.1. | 848 // the underlying string value. See ECMA-262 15.5.5.1. |
844 if ((object->IsString() || object->IsStringWrapper()) && | 849 if ((object->IsString() || object->IsStringWrapper()) && |
845 name->Equals(isolate()->heap()->length_symbol())) { | 850 name->Equals(isolate()->heap()->length_symbol())) { |
846 Handle<Code> stub; | 851 Handle<Code> stub; |
847 if (state == UNINITIALIZED) { | 852 if (state == UNINITIALIZED) { |
848 stub = pre_monomorphic_stub(); | 853 stub = pre_monomorphic_stub(); |
(...skipping 10 matching lines...) Expand all Loading... | |
859 if (!stub.is_null()) { | 864 if (!stub.is_null()) { |
860 set_target(*stub); | 865 set_target(*stub); |
861 #ifdef DEBUG | 866 #ifdef DEBUG |
862 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | 867 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); |
863 #endif | 868 #endif |
864 } | 869 } |
865 // Get the string if we have a string wrapper object. | 870 // Get the string if we have a string wrapper object. |
866 Handle<Object> string = object->IsJSValue() | 871 Handle<Object> string = object->IsJSValue() |
867 ? Handle<Object>(Handle<JSValue>::cast(object)->value()) | 872 ? Handle<Object>(Handle<JSValue>::cast(object)->value()) |
868 : object; | 873 : object; |
869 *result = Smi::FromInt(String::cast(*string)->length()); | 874 return Smi::FromInt(String::cast(*string)->length()); |
870 return true; | |
871 } | 875 } |
872 | 876 |
873 // Use specialized code for getting the length of arrays. | 877 // Use specialized code for getting the length of arrays. |
874 if (object->IsJSArray() && | 878 if (object->IsJSArray() && |
875 name->Equals(isolate()->heap()->length_symbol())) { | 879 name->Equals(isolate()->heap()->length_symbol())) { |
876 Handle<Code> stub; | 880 Handle<Code> stub; |
877 if (state == UNINITIALIZED) { | 881 if (state == UNINITIALIZED) { |
878 stub = pre_monomorphic_stub(); | 882 stub = pre_monomorphic_stub(); |
879 } else if (state == PREMONOMORPHIC) { | 883 } else if (state == PREMONOMORPHIC) { |
880 ArrayLengthStub array_length_stub(kind()); | 884 ArrayLengthStub array_length_stub(kind()); |
881 stub = array_length_stub.GetCode(); | 885 stub = array_length_stub.GetCode(); |
882 } else if (state != MEGAMORPHIC) { | 886 } else if (state != MEGAMORPHIC) { |
883 ASSERT(state != GENERIC); | 887 ASSERT(state != GENERIC); |
884 stub = megamorphic_stub(); | 888 stub = megamorphic_stub(); |
885 } | 889 } |
886 if (!stub.is_null()) { | 890 if (!stub.is_null()) { |
887 set_target(*stub); | 891 set_target(*stub); |
888 #ifdef DEBUG | 892 #ifdef DEBUG |
889 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); | 893 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); |
890 #endif | 894 #endif |
891 } | 895 } |
892 *result = JSArray::cast(*object)->length(); | 896 return JSArray::cast(*object)->length(); |
893 return true; | |
894 } | 897 } |
895 | 898 |
896 // Use specialized code for getting prototype of functions. | 899 // Use specialized code for getting prototype of functions. |
897 if (object->IsJSFunction() && | 900 if (object->IsJSFunction() && |
898 name->Equals(isolate()->heap()->prototype_symbol()) && | 901 name->Equals(isolate()->heap()->prototype_symbol()) && |
899 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 902 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
900 Handle<Code> stub; | 903 Handle<Code> stub; |
901 if (state == UNINITIALIZED) { | 904 if (state == UNINITIALIZED) { |
902 stub = pre_monomorphic_stub(); | 905 stub = pre_monomorphic_stub(); |
903 } else if (state == PREMONOMORPHIC) { | 906 } else if (state == PREMONOMORPHIC) { |
904 FunctionPrototypeStub function_prototype_stub(kind()); | 907 FunctionPrototypeStub function_prototype_stub(kind()); |
905 stub = function_prototype_stub.GetCode(); | 908 stub = function_prototype_stub.GetCode(); |
906 } else if (state != MEGAMORPHIC) { | 909 } else if (state != MEGAMORPHIC) { |
907 ASSERT(state != GENERIC); | 910 ASSERT(state != GENERIC); |
908 stub = megamorphic_stub(); | 911 stub = megamorphic_stub(); |
909 } | 912 } |
910 if (!stub.is_null()) { | 913 if (!stub.is_null()) { |
911 set_target(*stub); | 914 set_target(*stub); |
912 #ifdef DEBUG | 915 #ifdef DEBUG |
913 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 916 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
914 #endif | 917 #endif |
915 } | 918 } |
916 *result = Accessors::FunctionGetPrototype(*object, 0); | 919 return Accessors::FunctionGetPrototype(*object, 0); |
917 return true; | |
918 } | 920 } |
919 } | 921 } |
920 | 922 |
921 return false; | 923 // Check if the name is trivially convertible to an index and get |
922 } | 924 // the element or char if so. |
923 | 925 uint32_t index; |
924 | 926 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
925 MaybeObject* LoadIC::Load(State state, | 927 // Rewrite to the generic keyed load stub. |
926 Handle<Object> object, | 928 if (FLAG_use_ic) set_target(*generic_stub()); |
927 Handle<String> name) { | 929 return Runtime::GetElementOrCharAt(isolate(), object, index); |
928 // If the object is undefined or null it's illegal to try to get any | |
929 // of its properties; throw a TypeError in that case. | |
930 if (object->IsUndefined() || object->IsNull()) { | |
931 return TypeError("non_object_property_load", object, name); | |
932 } | 930 } |
933 | 931 |
934 MaybeObject* result; | |
935 if (HandleLoad(state, object, name, &result)) { | |
936 return result; | |
937 } | |
938 | |
939 // Check if the name is trivially convertible to an index and get | |
940 // the element if so. | |
941 uint32_t index; | |
942 if (name->AsArrayIndex(&index)) return object->GetElement(index); | |
Jakob Kummerow
2013/01/22 09:24:39
Per offline discussion: it seems this condition ca
| |
943 | |
944 // Named lookup in the object. | 932 // Named lookup in the object. |
945 LookupResult lookup(isolate()); | 933 LookupResult lookup(isolate()); |
946 LookupForRead(object, name, &lookup); | 934 LookupForRead(object, name, &lookup); |
947 | 935 |
948 // If we did not find a property, check if we need to throw an exception. | 936 // If we did not find a property, check if we need to throw an exception. |
949 if (!lookup.IsFound()) { | 937 if (!lookup.IsFound()) { |
950 if (IsContextual(object)) { | 938 if (IsContextual(object)) { |
951 return ReferenceError("not_defined", name); | 939 return ReferenceError("not_defined", name); |
952 } | 940 } |
953 LOG(isolate(), SuspectReadEvent(*name, *object)); | 941 LOG(isolate(), SuspectReadEvent(*name, *object)); |
954 } | 942 } |
955 | 943 |
956 // Update inline cache and stub cache. | 944 // Update inline cache and stub cache. |
957 if (FLAG_use_ic) { | 945 if (FLAG_use_ic) { |
958 UpdateCaches(&lookup, state, object, name); | 946 UpdateLoadCaches(&lookup, state, object, name); |
959 } | 947 } |
960 | 948 |
961 PropertyAttributes attr; | 949 PropertyAttributes attr; |
962 if (lookup.IsInterceptor() || lookup.IsHandler()) { | 950 if (lookup.IsInterceptor() || lookup.IsHandler()) { |
963 // Get the property. | 951 // Get the property. |
964 Handle<Object> result = | 952 Handle<Object> result = |
965 Object::GetProperty(object, object, &lookup, name, &attr); | 953 Object::GetProperty(object, object, &lookup, name, &attr); |
966 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 954 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
967 // If the property is not present, check if we need to throw an | 955 // If the property is not present, check if we need to throw an |
968 // exception. | 956 // exception. |
969 if (attr == ABSENT && IsContextual(object)) { | 957 if (attr == ABSENT && IsContextual(object)) { |
970 return ReferenceError("not_defined", name); | 958 return ReferenceError("not_defined", name); |
971 } | 959 } |
972 return *result; | 960 return *result; |
973 } | 961 } |
974 | 962 |
975 // Get the property. | 963 // Get the property. |
976 return object->GetProperty(*object, &lookup, *name, &attr); | 964 return object->GetProperty(*object, &lookup, *name, &attr); |
977 } | 965 } |
978 | 966 |
979 | 967 |
980 void LoadIC::UpdateCaches(LookupResult* lookup, | 968 void LoadIC::UpdateLoadCaches(LookupResult* lookup, |
981 State state, | 969 State state, |
982 Handle<Object> object, | 970 Handle<Object> object, |
983 Handle<String> name) { | 971 Handle<String> name) { |
984 // Bail out if the result is not cacheable. | 972 // Bail out if the result is not cacheable. |
985 if (!lookup->IsCacheable()) return; | 973 if (!lookup->IsCacheable()) return; |
986 | 974 |
987 // Loading properties from values is not common, so don't try to | 975 // Loading properties from values is not common, so don't try to |
988 // deal with non-JS objects here. | 976 // deal with non-JS objects here. |
989 if (!object->IsJSObject()) return; | 977 if (!object->IsJSObject()) return; |
990 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 978 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
991 | 979 |
992 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; | 980 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; |
993 | 981 |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1158 | 1146 |
1159 MaybeObject* KeyedLoadIC::Load(State state, | 1147 MaybeObject* KeyedLoadIC::Load(State state, |
1160 Handle<Object> object, | 1148 Handle<Object> object, |
1161 Handle<Object> key, | 1149 Handle<Object> key, |
1162 ICMissMode miss_mode) { | 1150 ICMissMode miss_mode) { |
1163 // Check for values that can be converted into a symbol directly or | 1151 // Check for values that can be converted into a symbol directly or |
1164 // is representable as a smi. | 1152 // is representable as a smi. |
1165 key = TryConvertKey(key, isolate()); | 1153 key = TryConvertKey(key, isolate()); |
1166 | 1154 |
1167 if (key->IsSymbol()) { | 1155 if (key->IsSymbol()) { |
1168 Handle<String> name = Handle<String>::cast(key); | 1156 return IC::Load(state, object, Handle<String>::cast(key)); |
1169 | |
1170 // If the object is undefined or null it's illegal to try to get any | |
1171 // of its properties; throw a TypeError in that case. | |
1172 if (object->IsUndefined() || object->IsNull()) { | |
1173 return TypeError("non_object_property_load", object, name); | |
1174 } | |
1175 | |
1176 MaybeObject* result; | |
1177 if (HandleLoad(state, object, name, &result)) { | |
1178 return result; | |
1179 } | |
1180 | |
1181 // Check if the name is trivially convertible to an index and get | |
1182 // the element or char if so. | |
1183 uint32_t index = 0; | |
1184 if (name->AsArrayIndex(&index)) { | |
1185 // Rewrite to the generic keyed load stub. | |
1186 if (FLAG_use_ic) set_target(*generic_stub()); | |
1187 return Runtime::GetElementOrCharAt(isolate(), object, index); | |
1188 } | |
1189 | |
1190 // Named lookup. | |
1191 LookupResult lookup(isolate()); | |
1192 LookupForRead(object, name, &lookup); | |
1193 | |
1194 // If we did not find a property, check if we need to throw an exception. | |
1195 if (!lookup.IsFound() && IsContextual(object)) { | |
1196 return ReferenceError("not_defined", name); | |
1197 } | |
1198 | |
1199 if (FLAG_use_ic) { | |
1200 UpdateCaches(&lookup, state, object, name); | |
1201 } | |
1202 | |
1203 PropertyAttributes attr; | |
1204 if (lookup.IsInterceptor()) { | |
1205 // Get the property. | |
1206 Handle<Object> result = | |
1207 Object::GetProperty(object, object, &lookup, name, &attr); | |
1208 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
1209 // If the property is not present, check if we need to throw an | |
1210 // exception. | |
1211 if (attr == ABSENT && IsContextual(object)) { | |
1212 return ReferenceError("not_defined", name); | |
1213 } | |
1214 return *result; | |
1215 } | |
1216 | |
1217 return object->GetProperty(*object, &lookup, *name, &attr); | |
1218 } | 1157 } |
1219 | 1158 |
1220 // Do not use ICs for objects that require access checks (including | 1159 // Do not use ICs for objects that require access checks (including |
1221 // the global object). | 1160 // the global object). |
1222 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1161 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
1223 | 1162 |
1224 if (use_ic) { | 1163 if (use_ic) { |
1225 Handle<Code> stub = generic_stub(); | 1164 Handle<Code> stub = generic_stub(); |
1226 if (miss_mode != MISS_FORCE_GENERIC) { | 1165 if (miss_mode != MISS_FORCE_GENERIC) { |
1227 if (object->IsString() && key->IsNumber()) { | 1166 if (object->IsString() && key->IsNumber()) { |
1228 if (state == UNINITIALIZED) { | 1167 if (state == UNINITIALIZED) { |
1229 stub = string_stub(); | 1168 stub = string_stub(); |
1230 } | 1169 } |
1231 } else if (object->IsJSObject()) { | 1170 } else if (object->IsJSObject()) { |
1232 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1171 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1233 if (receiver->elements()->map() == | 1172 if (receiver->elements()->map() == |
1234 isolate()->heap()->non_strict_arguments_elements_map()) { | 1173 isolate()->heap()->non_strict_arguments_elements_map()) { |
1235 stub = non_strict_arguments_stub(); | 1174 stub = non_strict_arguments_stub(); |
1236 } else if (receiver->HasIndexedInterceptor()) { | 1175 } else if (receiver->HasIndexedInterceptor()) { |
1237 stub = indexed_interceptor_stub(); | 1176 stub = indexed_interceptor_stub(); |
1238 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1177 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
1239 stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub); | 1178 stub = ComputeStub(receiver, KeyedIC::LOAD, kNonStrictMode, stub); |
1240 } | 1179 } |
1241 } | 1180 } |
1242 } else { | 1181 } else { |
1243 TRACE_GENERIC_IC("KeyedLoadIC", "force generic"); | 1182 TRACE_GENERIC_IC("KeyedLoadIC", "force generic"); |
1244 } | 1183 } |
1245 if (!stub.is_null()) set_target(*stub); | 1184 if (!stub.is_null()) set_target(*stub); |
1246 } | 1185 } |
1247 | 1186 |
1248 TRACE_IC("KeyedLoadIC", key, state, target()); | 1187 TRACE_IC("KeyedLoadIC", key, state, target()); |
1249 | 1188 |
1250 // Get the property. | 1189 // Get the property. |
1251 return Runtime::GetObjectProperty(isolate(), object, key); | 1190 return Runtime::GetObjectProperty(isolate(), object, key); |
1252 } | 1191 } |
1253 | 1192 |
1254 | 1193 |
1255 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, | 1194 void KeyedLoadIC::UpdateLoadCaches(LookupResult* lookup, |
1256 State state, | 1195 State state, |
1257 Handle<Object> object, | 1196 Handle<Object> object, |
1258 Handle<String> name) { | 1197 Handle<String> name) { |
1259 // Bail out if we didn't find a result. | 1198 // Bail out if we didn't find a result. |
1260 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 1199 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
1261 | 1200 |
1262 if (!object->IsJSObject()) return; | 1201 if (!object->IsJSObject()) return; |
1263 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1202 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1264 | 1203 |
1265 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; | 1204 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; |
1266 | 1205 |
1267 // Compute the code stub for this load. | 1206 // Compute the code stub for this load. |
1268 Handle<Code> code; | 1207 Handle<Code> code; |
(...skipping 1589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2858 #undef ADDR | 2797 #undef ADDR |
2859 }; | 2798 }; |
2860 | 2799 |
2861 | 2800 |
2862 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2801 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2863 return IC_utilities[id]; | 2802 return IC_utilities[id]; |
2864 } | 2803 } |
2865 | 2804 |
2866 | 2805 |
2867 } } // namespace v8::internal | 2806 } } // namespace v8::internal |
OLD | NEW |