| 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 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 return CallICBase::LoadFunction(state, | 788 return CallICBase::LoadFunction(state, |
| 789 Code::kNoExtraICState, | 789 Code::kNoExtraICState, |
| 790 object, | 790 object, |
| 791 Handle<String>::cast(key)); | 791 Handle<String>::cast(key)); |
| 792 } | 792 } |
| 793 | 793 |
| 794 if (object->IsUndefined() || object->IsNull()) { | 794 if (object->IsUndefined() || object->IsNull()) { |
| 795 return TypeError("non_object_property_call", object, key); | 795 return TypeError("non_object_property_call", object, key); |
| 796 } | 796 } |
| 797 | 797 |
| 798 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { | 798 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 799 ASSERT(state != GENERIC); | 799 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
| 800 |
| 801 if (use_ic && state != MEGAMORPHIC) { |
| 800 int argc = target()->arguments_count(); | 802 int argc = target()->arguments_count(); |
| 801 Handle<Map> map = | 803 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 802 isolate()->factory()->non_strict_arguments_elements_map(); | 804 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
| 803 if (object->IsJSObject() && | 805 if (object->IsJSObject()) { |
| 804 Handle<JSObject>::cast(object)->elements()->map() == *map) { | 806 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 805 Handle<Code> code = isolate()->stub_cache()->ComputeCallArguments( | 807 if (receiver->elements()->map() == |
| 806 argc, Code::KEYED_CALL_IC); | 808 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 807 set_target(*code); | 809 stub = isolate()->stub_cache()->ComputeCallArguments(argc); |
| 808 TRACE_IC("KeyedCallIC", key, state, target()); | 810 } |
| 809 } else if (!object->IsAccessCheckNeeded()) { | |
| 810 Handle<Code> code = isolate()->stub_cache()->ComputeCallMegamorphic( | |
| 811 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | |
| 812 set_target(*code); | |
| 813 TRACE_IC("KeyedCallIC", key, state, target()); | |
| 814 } | 811 } |
| 812 ASSERT(!stub.is_null()); |
| 813 set_target(*stub); |
| 814 TRACE_IC("KeyedCallIC", key, state, target()); |
| 815 } | 815 } |
| 816 | 816 |
| 817 Handle<Object> result = GetProperty(object, key); | 817 Handle<Object> result = GetProperty(object, key); |
| 818 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 818 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 819 | 819 |
| 820 // Make receiver an object if the callee requires it. Strict mode or builtin | 820 // Make receiver an object if the callee requires it. Strict mode or builtin |
| 821 // functions do not wrap the receiver, non-strict functions and objects | 821 // functions do not wrap the receiver, non-strict functions and objects |
| 822 // called as functions do. | 822 // called as functions do. |
| 823 ReceiverToObjectIfRequired(result, object); | 823 ReceiverToObjectIfRequired(result, object); |
| 824 if (result->IsJSFunction()) return *result; | 824 if (result->IsJSFunction()) return *result; |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1236 Handle<Object> key, | 1236 Handle<Object> key, |
| 1237 ICMissMode miss_mode) { | 1237 ICMissMode miss_mode) { |
| 1238 // Check for values that can be converted into a symbol directly or | 1238 // Check for values that can be converted into a symbol directly or |
| 1239 // is representable as a smi. | 1239 // is representable as a smi. |
| 1240 key = TryConvertKey(key, isolate()); | 1240 key = TryConvertKey(key, isolate()); |
| 1241 | 1241 |
| 1242 if (key->IsSymbol()) { | 1242 if (key->IsSymbol()) { |
| 1243 return LoadIC::Load(state, object, Handle<String>::cast(key)); | 1243 return LoadIC::Load(state, object, Handle<String>::cast(key)); |
| 1244 } | 1244 } |
| 1245 | 1245 |
| 1246 // Do not use ICs for objects that require access checks (including | |
| 1247 // the global object). | |
| 1248 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1246 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 1247 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
| 1249 | 1248 |
| 1250 if (use_ic) { | 1249 if (use_ic) { |
| 1251 Handle<Code> stub = generic_stub(); | 1250 Handle<Code> stub = generic_stub(); |
| 1252 if (miss_mode != MISS_FORCE_GENERIC) { | 1251 if (miss_mode != MISS_FORCE_GENERIC) { |
| 1253 if (object->IsString() && key->IsNumber()) { | 1252 if (object->IsString() && key->IsNumber()) { |
| 1254 if (state == UNINITIALIZED) { | 1253 if (state == UNINITIALIZED) { |
| 1255 stub = string_stub(); | 1254 stub = string_stub(); |
| 1256 } | 1255 } |
| 1257 } else if (object->IsJSObject()) { | 1256 } else if (object->IsJSObject()) { |
| 1258 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1257 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1259 if (receiver->elements()->map() == | 1258 if (receiver->elements()->map() == |
| 1260 isolate()->heap()->non_strict_arguments_elements_map()) { | 1259 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1261 stub = non_strict_arguments_stub(); | 1260 stub = non_strict_arguments_stub(); |
| 1262 } else if (receiver->HasIndexedInterceptor()) { | 1261 } else if (receiver->HasIndexedInterceptor()) { |
| 1263 stub = indexed_interceptor_stub(); | 1262 stub = indexed_interceptor_stub(); |
| 1264 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1263 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
| 1265 stub = LoadElementStub(receiver); | 1264 stub = LoadElementStub(receiver); |
| 1266 } | 1265 } |
| 1267 } | 1266 } |
| 1268 } else { | 1267 } else { |
| 1269 TRACE_GENERIC_IC("KeyedLoadIC", "force generic"); | 1268 TRACE_GENERIC_IC("KeyedLoadIC", "force generic"); |
| 1270 } | 1269 } |
| 1271 if (!stub.is_null()) set_target(*stub); | 1270 ASSERT(!stub.is_null()); |
| 1271 set_target(*stub); |
| 1272 TRACE_IC("KeyedLoadIC", key, state, target()); |
| 1272 } | 1273 } |
| 1273 | 1274 |
| 1274 TRACE_IC("KeyedLoadIC", key, state, target()); | |
| 1275 | 1275 |
| 1276 // Get the property. | |
| 1277 return Runtime::GetObjectProperty(isolate(), object, key); | 1276 return Runtime::GetObjectProperty(isolate(), object, key); |
| 1278 } | 1277 } |
| 1279 | 1278 |
| 1280 | 1279 |
| 1281 Handle<Code> KeyedLoadIC::ComputeLoadMonomorphic(LookupResult* lookup, | 1280 Handle<Code> KeyedLoadIC::ComputeLoadMonomorphic(LookupResult* lookup, |
| 1282 Handle<JSObject> receiver, | 1281 Handle<JSObject> receiver, |
| 1283 Handle<String> name) { | 1282 Handle<String> name) { |
| 1284 // Bail out if we didn't find a result. | 1283 // Bail out if we didn't find a result. |
| 1285 if (!lookup->IsProperty()) return Handle<Code>::null(); | 1284 if (!lookup->IsProperty()) return Handle<Code>::null(); |
| 1286 | 1285 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1399 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
| 1401 } | 1400 } |
| 1402 | 1401 |
| 1403 // Use specialized code for setting the length of arrays with fast | 1402 // Use specialized code for setting the length of arrays with fast |
| 1404 // properties. Slow properties might indicate redefinition of the length | 1403 // properties. Slow properties might indicate redefinition of the length |
| 1405 // property. | 1404 // property. |
| 1406 if (FLAG_use_ic && | 1405 if (FLAG_use_ic && |
| 1407 receiver->IsJSArray() && | 1406 receiver->IsJSArray() && |
| 1408 name->Equals(isolate()->heap()->length_symbol()) && | 1407 name->Equals(isolate()->heap()->length_symbol()) && |
| 1409 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1408 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
| 1410 receiver->HasFastProperties() && | 1409 receiver->HasFastProperties()) { |
| 1411 kind() != Code::KEYED_STORE_IC) { | 1410 Handle<Code> stub = StoreArrayLengthStub(kind(), strict_mode).GetCode(); |
| 1412 Handle<Code> stub = (strict_mode == kStrictMode) | |
| 1413 ? isolate()->builtins()->StoreIC_ArrayLength_Strict() | |
| 1414 : isolate()->builtins()->StoreIC_ArrayLength(); | |
| 1415 set_target(*stub); | 1411 set_target(*stub); |
| 1416 TRACE_IC("StoreIC", name, state, *stub); | 1412 TRACE_IC("StoreIC", name, state, *stub); |
| 1417 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1413 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
| 1418 } | 1414 } |
| 1419 | 1415 |
| 1420 if (receiver->IsJSGlobalProxy()) { | 1416 if (receiver->IsJSGlobalProxy()) { |
| 1421 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { | 1417 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { |
| 1422 // Generate a generic stub that goes to the runtime when we see a global | 1418 // Generate a generic stub that goes to the runtime when we see a global |
| 1423 // proxy as receiver. | 1419 // proxy as receiver. |
| 1424 Handle<Code> stub = (strict_mode == kStrictMode) | 1420 Handle<Code> stub = (strict_mode == kStrictMode) |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1721 StrictModeFlag strict_mode, | 1717 StrictModeFlag strict_mode, |
| 1722 Handle<Object> object, | 1718 Handle<Object> object, |
| 1723 Handle<Object> key, | 1719 Handle<Object> key, |
| 1724 Handle<Object> value, | 1720 Handle<Object> value, |
| 1725 ICMissMode miss_mode) { | 1721 ICMissMode miss_mode) { |
| 1726 // Check for values that can be converted into a symbol directly or | 1722 // Check for values that can be converted into a symbol directly or |
| 1727 // is representable as a smi. | 1723 // is representable as a smi. |
| 1728 key = TryConvertKey(key, isolate()); | 1724 key = TryConvertKey(key, isolate()); |
| 1729 | 1725 |
| 1730 if (key->IsSymbol()) { | 1726 if (key->IsSymbol()) { |
| 1731 Handle<String> name = Handle<String>::cast(key); | |
| 1732 return StoreIC::Store(state, | 1727 return StoreIC::Store(state, |
| 1733 strict_mode, | 1728 strict_mode, |
| 1734 object, | 1729 object, |
| 1735 name, | 1730 Handle<String>::cast(key), |
| 1736 value, | 1731 value, |
| 1737 JSReceiver::MAY_BE_STORE_FROM_KEYED); | 1732 JSReceiver::MAY_BE_STORE_FROM_KEYED); |
| 1738 } | 1733 } |
| 1739 | 1734 |
| 1740 // Do not use ICs for objects that require access checks (including | |
| 1741 // the global object), or are observed. | |
| 1742 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && | 1735 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && |
| 1743 !(FLAG_harmony_observation && object->IsJSObject() && | 1736 !(FLAG_harmony_observation && object->IsJSObject() && |
| 1744 JSObject::cast(*object)->map()->is_observed()); | 1737 JSObject::cast(*object)->map()->is_observed()); |
| 1745 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1738 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
| 1746 | 1739 |
| 1747 if (use_ic) { | 1740 if (use_ic) { |
| 1748 Handle<Code> stub = (strict_mode == kStrictMode) | 1741 Handle<Code> stub = (strict_mode == kStrictMode) |
| 1749 ? generic_stub_strict() | 1742 ? generic_stub_strict() |
| 1750 : generic_stub(); | 1743 : generic_stub(); |
| 1751 if (object->IsJSObject()) { | 1744 if (miss_mode != MISS_FORCE_GENERIC) { |
| 1752 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1745 if (object->IsJSObject()) { |
| 1753 if (receiver->elements()->map() == | 1746 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1754 isolate()->heap()->non_strict_arguments_elements_map()) { | 1747 if (receiver->elements()->map() == |
| 1755 stub = non_strict_arguments_stub(); | 1748 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1756 } else if (miss_mode != MISS_FORCE_GENERIC) { | 1749 stub = non_strict_arguments_stub(); |
| 1757 if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1750 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
| 1758 StubKind stub_kind = GetStubKind(receiver, key, value); | 1751 StubKind stub_kind = GetStubKind(receiver, key, value); |
| 1759 stub = StoreElementStub(receiver, stub_kind, strict_mode); | 1752 stub = StoreElementStub(receiver, stub_kind, strict_mode); |
| 1760 } | 1753 } |
| 1761 } else { | |
| 1762 TRACE_GENERIC_IC("KeyedStoreIC", "force generic"); | |
| 1763 } | 1754 } |
| 1755 } else { |
| 1756 TRACE_GENERIC_IC("KeyedStoreIC", "force generic"); |
| 1764 } | 1757 } |
| 1765 if (!stub.is_null()) set_target(*stub); | 1758 ASSERT(!stub.is_null()); |
| 1759 set_target(*stub); |
| 1760 TRACE_IC("KeyedStoreIC", key, state, target()); |
| 1766 } | 1761 } |
| 1767 | 1762 |
| 1768 TRACE_IC("KeyedStoreIC", key, state, target()); | |
| 1769 | |
| 1770 // Set the property. | |
| 1771 return Runtime::SetObjectProperty( | 1763 return Runtime::SetObjectProperty( |
| 1772 isolate(), object , key, value, NONE, strict_mode); | 1764 isolate(), object , key, value, NONE, strict_mode); |
| 1773 } | 1765 } |
| 1774 | 1766 |
| 1775 | 1767 |
| 1776 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, | 1768 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
| 1777 StrictModeFlag strict_mode, | 1769 StrictModeFlag strict_mode, |
| 1778 Handle<JSObject> receiver, | 1770 Handle<JSObject> receiver, |
| 1779 Handle<String> name) { | 1771 Handle<String> name) { |
| 1780 // If the property has a non-field type allowing map transitions | 1772 // If the property has a non-field type allowing map transitions |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1929 ASSERT(len->IsSmi()); | 1921 ASSERT(len->IsSmi()); |
| 1930 | 1922 |
| 1931 #ifdef DEBUG | 1923 #ifdef DEBUG |
| 1932 // The length property has to be a writable callback property. | 1924 // The length property has to be a writable callback property. |
| 1933 LookupResult debug_lookup(isolate); | 1925 LookupResult debug_lookup(isolate); |
| 1934 receiver->LocalLookup(isolate->heap()->length_symbol(), &debug_lookup); | 1926 receiver->LocalLookup(isolate->heap()->length_symbol(), &debug_lookup); |
| 1935 ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly()); | 1927 ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly()); |
| 1936 #endif | 1928 #endif |
| 1937 | 1929 |
| 1938 Object* result; | 1930 Object* result; |
| 1939 { MaybeObject* maybe_result = receiver->SetElementsLength(len); | 1931 MaybeObject* maybe_result = receiver->SetElementsLength(len); |
| 1940 if (!maybe_result->ToObject(&result)) return maybe_result; | 1932 if (!maybe_result->To(&result)) return maybe_result; |
| 1941 } | 1933 |
| 1942 return len; | 1934 return len; |
| 1943 } | 1935 } |
| 1944 | 1936 |
| 1945 | 1937 |
| 1946 // Extend storage is called in a store inline cache when | 1938 // Extend storage is called in a store inline cache when |
| 1947 // it is necessary to extend the properties array of a | 1939 // it is necessary to extend the properties array of a |
| 1948 // JSObject. | 1940 // JSObject. |
| 1949 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) { | 1941 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) { |
| 1950 NoHandleAllocation na; | 1942 NoHandleAllocation na; |
| 1951 ASSERT(args.length() == 3); | 1943 ASSERT(args.length() == 3); |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2558 #undef ADDR | 2550 #undef ADDR |
| 2559 }; | 2551 }; |
| 2560 | 2552 |
| 2561 | 2553 |
| 2562 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2554 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2563 return IC_utilities[id]; | 2555 return IC_utilities[id]; |
| 2564 } | 2556 } |
| 2565 | 2557 |
| 2566 | 2558 |
| 2567 } } // namespace v8::internal | 2559 } } // namespace v8::internal |
| OLD | NEW |