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 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 } | 748 } |
749 | 749 |
750 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 750 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
751 name, state, target()); | 751 name, state, target()); |
752 } | 752 } |
753 | 753 |
754 | 754 |
755 MaybeObject* KeyedCallIC::LoadFunction(State state, | 755 MaybeObject* KeyedCallIC::LoadFunction(State state, |
756 Handle<Object> object, | 756 Handle<Object> object, |
757 Handle<Object> key) { | 757 Handle<Object> key) { |
758 if (key->IsSymbol()) { | 758 if (key->IsInternalizedString()) { |
759 return CallICBase::LoadFunction(state, | 759 return CallICBase::LoadFunction(state, |
760 Code::kNoExtraICState, | 760 Code::kNoExtraICState, |
761 object, | 761 object, |
762 Handle<String>::cast(key)); | 762 Handle<String>::cast(key)); |
763 } | 763 } |
764 | 764 |
765 if (object->IsUndefined() || object->IsNull()) { | 765 if (object->IsUndefined() || object->IsNull()) { |
766 return TypeError("non_object_property_call", object, key); | 766 return TypeError("non_object_property_call", object, key); |
767 } | 767 } |
768 | 768 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 if (object->IsUndefined() || object->IsNull()) { | 809 if (object->IsUndefined() || object->IsNull()) { |
810 return TypeError("non_object_property_load", object, name); | 810 return TypeError("non_object_property_load", object, name); |
811 } | 811 } |
812 | 812 |
813 if (FLAG_use_ic) { | 813 if (FLAG_use_ic) { |
814 // Use specialized code for getting the length of strings and | 814 // Use specialized code for getting the length of strings and |
815 // string wrapper objects. The length property of string wrapper | 815 // string wrapper objects. The length property of string wrapper |
816 // objects is read-only and therefore always returns the length of | 816 // objects is read-only and therefore always returns the length of |
817 // the underlying string value. See ECMA-262 15.5.5.1. | 817 // the underlying string value. See ECMA-262 15.5.5.1. |
818 if ((object->IsString() || object->IsStringWrapper()) && | 818 if ((object->IsString() || object->IsStringWrapper()) && |
819 name->Equals(isolate()->heap()->length_symbol())) { | 819 name->Equals(isolate()->heap()->length_string())) { |
820 Handle<Code> stub; | 820 Handle<Code> stub; |
821 if (state == UNINITIALIZED) { | 821 if (state == UNINITIALIZED) { |
822 stub = pre_monomorphic_stub(); | 822 stub = pre_monomorphic_stub(); |
823 } else if (state == PREMONOMORPHIC) { | 823 } else if (state == PREMONOMORPHIC) { |
824 StringLengthStub string_length_stub(kind(), !object->IsString()); | 824 StringLengthStub string_length_stub(kind(), !object->IsString()); |
825 stub = string_length_stub.GetCode(); | 825 stub = string_length_stub.GetCode(); |
826 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { | 826 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { |
827 StringLengthStub string_length_stub(kind(), true); | 827 StringLengthStub string_length_stub(kind(), true); |
828 stub = string_length_stub.GetCode(); | 828 stub = string_length_stub.GetCode(); |
829 } else if (state != MEGAMORPHIC) { | 829 } else if (state != MEGAMORPHIC) { |
830 ASSERT(state != GENERIC); | 830 ASSERT(state != GENERIC); |
831 stub = megamorphic_stub(); | 831 stub = megamorphic_stub(); |
832 } | 832 } |
833 if (!stub.is_null()) { | 833 if (!stub.is_null()) { |
834 set_target(*stub); | 834 set_target(*stub); |
835 #ifdef DEBUG | 835 #ifdef DEBUG |
836 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | 836 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); |
837 #endif | 837 #endif |
838 } | 838 } |
839 // Get the string if we have a string wrapper object. | 839 // Get the string if we have a string wrapper object. |
840 Handle<Object> string = object->IsJSValue() | 840 Handle<Object> string = object->IsJSValue() |
841 ? Handle<Object>(Handle<JSValue>::cast(object)->value()) | 841 ? Handle<Object>(Handle<JSValue>::cast(object)->value()) |
842 : object; | 842 : object; |
843 return Smi::FromInt(String::cast(*string)->length()); | 843 return Smi::FromInt(String::cast(*string)->length()); |
844 } | 844 } |
845 | 845 |
846 // Use specialized code for getting the length of arrays. | 846 // Use specialized code for getting the length of arrays. |
847 if (object->IsJSArray() && | 847 if (object->IsJSArray() && |
848 name->Equals(isolate()->heap()->length_symbol())) { | 848 name->Equals(isolate()->heap()->length_string())) { |
849 Handle<Code> stub; | 849 Handle<Code> stub; |
850 if (state == UNINITIALIZED) { | 850 if (state == UNINITIALIZED) { |
851 stub = pre_monomorphic_stub(); | 851 stub = pre_monomorphic_stub(); |
852 } else if (state == PREMONOMORPHIC) { | 852 } else if (state == PREMONOMORPHIC) { |
853 ArrayLengthStub array_length_stub(kind()); | 853 ArrayLengthStub array_length_stub(kind()); |
854 stub = array_length_stub.GetCode(); | 854 stub = array_length_stub.GetCode(); |
855 } else if (state != MEGAMORPHIC) { | 855 } else if (state != MEGAMORPHIC) { |
856 ASSERT(state != GENERIC); | 856 ASSERT(state != GENERIC); |
857 stub = megamorphic_stub(); | 857 stub = megamorphic_stub(); |
858 } | 858 } |
859 if (!stub.is_null()) { | 859 if (!stub.is_null()) { |
860 set_target(*stub); | 860 set_target(*stub); |
861 #ifdef DEBUG | 861 #ifdef DEBUG |
862 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); | 862 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); |
863 #endif | 863 #endif |
864 } | 864 } |
865 return JSArray::cast(*object)->length(); | 865 return JSArray::cast(*object)->length(); |
866 } | 866 } |
867 | 867 |
868 // Use specialized code for getting prototype of functions. | 868 // Use specialized code for getting prototype of functions. |
869 if (object->IsJSFunction() && | 869 if (object->IsJSFunction() && |
870 name->Equals(isolate()->heap()->prototype_symbol()) && | 870 name->Equals(isolate()->heap()->prototype_string()) && |
871 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 871 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
872 Handle<Code> stub; | 872 Handle<Code> stub; |
873 if (state == UNINITIALIZED) { | 873 if (state == UNINITIALIZED) { |
874 stub = pre_monomorphic_stub(); | 874 stub = pre_monomorphic_stub(); |
875 } else if (state == PREMONOMORPHIC) { | 875 } else if (state == PREMONOMORPHIC) { |
876 FunctionPrototypeStub function_prototype_stub(kind()); | 876 FunctionPrototypeStub function_prototype_stub(kind()); |
877 stub = function_prototype_stub.GetCode(); | 877 stub = function_prototype_stub.GetCode(); |
878 } else if (state != MEGAMORPHIC) { | 878 } else if (state != MEGAMORPHIC) { |
879 ASSERT(state != GENERIC); | 879 ASSERT(state != GENERIC); |
880 stub = megamorphic_stub(); | 880 stub = megamorphic_stub(); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1081 return Handle<Code>::null(); | 1081 return Handle<Code>::null(); |
1082 } | 1082 } |
1083 | 1083 |
1084 | 1084 |
1085 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { | 1085 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
1086 // This helper implements a few common fast cases for converting | 1086 // This helper implements a few common fast cases for converting |
1087 // non-smi keys of keyed loads/stores to a smi or a string. | 1087 // non-smi keys of keyed loads/stores to a smi or a string. |
1088 if (key->IsHeapNumber()) { | 1088 if (key->IsHeapNumber()) { |
1089 double value = Handle<HeapNumber>::cast(key)->value(); | 1089 double value = Handle<HeapNumber>::cast(key)->value(); |
1090 if (isnan(value)) { | 1090 if (isnan(value)) { |
1091 key = isolate->factory()->nan_symbol(); | 1091 key = isolate->factory()->nan_string(); |
1092 } else { | 1092 } else { |
1093 int int_value = FastD2I(value); | 1093 int int_value = FastD2I(value); |
1094 if (value == int_value && Smi::IsValid(int_value)) { | 1094 if (value == int_value && Smi::IsValid(int_value)) { |
1095 key = Handle<Smi>(Smi::FromInt(int_value)); | 1095 key = Handle<Smi>(Smi::FromInt(int_value)); |
1096 } | 1096 } |
1097 } | 1097 } |
1098 } else if (key->IsUndefined()) { | 1098 } else if (key->IsUndefined()) { |
1099 key = isolate->factory()->undefined_symbol(); | 1099 key = isolate->factory()->undefined_string(); |
1100 } | 1100 } |
1101 return key; | 1101 return key; |
1102 } | 1102 } |
1103 | 1103 |
1104 | 1104 |
1105 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 1105 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, |
1106 Handle<Map> new_receiver_map) { | 1106 Handle<Map> new_receiver_map) { |
1107 ASSERT(!new_receiver_map.is_null()); | 1107 ASSERT(!new_receiver_map.is_null()); |
1108 for (int current = 0; current < receiver_maps->length(); ++current) { | 1108 for (int current = 0; current < receiver_maps->length(); ++current) { |
1109 if (!receiver_maps->at(current).is_null() && | 1109 if (!receiver_maps->at(current).is_null() && |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 | 1214 |
1215 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( | 1215 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( |
1216 &target_receiver_maps); | 1216 &target_receiver_maps); |
1217 } | 1217 } |
1218 | 1218 |
1219 | 1219 |
1220 MaybeObject* KeyedLoadIC::Load(State state, | 1220 MaybeObject* KeyedLoadIC::Load(State state, |
1221 Handle<Object> object, | 1221 Handle<Object> object, |
1222 Handle<Object> key, | 1222 Handle<Object> key, |
1223 ICMissMode miss_mode) { | 1223 ICMissMode miss_mode) { |
1224 // Check for values that can be converted into a symbol directly or | 1224 // Check for values that can be converted into an internalized string directly |
1225 // is representable as a smi. | 1225 // or is representable as a smi. |
1226 key = TryConvertKey(key, isolate()); | 1226 key = TryConvertKey(key, isolate()); |
1227 | 1227 |
1228 if (key->IsSymbol()) { | 1228 if (key->IsInternalizedString()) { |
1229 return LoadIC::Load(state, object, Handle<String>::cast(key)); | 1229 return LoadIC::Load(state, object, Handle<String>::cast(key)); |
1230 } | 1230 } |
1231 | 1231 |
1232 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1232 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
1233 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1233 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
1234 | 1234 |
1235 if (use_ic) { | 1235 if (use_ic) { |
1236 Handle<Code> stub = generic_stub(); | 1236 Handle<Code> stub = generic_stub(); |
1237 if (miss_mode != MISS_FORCE_GENERIC) { | 1237 if (miss_mode != MISS_FORCE_GENERIC) { |
1238 if (object->IsString() && key->IsNumber()) { | 1238 if (object->IsString() && key->IsNumber()) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1354 } | 1354 } |
1355 | 1355 |
1356 // If the object is undefined or null it's illegal to try to set any | 1356 // If the object is undefined or null it's illegal to try to set any |
1357 // properties on it; throw a TypeError in that case. | 1357 // properties on it; throw a TypeError in that case. |
1358 if (object->IsUndefined() || object->IsNull()) { | 1358 if (object->IsUndefined() || object->IsNull()) { |
1359 return TypeError("non_object_property_store", object, name); | 1359 return TypeError("non_object_property_store", object, name); |
1360 } | 1360 } |
1361 | 1361 |
1362 // The length property of string values is read-only. Throw in strict mode. | 1362 // The length property of string values is read-only. Throw in strict mode. |
1363 if (strict_mode == kStrictMode && object->IsString() && | 1363 if (strict_mode == kStrictMode && object->IsString() && |
1364 name->Equals(isolate()->heap()->length_symbol())) { | 1364 name->Equals(isolate()->heap()->length_string())) { |
1365 return TypeError("strict_read_only_property", object, name); | 1365 return TypeError("strict_read_only_property", object, name); |
1366 } | 1366 } |
1367 | 1367 |
1368 // Ignore other stores where the receiver is not a JSObject. | 1368 // Ignore other stores where the receiver is not a JSObject. |
1369 // TODO(1475): Must check prototype chains of object wrappers. | 1369 // TODO(1475): Must check prototype chains of object wrappers. |
1370 if (!object->IsJSObject()) return *value; | 1370 if (!object->IsJSObject()) return *value; |
1371 | 1371 |
1372 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1372 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1373 | 1373 |
1374 // Check if the given name is an array index. | 1374 // Check if the given name is an array index. |
1375 uint32_t index; | 1375 uint32_t index; |
1376 if (name->AsArrayIndex(&index)) { | 1376 if (name->AsArrayIndex(&index)) { |
1377 Handle<Object> result = | 1377 Handle<Object> result = |
1378 JSObject::SetElement(receiver, index, value, NONE, strict_mode); | 1378 JSObject::SetElement(receiver, index, value, NONE, strict_mode); |
1379 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1379 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1380 return *value; | 1380 return *value; |
1381 } | 1381 } |
1382 | 1382 |
1383 // Observed objects are always modified through the runtime. | 1383 // Observed objects are always modified through the runtime. |
1384 if (FLAG_harmony_observation && receiver->map()->is_observed()) { | 1384 if (FLAG_harmony_observation && receiver->map()->is_observed()) { |
1385 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1385 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
1386 } | 1386 } |
1387 | 1387 |
1388 // Use specialized code for setting the length of arrays with fast | 1388 // Use specialized code for setting the length of arrays with fast |
1389 // properties. Slow properties might indicate redefinition of the length | 1389 // properties. Slow properties might indicate redefinition of the length |
1390 // property. | 1390 // property. |
1391 if (FLAG_use_ic && | 1391 if (FLAG_use_ic && |
1392 receiver->IsJSArray() && | 1392 receiver->IsJSArray() && |
1393 name->Equals(isolate()->heap()->length_symbol()) && | 1393 name->Equals(isolate()->heap()->length_string()) && |
1394 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1394 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
1395 receiver->HasFastProperties()) { | 1395 receiver->HasFastProperties()) { |
1396 Handle<Code> stub = StoreArrayLengthStub(kind(), strict_mode).GetCode(); | 1396 Handle<Code> stub = StoreArrayLengthStub(kind(), strict_mode).GetCode(); |
1397 set_target(*stub); | 1397 set_target(*stub); |
1398 TRACE_IC("StoreIC", name, state, *stub); | 1398 TRACE_IC("StoreIC", name, state, *stub); |
1399 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1399 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
1400 } | 1400 } |
1401 | 1401 |
1402 if (receiver->IsJSGlobalProxy()) { | 1402 if (receiver->IsJSGlobalProxy()) { |
1403 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { | 1403 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1705 } | 1705 } |
1706 } | 1706 } |
1707 | 1707 |
1708 | 1708 |
1709 MaybeObject* KeyedStoreIC::Store(State state, | 1709 MaybeObject* KeyedStoreIC::Store(State state, |
1710 StrictModeFlag strict_mode, | 1710 StrictModeFlag strict_mode, |
1711 Handle<Object> object, | 1711 Handle<Object> object, |
1712 Handle<Object> key, | 1712 Handle<Object> key, |
1713 Handle<Object> value, | 1713 Handle<Object> value, |
1714 ICMissMode miss_mode) { | 1714 ICMissMode miss_mode) { |
1715 // Check for values that can be converted into a symbol directly or | 1715 // Check for values that can be converted into an internalized string directly |
1716 // is representable as a smi. | 1716 // or is representable as a smi. |
1717 key = TryConvertKey(key, isolate()); | 1717 key = TryConvertKey(key, isolate()); |
1718 | 1718 |
1719 if (key->IsSymbol()) { | 1719 if (key->IsInternalizedString()) { |
1720 return StoreIC::Store(state, | 1720 return StoreIC::Store(state, |
1721 strict_mode, | 1721 strict_mode, |
1722 object, | 1722 object, |
1723 Handle<String>::cast(key), | 1723 Handle<String>::cast(key), |
1724 value, | 1724 value, |
1725 JSReceiver::MAY_BE_STORE_FROM_KEYED); | 1725 JSReceiver::MAY_BE_STORE_FROM_KEYED); |
1726 } | 1726 } |
1727 | 1727 |
1728 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && | 1728 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && |
1729 !(FLAG_harmony_observation && object->IsJSObject() && | 1729 !(FLAG_harmony_observation && object->IsJSObject() && |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1918 ASSERT(args.length() == 2); | 1918 ASSERT(args.length() == 2); |
1919 JSArray* receiver = JSArray::cast(args[0]); | 1919 JSArray* receiver = JSArray::cast(args[0]); |
1920 Object* len = args[1]; | 1920 Object* len = args[1]; |
1921 | 1921 |
1922 // The generated code should filter out non-Smis before we get here. | 1922 // The generated code should filter out non-Smis before we get here. |
1923 ASSERT(len->IsSmi()); | 1923 ASSERT(len->IsSmi()); |
1924 | 1924 |
1925 #ifdef DEBUG | 1925 #ifdef DEBUG |
1926 // The length property has to be a writable callback property. | 1926 // The length property has to be a writable callback property. |
1927 LookupResult debug_lookup(isolate); | 1927 LookupResult debug_lookup(isolate); |
1928 receiver->LocalLookup(isolate->heap()->length_symbol(), &debug_lookup); | 1928 receiver->LocalLookup(isolate->heap()->length_string(), &debug_lookup); |
1929 ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly()); | 1929 ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly()); |
1930 #endif | 1930 #endif |
1931 | 1931 |
1932 Object* result; | 1932 Object* result; |
1933 MaybeObject* maybe_result = receiver->SetElementsLength(len); | 1933 MaybeObject* maybe_result = receiver->SetElementsLength(len); |
1934 if (!maybe_result->To(&result)) return maybe_result; | 1934 if (!maybe_result->To(&result)) return maybe_result; |
1935 | 1935 |
1936 return len; | 1936 return len; |
1937 } | 1937 } |
1938 | 1938 |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2362 } | 2362 } |
2363 | 2363 |
2364 | 2364 |
2365 const char* CompareIC::GetStateName(State state) { | 2365 const char* CompareIC::GetStateName(State state) { |
2366 switch (state) { | 2366 switch (state) { |
2367 case UNINITIALIZED: return "UNINITIALIZED"; | 2367 case UNINITIALIZED: return "UNINITIALIZED"; |
2368 case SMI: return "SMI"; | 2368 case SMI: return "SMI"; |
2369 case HEAP_NUMBER: return "HEAP_NUMBER"; | 2369 case HEAP_NUMBER: return "HEAP_NUMBER"; |
2370 case OBJECT: return "OBJECTS"; | 2370 case OBJECT: return "OBJECTS"; |
2371 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; | 2371 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; |
2372 case SYMBOL: return "SYMBOL"; | 2372 case INTERNALIZED_STRING: return "INTERNALIZED_STRING"; |
2373 case STRING: return "STRING"; | 2373 case STRING: return "STRING"; |
2374 case GENERIC: return "GENERIC"; | 2374 case GENERIC: return "GENERIC"; |
2375 default: | 2375 default: |
2376 UNREACHABLE(); | 2376 UNREACHABLE(); |
2377 return NULL; | 2377 return NULL; |
2378 } | 2378 } |
2379 } | 2379 } |
2380 | 2380 |
2381 | 2381 |
2382 static CompareIC::State InputState(CompareIC::State old_state, | 2382 static CompareIC::State InputState(CompareIC::State old_state, |
2383 Handle<Object> value) { | 2383 Handle<Object> value) { |
2384 switch (old_state) { | 2384 switch (old_state) { |
2385 case CompareIC::UNINITIALIZED: | 2385 case CompareIC::UNINITIALIZED: |
2386 if (value->IsSmi()) return CompareIC::SMI; | 2386 if (value->IsSmi()) return CompareIC::SMI; |
2387 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; | 2387 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; |
2388 if (value->IsSymbol()) return CompareIC::SYMBOL; | 2388 if (value->IsInternalizedString()) return CompareIC::INTERNALIZED_STRING; |
2389 if (value->IsString()) return CompareIC::STRING; | 2389 if (value->IsString()) return CompareIC::STRING; |
2390 if (value->IsJSObject()) return CompareIC::OBJECT; | 2390 if (value->IsJSObject()) return CompareIC::OBJECT; |
2391 break; | 2391 break; |
2392 case CompareIC::SMI: | 2392 case CompareIC::SMI: |
2393 if (value->IsSmi()) return CompareIC::SMI; | 2393 if (value->IsSmi()) return CompareIC::SMI; |
2394 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; | 2394 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; |
2395 break; | 2395 break; |
2396 case CompareIC::HEAP_NUMBER: | 2396 case CompareIC::HEAP_NUMBER: |
2397 if (value->IsNumber()) return CompareIC::HEAP_NUMBER; | 2397 if (value->IsNumber()) return CompareIC::HEAP_NUMBER; |
2398 break; | 2398 break; |
2399 case CompareIC::SYMBOL: | 2399 case CompareIC::INTERNALIZED_STRING: |
2400 if (value->IsSymbol()) return CompareIC::SYMBOL; | 2400 if (value->IsInternalizedString()) return CompareIC::INTERNALIZED_STRING; |
2401 if (value->IsString()) return CompareIC::STRING; | 2401 if (value->IsString()) return CompareIC::STRING; |
2402 break; | 2402 break; |
2403 case CompareIC::STRING: | 2403 case CompareIC::STRING: |
2404 if (value->IsSymbol() || value->IsString()) return CompareIC::STRING; | 2404 if (value->IsInternalizedString() || value->IsString()) |
| 2405 return CompareIC::STRING; |
2405 break; | 2406 break; |
2406 case CompareIC::OBJECT: | 2407 case CompareIC::OBJECT: |
2407 if (value->IsJSObject()) return CompareIC::OBJECT; | 2408 if (value->IsJSObject()) return CompareIC::OBJECT; |
2408 break; | 2409 break; |
2409 case CompareIC::GENERIC: | 2410 case CompareIC::GENERIC: |
2410 break; | 2411 break; |
2411 case CompareIC::KNOWN_OBJECTS: | 2412 case CompareIC::KNOWN_OBJECTS: |
2412 UNREACHABLE(); | 2413 UNREACHABLE(); |
2413 break; | 2414 break; |
2414 } | 2415 } |
(...skipping 12 matching lines...) Expand all Loading... |
2427 if (x->IsSmi() && y->IsSmi()) return SMI; | 2428 if (x->IsSmi() && y->IsSmi()) return SMI; |
2428 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBER; | 2429 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBER; |
2429 if (Token::IsOrderedRelationalCompareOp(op_)) { | 2430 if (Token::IsOrderedRelationalCompareOp(op_)) { |
2430 // Ordered comparisons treat undefined as NaN, so the | 2431 // Ordered comparisons treat undefined as NaN, so the |
2431 // HEAP_NUMBER stub will do the right thing. | 2432 // HEAP_NUMBER stub will do the right thing. |
2432 if ((x->IsNumber() && y->IsUndefined()) || | 2433 if ((x->IsNumber() && y->IsUndefined()) || |
2433 (y->IsNumber() && x->IsUndefined())) { | 2434 (y->IsNumber() && x->IsUndefined())) { |
2434 return HEAP_NUMBER; | 2435 return HEAP_NUMBER; |
2435 } | 2436 } |
2436 } | 2437 } |
2437 if (x->IsSymbol() && y->IsSymbol()) { | 2438 if (x->IsInternalizedString() && y->IsInternalizedString()) { |
2438 // We compare symbols as strings if we need to determine | 2439 // We compare internalized strings as plain ones if we need to determine |
2439 // the order in a non-equality compare. | 2440 // the order in a non-equality compare. |
2440 return Token::IsEqualityOp(op_) ? SYMBOL : STRING; | 2441 return Token::IsEqualityOp(op_) ? INTERNALIZED_STRING : STRING; |
2441 } | 2442 } |
2442 if (x->IsString() && y->IsString()) return STRING; | 2443 if (x->IsString() && y->IsString()) return STRING; |
2443 if (!Token::IsEqualityOp(op_)) return GENERIC; | 2444 if (!Token::IsEqualityOp(op_)) return GENERIC; |
2444 if (x->IsJSObject() && y->IsJSObject()) { | 2445 if (x->IsJSObject() && y->IsJSObject()) { |
2445 if (Handle<JSObject>::cast(x)->map() == | 2446 if (Handle<JSObject>::cast(x)->map() == |
2446 Handle<JSObject>::cast(y)->map() && | 2447 Handle<JSObject>::cast(y)->map() && |
2447 Token::IsEqualityOp(op_)) { | 2448 Token::IsEqualityOp(op_)) { |
2448 return KNOWN_OBJECTS; | 2449 return KNOWN_OBJECTS; |
2449 } else { | 2450 } else { |
2450 return OBJECT; | 2451 return OBJECT; |
2451 } | 2452 } |
2452 } | 2453 } |
2453 return GENERIC; | 2454 return GENERIC; |
2454 case SMI: | 2455 case SMI: |
2455 return x->IsNumber() && y->IsNumber() | 2456 return x->IsNumber() && y->IsNumber() |
2456 ? HEAP_NUMBER | 2457 ? HEAP_NUMBER |
2457 : GENERIC; | 2458 : GENERIC; |
2458 case SYMBOL: | 2459 case INTERNALIZED_STRING: |
2459 ASSERT(Token::IsEqualityOp(op_)); | 2460 ASSERT(Token::IsEqualityOp(op_)); |
2460 return x->IsString() && y->IsString() ? STRING : GENERIC; | 2461 return x->IsString() && y->IsString() ? STRING : GENERIC; |
2461 case HEAP_NUMBER: | 2462 case HEAP_NUMBER: |
2462 if (old_left == SMI && x->IsHeapNumber()) return HEAP_NUMBER; | 2463 if (old_left == SMI && x->IsHeapNumber()) return HEAP_NUMBER; |
2463 if (old_right == SMI && y->IsHeapNumber()) return HEAP_NUMBER; | 2464 if (old_right == SMI && y->IsHeapNumber()) return HEAP_NUMBER; |
2464 case STRING: | 2465 case STRING: |
2465 case OBJECT: | 2466 case OBJECT: |
2466 case KNOWN_OBJECTS: | 2467 case KNOWN_OBJECTS: |
2467 case GENERIC: | 2468 case GENERIC: |
2468 return GENERIC; | 2469 return GENERIC; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2552 #undef ADDR | 2553 #undef ADDR |
2553 }; | 2554 }; |
2554 | 2555 |
2555 | 2556 |
2556 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2557 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2557 return IC_utilities[id]; | 2558 return IC_utilities[id]; |
2558 } | 2559 } |
2559 | 2560 |
2560 | 2561 |
2561 } } // namespace v8::internal | 2562 } } // namespace v8::internal |
OLD | NEW |