| 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 1331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1342 name, receiver, global, cell, lookup->IsDontDelete()); | 1342 name, receiver, global, cell, lookup->IsDontDelete()); |
| 1343 } | 1343 } |
| 1344 // There is only one shared stub for loading normalized | 1344 // There is only one shared stub for loading normalized |
| 1345 // properties. It does not traverse the prototype chain, so the | 1345 // properties. It does not traverse the prototype chain, so the |
| 1346 // property must be found in the receiver for the stub to be | 1346 // property must be found in the receiver for the stub to be |
| 1347 // applicable. | 1347 // applicable. |
| 1348 if (!holder.is_identical_to(receiver)) break; | 1348 if (!holder.is_identical_to(receiver)) break; |
| 1349 return isolate()->stub_cache()->ComputeLoadNormal(name, receiver); | 1349 return isolate()->stub_cache()->ComputeLoadNormal(name, receiver); |
| 1350 case CALLBACKS: { | 1350 case CALLBACKS: { |
| 1351 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1351 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
| 1352 if (name->Equals(isolate()->heap()->length_string())) { |
| 1353 if (receiver->IsJSArray()) { |
| 1354 PropertyIndex lengthIndex = PropertyIndex::NewHeaderIndex( |
| 1355 JSArray::kLengthOffset / kPointerSize); |
| 1356 return isolate()->stub_cache()->ComputeLoadField( |
| 1357 name, receiver, receiver, lengthIndex, Representation::Tagged()); |
| 1358 } else if (receiver->IsJSTypedArray()) { |
| 1359 PropertyIndex lengthIndex = PropertyIndex::NewHeaderIndex( |
| 1360 JSTypedArray::kLengthOffset / kPointerSize); |
| 1361 return isolate()->stub_cache()->ComputeLoadField( |
| 1362 name, receiver, receiver, lengthIndex, Representation::Tagged()); |
| 1363 } |
| 1364 } |
| 1352 if (callback->IsExecutableAccessorInfo()) { | 1365 if (callback->IsExecutableAccessorInfo()) { |
| 1353 Handle<ExecutableAccessorInfo> info = | 1366 Handle<ExecutableAccessorInfo> info = |
| 1354 Handle<ExecutableAccessorInfo>::cast(callback); | 1367 Handle<ExecutableAccessorInfo>::cast(callback); |
| 1355 if (v8::ToCData<Address>(info->getter()) == 0) break; | 1368 if (v8::ToCData<Address>(info->getter()) == 0) break; |
| 1356 if (!info->IsCompatibleReceiver(*receiver)) break; | 1369 if (!info->IsCompatibleReceiver(*receiver)) break; |
| 1357 return isolate()->stub_cache()->ComputeLoadCallback( | 1370 return isolate()->stub_cache()->ComputeLoadCallback( |
| 1358 name, receiver, holder, info); | 1371 name, receiver, holder, info); |
| 1359 } else if (callback->IsAccessorPair()) { | 1372 } else if (callback->IsAccessorPair()) { |
| 1360 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), | 1373 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), |
| 1361 isolate()); | 1374 isolate()); |
| 1362 if (!getter->IsJSFunction()) break; | 1375 if (!getter->IsJSFunction()) break; |
| 1363 if (holder->IsGlobalObject()) break; | 1376 if (holder->IsGlobalObject()) break; |
| 1364 if (!holder->HasFastProperties()) break; | 1377 if (!holder->HasFastProperties()) break; |
| 1365 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1378 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 1366 CallOptimization call_optimization(function); | 1379 CallOptimization call_optimization(function); |
| 1367 if (call_optimization.is_simple_api_call() && | 1380 if (call_optimization.is_simple_api_call() && |
| 1368 call_optimization.IsCompatibleReceiver(*receiver) && | 1381 call_optimization.IsCompatibleReceiver(*receiver)) { |
| 1369 FLAG_js_accessor_ics) { | |
| 1370 return isolate()->stub_cache()->ComputeLoadCallback( | 1382 return isolate()->stub_cache()->ComputeLoadCallback( |
| 1371 name, receiver, holder, call_optimization); | 1383 name, receiver, holder, call_optimization); |
| 1372 } | 1384 } |
| 1373 return isolate()->stub_cache()->ComputeLoadViaGetter( | 1385 return isolate()->stub_cache()->ComputeLoadViaGetter( |
| 1374 name, receiver, holder, function); | 1386 name, receiver, holder, function); |
| 1375 } else if (receiver->IsJSArray() && | |
| 1376 name->Equals(isolate()->heap()->length_string())) { | |
| 1377 PropertyIndex lengthIndex = PropertyIndex::NewHeaderIndex( | |
| 1378 JSArray::kLengthOffset / kPointerSize); | |
| 1379 return isolate()->stub_cache()->ComputeLoadField( | |
| 1380 name, receiver, holder, lengthIndex, Representation::Tagged()); | |
| 1381 } | 1387 } |
| 1382 // TODO(dcarney): Handle correctly. | 1388 // TODO(dcarney): Handle correctly. |
| 1383 if (callback->IsDeclaredAccessorInfo()) break; | 1389 if (callback->IsDeclaredAccessorInfo()) break; |
| 1384 ASSERT(callback->IsForeign()); | 1390 ASSERT(callback->IsForeign()); |
| 1385 // No IC support for old-style native accessors. | 1391 // No IC support for old-style native accessors. |
| 1386 break; | 1392 break; |
| 1387 } | 1393 } |
| 1388 case INTERCEPTOR: | 1394 case INTERCEPTOR: |
| 1389 ASSERT(HasInterceptorGetter(*holder)); | 1395 ASSERT(HasInterceptorGetter(*holder)); |
| 1390 return isolate()->stub_cache()->ComputeLoadInterceptor( | 1396 return isolate()->stub_cache()->ComputeLoadInterceptor( |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1570 } else if (callback_object->IsAccessorPair()) { | 1576 } else if (callback_object->IsAccessorPair()) { |
| 1571 Handle<Object> getter( | 1577 Handle<Object> getter( |
| 1572 Handle<AccessorPair>::cast(callback_object)->getter(), | 1578 Handle<AccessorPair>::cast(callback_object)->getter(), |
| 1573 isolate()); | 1579 isolate()); |
| 1574 if (!getter->IsJSFunction()) break; | 1580 if (!getter->IsJSFunction()) break; |
| 1575 if (holder->IsGlobalObject()) break; | 1581 if (holder->IsGlobalObject()) break; |
| 1576 if (!holder->HasFastProperties()) break; | 1582 if (!holder->HasFastProperties()) break; |
| 1577 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1583 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 1578 CallOptimization call_optimization(function); | 1584 CallOptimization call_optimization(function); |
| 1579 if (call_optimization.is_simple_api_call() && | 1585 if (call_optimization.is_simple_api_call() && |
| 1580 call_optimization.IsCompatibleReceiver(*receiver) && | 1586 call_optimization.IsCompatibleReceiver(*receiver)) { |
| 1581 FLAG_js_accessor_ics) { | |
| 1582 return isolate()->stub_cache()->ComputeKeyedLoadCallback( | 1587 return isolate()->stub_cache()->ComputeKeyedLoadCallback( |
| 1583 name, receiver, holder, call_optimization); | 1588 name, receiver, holder, call_optimization); |
| 1584 } | 1589 } |
| 1585 } | 1590 } |
| 1586 break; | 1591 break; |
| 1587 } | 1592 } |
| 1588 case INTERCEPTOR: | 1593 case INTERCEPTOR: |
| 1589 ASSERT(HasInterceptorGetter(lookup->holder())); | 1594 ASSERT(HasInterceptorGetter(lookup->holder())); |
| 1590 return isolate()->stub_cache()->ComputeKeyedLoadInterceptor( | 1595 return isolate()->stub_cache()->ComputeKeyedLoadInterceptor( |
| 1591 name, receiver, holder); | 1596 name, receiver, holder); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1663 | 1668 |
| 1664 | 1669 |
| 1665 MaybeObject* StoreIC::Store(State state, | 1670 MaybeObject* StoreIC::Store(State state, |
| 1666 StrictModeFlag strict_mode, | 1671 StrictModeFlag strict_mode, |
| 1667 Handle<Object> object, | 1672 Handle<Object> object, |
| 1668 Handle<String> name, | 1673 Handle<String> name, |
| 1669 Handle<Object> value, | 1674 Handle<Object> value, |
| 1670 JSReceiver::StoreFromKeyed store_mode) { | 1675 JSReceiver::StoreFromKeyed store_mode) { |
| 1671 // Handle proxies. | 1676 // Handle proxies. |
| 1672 if (object->IsJSProxy()) { | 1677 if (object->IsJSProxy()) { |
| 1673 return JSReceiver::SetPropertyOrFail( | 1678 Handle<Object> result = JSReceiver::SetProperty( |
| 1674 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode); | 1679 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode); |
| 1680 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1681 return *result; |
| 1675 } | 1682 } |
| 1676 | 1683 |
| 1677 // If the object is undefined or null it's illegal to try to set any | 1684 // If the object is undefined or null it's illegal to try to set any |
| 1678 // properties on it; throw a TypeError in that case. | 1685 // properties on it; throw a TypeError in that case. |
| 1679 if (object->IsUndefined() || object->IsNull()) { | 1686 if (object->IsUndefined() || object->IsNull()) { |
| 1680 return TypeError("non_object_property_store", object, name); | 1687 return TypeError("non_object_property_store", object, name); |
| 1681 } | 1688 } |
| 1682 | 1689 |
| 1683 // The length property of string values is read-only. Throw in strict mode. | 1690 // The length property of string values is read-only. Throw in strict mode. |
| 1684 if (strict_mode == kStrictMode && object->IsString() && | 1691 if (strict_mode == kStrictMode && object->IsString() && |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1702 uint32_t index; | 1709 uint32_t index; |
| 1703 if (name->AsArrayIndex(&index)) { | 1710 if (name->AsArrayIndex(&index)) { |
| 1704 Handle<Object> result = | 1711 Handle<Object> result = |
| 1705 JSObject::SetElement(receiver, index, value, NONE, strict_mode); | 1712 JSObject::SetElement(receiver, index, value, NONE, strict_mode); |
| 1706 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1713 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1707 return *value; | 1714 return *value; |
| 1708 } | 1715 } |
| 1709 | 1716 |
| 1710 // Observed objects are always modified through the runtime. | 1717 // Observed objects are always modified through the runtime. |
| 1711 if (FLAG_harmony_observation && receiver->map()->is_observed()) { | 1718 if (FLAG_harmony_observation && receiver->map()->is_observed()) { |
| 1712 return JSReceiver::SetPropertyOrFail( | 1719 Handle<Object> result = JSReceiver::SetProperty( |
| 1713 receiver, name, value, NONE, strict_mode, store_mode); | 1720 receiver, name, value, NONE, strict_mode, store_mode); |
| 1721 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1722 return *result; |
| 1714 } | 1723 } |
| 1715 | 1724 |
| 1716 // Use specialized code for setting the length of arrays with fast | 1725 // Use specialized code for setting the length of arrays with fast |
| 1717 // properties. Slow properties might indicate redefinition of the length | 1726 // properties. Slow properties might indicate redefinition of the length |
| 1718 // property. Note that when redefined using Object.freeze, it's possible | 1727 // property. Note that when redefined using Object.freeze, it's possible |
| 1719 // to have fast properties but a read-only length. | 1728 // to have fast properties but a read-only length. |
| 1720 if (use_ic && | 1729 if (use_ic && |
| 1721 receiver->IsJSArray() && | 1730 receiver->IsJSArray() && |
| 1722 name->Equals(isolate()->heap()->length_string()) && | 1731 name->Equals(isolate()->heap()->length_string()) && |
| 1723 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1732 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
| 1724 receiver->HasFastProperties() && | 1733 receiver->HasFastProperties() && |
| 1725 !receiver->map()->is_frozen()) { | 1734 !receiver->map()->is_frozen()) { |
| 1726 Handle<Code> stub = | 1735 Handle<Code> stub = |
| 1727 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); | 1736 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); |
| 1728 set_target(*stub); | 1737 set_target(*stub); |
| 1729 TRACE_IC("StoreIC", name, state, *stub); | 1738 TRACE_IC("StoreIC", name, state, *stub); |
| 1730 return JSReceiver::SetPropertyOrFail( | 1739 Handle<Object> result = JSReceiver::SetProperty( |
| 1731 receiver, name, value, NONE, strict_mode, store_mode); | 1740 receiver, name, value, NONE, strict_mode, store_mode); |
| 1741 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1742 return *result; |
| 1732 } | 1743 } |
| 1733 | 1744 |
| 1734 if (receiver->IsJSGlobalProxy()) { | 1745 if (receiver->IsJSGlobalProxy()) { |
| 1735 if (use_ic && kind() != Code::KEYED_STORE_IC) { | 1746 if (use_ic && kind() != Code::KEYED_STORE_IC) { |
| 1736 // Generate a generic stub that goes to the runtime when we see a global | 1747 // Generate a generic stub that goes to the runtime when we see a global |
| 1737 // proxy as receiver. | 1748 // proxy as receiver. |
| 1738 Handle<Code> stub = (strict_mode == kStrictMode) | 1749 Handle<Code> stub = (strict_mode == kStrictMode) |
| 1739 ? global_proxy_stub_strict() | 1750 ? global_proxy_stub_strict() |
| 1740 : global_proxy_stub(); | 1751 : global_proxy_stub(); |
| 1741 set_target(*stub); | 1752 set_target(*stub); |
| 1742 TRACE_IC("StoreIC", name, state, *stub); | 1753 TRACE_IC("StoreIC", name, state, *stub); |
| 1743 } | 1754 } |
| 1744 return JSReceiver::SetPropertyOrFail( | 1755 Handle<Object> result = JSReceiver::SetProperty( |
| 1745 receiver, name, value, NONE, strict_mode, store_mode); | 1756 receiver, name, value, NONE, strict_mode, store_mode); |
| 1757 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1758 return *result; |
| 1746 } | 1759 } |
| 1747 | 1760 |
| 1748 LookupResult lookup(isolate()); | 1761 LookupResult lookup(isolate()); |
| 1749 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); | 1762 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); |
| 1750 if (!can_store && | 1763 if (!can_store && |
| 1751 strict_mode == kStrictMode && | 1764 strict_mode == kStrictMode && |
| 1752 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1765 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1753 IsUndeclaredGlobal(object)) { | 1766 IsUndeclaredGlobal(object)) { |
| 1754 // Strict mode doesn't allow setting non-existent global property. | 1767 // Strict mode doesn't allow setting non-existent global property. |
| 1755 return ReferenceError("not_defined", name); | 1768 return ReferenceError("not_defined", name); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1766 } else if (!name->IsCacheable(isolate()) || | 1779 } else if (!name->IsCacheable(isolate()) || |
| 1767 lookup.IsNormal() || | 1780 lookup.IsNormal() || |
| 1768 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1781 (lookup.IsField() && lookup.CanHoldValue(value))) { |
| 1769 Handle<Code> stub = (strict_mode == kStrictMode) ? generic_stub_strict() | 1782 Handle<Code> stub = (strict_mode == kStrictMode) ? generic_stub_strict() |
| 1770 : generic_stub(); | 1783 : generic_stub(); |
| 1771 set_target(*stub); | 1784 set_target(*stub); |
| 1772 } | 1785 } |
| 1773 } | 1786 } |
| 1774 | 1787 |
| 1775 // Set the property. | 1788 // Set the property. |
| 1776 return JSReceiver::SetPropertyOrFail( | 1789 Handle<Object> result = JSReceiver::SetProperty( |
| 1777 receiver, name, value, NONE, strict_mode, store_mode); | 1790 receiver, name, value, NONE, strict_mode, store_mode); |
| 1791 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1792 return *result; |
| 1778 } | 1793 } |
| 1779 | 1794 |
| 1780 | 1795 |
| 1781 void StoreIC::UpdateCaches(LookupResult* lookup, | 1796 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1782 State state, | 1797 State state, |
| 1783 StrictModeFlag strict_mode, | 1798 StrictModeFlag strict_mode, |
| 1784 Handle<JSObject> receiver, | 1799 Handle<JSObject> receiver, |
| 1785 Handle<String> name, | 1800 Handle<String> name, |
| 1786 Handle<Object> value) { | 1801 Handle<Object> value) { |
| 1787 ASSERT(!receiver->IsJSGlobalProxy()); | 1802 ASSERT(!receiver->IsJSGlobalProxy()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1839 name, receiver, holder, info, strict_mode); | 1854 name, receiver, holder, info, strict_mode); |
| 1840 } else if (callback->IsAccessorPair()) { | 1855 } else if (callback->IsAccessorPair()) { |
| 1841 Handle<Object> setter( | 1856 Handle<Object> setter( |
| 1842 Handle<AccessorPair>::cast(callback)->setter(), isolate()); | 1857 Handle<AccessorPair>::cast(callback)->setter(), isolate()); |
| 1843 if (!setter->IsJSFunction()) break; | 1858 if (!setter->IsJSFunction()) break; |
| 1844 if (holder->IsGlobalObject()) break; | 1859 if (holder->IsGlobalObject()) break; |
| 1845 if (!holder->HasFastProperties()) break; | 1860 if (!holder->HasFastProperties()) break; |
| 1846 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); | 1861 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); |
| 1847 CallOptimization call_optimization(function); | 1862 CallOptimization call_optimization(function); |
| 1848 if (call_optimization.is_simple_api_call() && | 1863 if (call_optimization.is_simple_api_call() && |
| 1849 call_optimization.IsCompatibleReceiver(*receiver) && | 1864 call_optimization.IsCompatibleReceiver(*receiver)) { |
| 1850 FLAG_js_accessor_ics) { | |
| 1851 return isolate()->stub_cache()->ComputeStoreCallback( | 1865 return isolate()->stub_cache()->ComputeStoreCallback( |
| 1852 name, receiver, holder, call_optimization, strict_mode); | 1866 name, receiver, holder, call_optimization, strict_mode); |
| 1853 } | 1867 } |
| 1854 return isolate()->stub_cache()->ComputeStoreViaSetter( | 1868 return isolate()->stub_cache()->ComputeStoreViaSetter( |
| 1855 name, receiver, holder, Handle<JSFunction>::cast(setter), | 1869 name, receiver, holder, Handle<JSFunction>::cast(setter), |
| 1856 strict_mode); | 1870 strict_mode); |
| 1857 } | 1871 } |
| 1858 // TODO(dcarney): Handle correctly. | 1872 // TODO(dcarney): Handle correctly. |
| 1859 if (callback->IsDeclaredAccessorInfo()) break; | 1873 if (callback->IsDeclaredAccessorInfo()) break; |
| 1860 ASSERT(callback->IsForeign()); | 1874 ASSERT(callback->IsForeign()); |
| (...skipping 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3149 #undef ADDR | 3163 #undef ADDR |
| 3150 }; | 3164 }; |
| 3151 | 3165 |
| 3152 | 3166 |
| 3153 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3167 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3154 return IC_utilities[id]; | 3168 return IC_utilities[id]; |
| 3155 } | 3169 } |
| 3156 | 3170 |
| 3157 | 3171 |
| 3158 } } // namespace v8::internal | 3172 } } // namespace v8::internal |
| OLD | NEW |