| 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 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 bool IC::HandleLoad(State state, |
| 836 Handle<Object> object, | 836 Handle<Object> object, |
| 837 Handle<String> name, | 837 Handle<String> name, |
| 838 MaybeObject** result) { | 838 MaybeObject** result) { |
| 839 // Use specialized code for getting the length of strings and | 839 if (FLAG_use_ic) { |
| 840 // string wrapper objects. The length property of string wrapper | 840 // Use specialized code for getting the length of strings and |
| 841 // objects is read-only and therefore always returns the length of | 841 // string wrapper objects. The length property of string wrapper |
| 842 // the underlying string value. See ECMA-262 15.5.5.1. | 842 // objects is read-only and therefore always returns the length of |
| 843 if ((object->IsString() || object->IsStringWrapper()) && | 843 // the underlying string value. See ECMA-262 15.5.5.1. |
| 844 name->Equals(isolate()->heap()->length_symbol())) { | 844 if ((object->IsString() || object->IsStringWrapper()) && |
| 845 Handle<Code> stub; | 845 name->Equals(isolate()->heap()->length_symbol())) { |
| 846 if (state == UNINITIALIZED) { | 846 Handle<Code> stub; |
| 847 stub = pre_monomorphic_stub(); | 847 if (state == UNINITIALIZED) { |
| 848 } else if (state == PREMONOMORPHIC) { | 848 stub = pre_monomorphic_stub(); |
| 849 StringLengthStub string_length_stub(kind(), !object->IsString()); | 849 } else if (state == PREMONOMORPHIC) { |
| 850 stub = string_length_stub.GetCode(); | 850 StringLengthStub string_length_stub(kind(), !object->IsString()); |
| 851 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { | 851 stub = string_length_stub.GetCode(); |
| 852 StringLengthStub string_length_stub(kind(), true); | 852 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { |
| 853 stub = string_length_stub.GetCode(); | 853 StringLengthStub string_length_stub(kind(), true); |
| 854 } else if (state != MEGAMORPHIC) { | 854 stub = string_length_stub.GetCode(); |
| 855 ASSERT(state != GENERIC); | 855 } else if (state != MEGAMORPHIC) { |
| 856 stub = megamorphic_stub(); | 856 ASSERT(state != GENERIC); |
| 857 stub = megamorphic_stub(); |
| 858 } |
| 859 if (!stub.is_null()) { |
| 860 set_target(*stub); |
| 861 #ifdef DEBUG |
| 862 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); |
| 863 #endif |
| 864 } |
| 865 // Get the string if we have a string wrapper object. |
| 866 Handle<Object> string = object->IsJSValue() |
| 867 ? Handle<Object>(Handle<JSValue>::cast(object)->value()) |
| 868 : object; |
| 869 *result = Smi::FromInt(String::cast(*string)->length()); |
| 870 return true; |
| 857 } | 871 } |
| 858 if (!stub.is_null()) { | 872 |
| 859 set_target(*stub); | 873 // Use specialized code for getting the length of arrays. |
| 874 if (object->IsJSArray() && |
| 875 name->Equals(isolate()->heap()->length_symbol())) { |
| 876 Handle<Code> stub; |
| 877 if (state == UNINITIALIZED) { |
| 878 stub = pre_monomorphic_stub(); |
| 879 } else if (state == PREMONOMORPHIC) { |
| 880 ArrayLengthStub array_length_stub(kind()); |
| 881 stub = array_length_stub.GetCode(); |
| 882 } else if (state != MEGAMORPHIC) { |
| 883 ASSERT(state != GENERIC); |
| 884 stub = megamorphic_stub(); |
| 885 } |
| 886 if (!stub.is_null()) { |
| 887 set_target(*stub); |
| 860 #ifdef DEBUG | 888 #ifdef DEBUG |
| 861 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | 889 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); |
| 862 #endif | 890 #endif |
| 863 } | 891 } |
| 864 // Get the string if we have a string wrapper object. | 892 *result = JSArray::cast(*object)->length(); |
| 865 Handle<Object> string = object->IsJSValue() | 893 return true; |
| 866 ? Handle<Object>(Handle<JSValue>::cast(object)->value()) | |
| 867 : object; | |
| 868 *result = Smi::FromInt(String::cast(*string)->length()); | |
| 869 return true; | |
| 870 } | |
| 871 | |
| 872 // Use specialized code for getting the length of arrays. | |
| 873 if (object->IsJSArray() && name->Equals(isolate()->heap()->length_symbol())) { | |
| 874 Handle<Code> stub; | |
| 875 if (state == UNINITIALIZED) { | |
| 876 stub = pre_monomorphic_stub(); | |
| 877 } else if (state == PREMONOMORPHIC) { | |
| 878 ArrayLengthStub array_length_stub(kind()); | |
| 879 stub = array_length_stub.GetCode(); | |
| 880 } else if (state != MEGAMORPHIC) { | |
| 881 ASSERT(state != GENERIC); | |
| 882 stub = megamorphic_stub(); | |
| 883 } | |
| 884 if (!stub.is_null()) { | |
| 885 set_target(*stub); | |
| 886 #ifdef DEBUG | |
| 887 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); | |
| 888 #endif | |
| 889 } | |
| 890 *result = JSArray::cast(*object)->length(); | |
| 891 return true; | |
| 892 } | |
| 893 | |
| 894 return false; | |
| 895 } | |
| 896 | |
| 897 | |
| 898 MaybeObject* LoadIC::Load(State state, | |
| 899 Handle<Object> object, | |
| 900 Handle<String> name) { | |
| 901 // If the object is undefined or null it's illegal to try to get any | |
| 902 // of its properties; throw a TypeError in that case. | |
| 903 if (object->IsUndefined() || object->IsNull()) { | |
| 904 return TypeError("non_object_property_load", object, name); | |
| 905 } | |
| 906 | |
| 907 if (FLAG_use_ic) { | |
| 908 MaybeObject* result; | |
| 909 if (HandleLoad(state, object, name, &result)) { | |
| 910 return result; | |
| 911 } | 894 } |
| 912 | 895 |
| 913 // Use specialized code for getting prototype of functions. | 896 // Use specialized code for getting prototype of functions. |
| 914 if (object->IsJSFunction() && | 897 if (object->IsJSFunction() && |
| 915 name->Equals(isolate()->heap()->prototype_symbol()) && | 898 name->Equals(isolate()->heap()->prototype_symbol()) && |
| 916 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 899 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
| 917 Handle<Code> stub; | 900 Handle<Code> stub; |
| 918 if (state == UNINITIALIZED) { | 901 if (state == UNINITIALIZED) { |
| 919 stub = pre_monomorphic_stub(); | 902 stub = pre_monomorphic_stub(); |
| 920 } else if (state == PREMONOMORPHIC) { | 903 } else if (state == PREMONOMORPHIC) { |
| 921 stub = isolate()->builtins()->LoadIC_FunctionPrototype(); | 904 FunctionPrototypeStub function_prototype_stub(kind()); |
| 905 stub = function_prototype_stub.GetCode(); |
| 922 } else if (state != MEGAMORPHIC) { | 906 } else if (state != MEGAMORPHIC) { |
| 923 ASSERT(state != GENERIC); | 907 ASSERT(state != GENERIC); |
| 924 stub = megamorphic_stub(); | 908 stub = megamorphic_stub(); |
| 925 } | 909 } |
| 926 if (!stub.is_null()) { | 910 if (!stub.is_null()) { |
| 927 set_target(*stub); | 911 set_target(*stub); |
| 928 #ifdef DEBUG | 912 #ifdef DEBUG |
| 929 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 913 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
| 930 #endif | 914 #endif |
| 931 } | 915 } |
| 932 return Accessors::FunctionGetPrototype(*object, 0); | 916 *result = Accessors::FunctionGetPrototype(*object, 0); |
| 917 return true; |
| 933 } | 918 } |
| 934 } | 919 } |
| 935 | 920 |
| 921 return false; |
| 922 } |
| 923 |
| 924 |
| 925 MaybeObject* LoadIC::Load(State state, |
| 926 Handle<Object> object, |
| 927 Handle<String> name) { |
| 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 } |
| 933 |
| 934 MaybeObject* result; |
| 935 if (HandleLoad(state, object, name, &result)) { |
| 936 return result; |
| 937 } |
| 938 |
| 936 // Check if the name is trivially convertible to an index and get | 939 // Check if the name is trivially convertible to an index and get |
| 937 // the element if so. | 940 // the element if so. |
| 938 uint32_t index; | 941 uint32_t index; |
| 939 if (name->AsArrayIndex(&index)) return object->GetElement(index); | 942 if (name->AsArrayIndex(&index)) return object->GetElement(index); |
| 940 | 943 |
| 941 // Named lookup in the object. | 944 // Named lookup in the object. |
| 942 LookupResult lookup(isolate()); | 945 LookupResult lookup(isolate()); |
| 943 LookupForRead(object, name, &lookup); | 946 LookupForRead(object, name, &lookup); |
| 944 | 947 |
| 945 // If we did not find a property, check if we need to throw an exception. | 948 // If we did not find a property, check if we need to throw an exception. |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1163 | 1166 |
| 1164 if (key->IsSymbol()) { | 1167 if (key->IsSymbol()) { |
| 1165 Handle<String> name = Handle<String>::cast(key); | 1168 Handle<String> name = Handle<String>::cast(key); |
| 1166 | 1169 |
| 1167 // If the object is undefined or null it's illegal to try to get any | 1170 // If the object is undefined or null it's illegal to try to get any |
| 1168 // of its properties; throw a TypeError in that case. | 1171 // of its properties; throw a TypeError in that case. |
| 1169 if (object->IsUndefined() || object->IsNull()) { | 1172 if (object->IsUndefined() || object->IsNull()) { |
| 1170 return TypeError("non_object_property_load", object, name); | 1173 return TypeError("non_object_property_load", object, name); |
| 1171 } | 1174 } |
| 1172 | 1175 |
| 1173 if (FLAG_use_ic) { | 1176 MaybeObject* result; |
| 1174 MaybeObject* result; | 1177 if (HandleLoad(state, object, name, &result)) { |
| 1175 if (HandleLoad(state, object, name, &result)) { | 1178 return result; |
| 1176 return result; | |
| 1177 } | |
| 1178 | |
| 1179 // TODO(1073): don't ignore the current stub state. | |
| 1180 // Use specialized code for getting prototype of functions. | |
| 1181 if (object->IsJSFunction() && | |
| 1182 name->Equals(isolate()->heap()->prototype_symbol()) && | |
| 1183 Handle<JSFunction>::cast(object)->should_have_prototype()) { | |
| 1184 Handle<JSFunction> function = Handle<JSFunction>::cast(object); | |
| 1185 Handle<Code> code = | |
| 1186 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( | |
| 1187 name, function); | |
| 1188 ASSERT(!code.is_null()); | |
| 1189 set_target(*code); | |
| 1190 TRACE_IC("KeyedLoadIC", name, state, target()); | |
| 1191 return Accessors::FunctionGetPrototype(*object, 0); | |
| 1192 } | |
| 1193 } | 1179 } |
| 1194 | 1180 |
| 1195 // Check if the name is trivially convertible to an index and get | 1181 // Check if the name is trivially convertible to an index and get |
| 1196 // the element or char if so. | 1182 // the element or char if so. |
| 1197 uint32_t index = 0; | 1183 uint32_t index = 0; |
| 1198 if (name->AsArrayIndex(&index)) { | 1184 if (name->AsArrayIndex(&index)) { |
| 1199 // Rewrite to the generic keyed load stub. | 1185 // Rewrite to the generic keyed load stub. |
| 1200 if (FLAG_use_ic) set_target(*generic_stub()); | 1186 if (FLAG_use_ic) set_target(*generic_stub()); |
| 1201 return Runtime::GetElementOrCharAt(isolate(), object, index); | 1187 return Runtime::GetElementOrCharAt(isolate(), object, index); |
| 1202 } | 1188 } |
| (...skipping 1669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2872 #undef ADDR | 2858 #undef ADDR |
| 2873 }; | 2859 }; |
| 2874 | 2860 |
| 2875 | 2861 |
| 2876 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2862 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2877 return IC_utilities[id]; | 2863 return IC_utilities[id]; |
| 2878 } | 2864 } |
| 2879 | 2865 |
| 2880 | 2866 |
| 2881 } } // namespace v8::internal | 2867 } } // namespace v8::internal |
| OLD | NEW |