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, |
| 836 Handle<Object> object, |
| 837 Handle<String> name, |
| 838 MaybeObject** result) { |
| 839 // Use specialized code for getting the length of strings and |
| 840 // string wrapper objects. The length property of string wrapper |
| 841 // objects is read-only and therefore always returns the length of |
| 842 // the underlying string value. See ECMA-262 15.5.5.1. |
| 843 if ((object->IsString() || object->IsStringWrapper()) && |
| 844 name->Equals(isolate()->heap()->length_symbol())) { |
| 845 Handle<Code> stub; |
| 846 if (state == UNINITIALIZED) { |
| 847 stub = pre_monomorphic_stub(); |
| 848 } else if (state == PREMONOMORPHIC) { |
| 849 StringLengthStub string_length_stub(kind(), !object->IsString()); |
| 850 stub = string_length_stub.GetCode(); |
| 851 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { |
| 852 StringLengthStub string_length_stub(kind(), true); |
| 853 stub = string_length_stub.GetCode(); |
| 854 } else if (state != MEGAMORPHIC) { |
| 855 ASSERT(state != GENERIC); |
| 856 stub = megamorphic_stub(); |
| 857 } |
| 858 if (!stub.is_null()) { |
| 859 set_target(*stub); |
| 860 #ifdef DEBUG |
| 861 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); |
| 862 #endif |
| 863 } |
| 864 // Get the string if we have a string wrapper object. |
| 865 Handle<Object> string = object->IsJSValue() |
| 866 ? Handle<Object>(Handle<JSValue>::cast(object)->value()) |
| 867 : object; |
| 868 *result = Smi::FromInt(String::cast(*string)->length()); |
| 869 return true; |
| 870 } |
| 871 return false; |
| 872 } |
| 873 |
| 874 |
835 MaybeObject* LoadIC::Load(State state, | 875 MaybeObject* LoadIC::Load(State state, |
836 Handle<Object> object, | 876 Handle<Object> object, |
837 Handle<String> name) { | 877 Handle<String> name) { |
838 // If the object is undefined or null it's illegal to try to get any | 878 // 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. | 879 // of its properties; throw a TypeError in that case. |
840 if (object->IsUndefined() || object->IsNull()) { | 880 if (object->IsUndefined() || object->IsNull()) { |
841 return TypeError("non_object_property_load", object, name); | 881 return TypeError("non_object_property_load", object, name); |
842 } | 882 } |
843 | 883 |
844 if (FLAG_use_ic) { | 884 if (FLAG_use_ic) { |
845 // Use specialized code for getting the length of strings and | 885 MaybeObject* result; |
846 // string wrapper objects. The length property of string wrapper | 886 if (HandleLoad(state, object, name, &result)) { |
847 // objects is read-only and therefore always returns the length of | 887 return result; |
848 // the underlying string value. See ECMA-262 15.5.5.1. | |
849 if ((object->IsString() || object->IsStringWrapper()) && | |
850 name->Equals(isolate()->heap()->length_symbol())) { | |
851 Handle<Code> stub; | |
852 if (state == UNINITIALIZED) { | |
853 stub = pre_monomorphic_stub(); | |
854 } else if (state == PREMONOMORPHIC) { | |
855 stub = object->IsString() | |
856 ? isolate()->builtins()->LoadIC_StringLength() | |
857 : isolate()->builtins()->LoadIC_StringWrapperLength(); | |
858 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { | |
859 stub = isolate()->builtins()->LoadIC_StringWrapperLength(); | |
860 } else if (state != MEGAMORPHIC) { | |
861 ASSERT(state != GENERIC); | |
862 stub = megamorphic_stub(); | |
863 } | |
864 if (!stub.is_null()) { | |
865 set_target(*stub); | |
866 #ifdef DEBUG | |
867 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | |
868 #endif | |
869 } | |
870 // Get the string if we have a string wrapper object. | |
871 Handle<Object> string = object->IsJSValue() | |
872 ? Handle<Object>(Handle<JSValue>::cast(object)->value()) | |
873 : object; | |
874 return Smi::FromInt(String::cast(*string)->length()); | |
875 } | 888 } |
876 | 889 |
877 // Use specialized code for getting the length of arrays. | 890 // Use specialized code for getting the length of arrays. |
878 if (object->IsJSArray() && | 891 if (object->IsJSArray() && |
879 name->Equals(isolate()->heap()->length_symbol())) { | 892 name->Equals(isolate()->heap()->length_symbol())) { |
880 Handle<Code> stub; | 893 Handle<Code> stub; |
881 if (state == UNINITIALIZED) { | 894 if (state == UNINITIALIZED) { |
882 stub = pre_monomorphic_stub(); | 895 stub = pre_monomorphic_stub(); |
883 } else if (state == PREMONOMORPHIC) { | 896 } else if (state == PREMONOMORPHIC) { |
884 stub = isolate()->builtins()->LoadIC_ArrayLength(); | 897 stub = isolate()->builtins()->LoadIC_ArrayLength(); |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 if (key->IsSymbol()) { | 1162 if (key->IsSymbol()) { |
1150 Handle<String> name = Handle<String>::cast(key); | 1163 Handle<String> name = Handle<String>::cast(key); |
1151 | 1164 |
1152 // If the object is undefined or null it's illegal to try to get any | 1165 // If the object is undefined or null it's illegal to try to get any |
1153 // of its properties; throw a TypeError in that case. | 1166 // of its properties; throw a TypeError in that case. |
1154 if (object->IsUndefined() || object->IsNull()) { | 1167 if (object->IsUndefined() || object->IsNull()) { |
1155 return TypeError("non_object_property_load", object, name); | 1168 return TypeError("non_object_property_load", object, name); |
1156 } | 1169 } |
1157 | 1170 |
1158 if (FLAG_use_ic) { | 1171 if (FLAG_use_ic) { |
1159 // TODO(1073): don't ignore the current stub state. | 1172 MaybeObject* result; |
1160 | 1173 if (HandleLoad(state, object, name, &result)) { |
1161 // Use specialized code for getting the length of strings. | 1174 return result; |
1162 if (object->IsString() && | |
1163 name->Equals(isolate()->heap()->length_symbol())) { | |
1164 Handle<String> string = Handle<String>::cast(object); | |
1165 Handle<Code> code = | |
1166 isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, string); | |
1167 ASSERT(!code.is_null()); | |
1168 set_target(*code); | |
1169 TRACE_IC("KeyedLoadIC", name, state, target()); | |
1170 return Smi::FromInt(string->length()); | |
1171 } | 1175 } |
1172 | 1176 |
| 1177 // TODO(1073): don't ignore the current stub state. |
1173 // Use specialized code for getting the length of arrays. | 1178 // Use specialized code for getting the length of arrays. |
1174 if (object->IsJSArray() && | 1179 if (object->IsJSArray() && |
1175 name->Equals(isolate()->heap()->length_symbol())) { | 1180 name->Equals(isolate()->heap()->length_symbol())) { |
1176 Handle<JSArray> array = Handle<JSArray>::cast(object); | 1181 Handle<JSArray> array = Handle<JSArray>::cast(object); |
1177 Handle<Code> code = | 1182 Handle<Code> code = |
1178 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array); | 1183 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array); |
1179 ASSERT(!code.is_null()); | 1184 ASSERT(!code.is_null()); |
1180 set_target(*code); | 1185 set_target(*code); |
1181 TRACE_IC("KeyedLoadIC", name, state, target()); | 1186 TRACE_IC("KeyedLoadIC", name, state, target()); |
1182 return array->length(); | 1187 return array->length(); |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 // We are transitioning from monomorphic to megamorphic case. | 1610 // We are transitioning from monomorphic to megamorphic case. |
1606 // Place the current monomorphic stub and stub compiled for | 1611 // Place the current monomorphic stub and stub compiled for |
1607 // the receiver into stub cache. | 1612 // the receiver into stub cache. |
1608 Map* map = target()->FindFirstMap(); | 1613 Map* map = target()->FindFirstMap(); |
1609 if (map != NULL) { | 1614 if (map != NULL) { |
1610 isolate()->stub_cache()->Set(*name, map, target()); | 1615 isolate()->stub_cache()->Set(*name, map, target()); |
1611 } | 1616 } |
1612 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | 1617 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
1613 set_target((strict_mode == kStrictMode) | 1618 set_target((strict_mode == kStrictMode) |
1614 ? megamorphic_stub_strict() | 1619 ? megamorphic_stub_strict() |
1615 : megamorphic_stub()); | 1620 : *megamorphic_stub()); |
1616 } | 1621 } |
1617 break; | 1622 break; |
1618 case MEGAMORPHIC: | 1623 case MEGAMORPHIC: |
1619 // Update the stub cache. | 1624 // Update the stub cache. |
1620 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | 1625 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
1621 break; | 1626 break; |
1622 case DEBUG_STUB: | 1627 case DEBUG_STUB: |
1623 break; | 1628 break; |
1624 case POLYMORPHIC: | 1629 case POLYMORPHIC: |
1625 case GENERIC: | 1630 case GENERIC: |
(...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2877 #undef ADDR | 2882 #undef ADDR |
2878 }; | 2883 }; |
2879 | 2884 |
2880 | 2885 |
2881 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2886 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2882 return IC_utilities[id]; | 2887 return IC_utilities[id]; |
2883 } | 2888 } |
2884 | 2889 |
2885 | 2890 |
2886 } } // namespace v8::internal | 2891 } } // namespace v8::internal |
OLD | NEW |