| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1729 return TypeError("non_object_property_store", object, name); | 1729 return TypeError("non_object_property_store", object, name); |
| 1730 } | 1730 } |
| 1731 | 1731 |
| 1732 // Ignore stores where the receiver is not a JSObject. | 1732 // Ignore stores where the receiver is not a JSObject. |
| 1733 if (!object->IsJSObject()) return *value; | 1733 if (!object->IsJSObject()) return *value; |
| 1734 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1734 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1735 | 1735 |
| 1736 // Check if the given name is an array index. | 1736 // Check if the given name is an array index. |
| 1737 uint32_t index; | 1737 uint32_t index; |
| 1738 if (name->AsArrayIndex(&index)) { | 1738 if (name->AsArrayIndex(&index)) { |
| 1739 HandleScope scope(isolate()); | |
| 1740 Handle<Object> result = SetElement(receiver, index, value, strict_mode); | 1739 Handle<Object> result = SetElement(receiver, index, value, strict_mode); |
| 1741 if (result.is_null()) return Failure::Exception(); | 1740 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1742 return *value; | 1741 return *value; |
| 1743 } | 1742 } |
| 1744 | 1743 |
| 1745 // Lookup the property locally in the receiver. | 1744 // Lookup the property locally in the receiver. |
| 1746 LookupResult lookup(isolate()); | 1745 LookupResult lookup(isolate()); |
| 1747 receiver->LocalLookup(*name, &lookup); | 1746 receiver->LocalLookup(*name, &lookup); |
| 1748 | 1747 |
| 1749 // Update inline cache and stub cache. | 1748 // Update inline cache and stub cache. |
| 1750 if (FLAG_use_ic) { | 1749 if (FLAG_use_ic) { |
| 1751 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1750 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
| 1752 } | 1751 } |
| 1753 | 1752 |
| 1754 // Set the property. | 1753 // Set the property. |
| 1755 return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1754 return receiver->SetProperty(*name, *value, NONE, strict_mode); |
| 1756 } | 1755 } |
| 1757 | 1756 |
| 1758 // Do not use ICs for objects that require access checks (including | 1757 // Do not use ICs for objects that require access checks (including |
| 1759 // the global object). | 1758 // the global object). |
| 1760 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1759 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 1761 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1760 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
| 1762 | 1761 |
| 1763 if (use_ic) { | 1762 if (use_ic) { |
| 1764 Code* stub = (strict_mode == kStrictMode) | 1763 Handle<Code> stub = (strict_mode == kStrictMode) |
| 1765 ? generic_stub_strict() | 1764 ? generic_stub_strict() |
| 1766 : generic_stub(); | 1765 : generic_stub(); |
| 1767 if (object->IsJSObject()) { | 1766 if (object->IsJSObject()) { |
| 1768 JSObject* receiver = JSObject::cast(*object); | 1767 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1769 Heap* heap = Handle<JSObject>::cast(object)->GetHeap(); | 1768 if (receiver->elements()->map() == |
| 1770 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map(); | 1769 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1771 if (elements_map == heap->non_strict_arguments_elements_map()) { | |
| 1772 stub = non_strict_arguments_stub(); | 1770 stub = non_strict_arguments_stub(); |
| 1773 } else if (!force_generic) { | 1771 } else if (!force_generic) { |
| 1774 if (key->IsSmi() && (target() != non_strict_arguments_stub())) { | 1772 if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
| 1775 StubKind stub_kind = STORE_NO_TRANSITION; | 1773 StubKind stub_kind = STORE_NO_TRANSITION; |
| 1776 if (receiver->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) { | 1774 if (receiver->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) { |
| 1777 if (value->IsHeapNumber()) { | 1775 if (value->IsHeapNumber()) { |
| 1778 stub_kind = STORE_TRANSITION_SMI_TO_DOUBLE; | 1776 stub_kind = STORE_TRANSITION_SMI_TO_DOUBLE; |
| 1779 } else if (value->IsHeapObject()) { | 1777 } else if (value->IsHeapObject()) { |
| 1780 stub_kind = STORE_TRANSITION_SMI_TO_OBJECT; | 1778 stub_kind = STORE_TRANSITION_SMI_TO_OBJECT; |
| 1781 } | 1779 } |
| 1782 } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) { | 1780 } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) { |
| 1783 if (!value->IsSmi() && !value->IsHeapNumber()) { | 1781 if (!value->IsSmi() && !value->IsHeapNumber()) { |
| 1784 stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT; | 1782 stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT; |
| 1785 } | 1783 } |
| 1786 } | 1784 } |
| 1787 HandleScope scope(isolate()); | 1785 stub = ComputeStub(receiver, stub_kind, strict_mode, stub); |
| 1788 MaybeObject* maybe_stub = ComputeStub(receiver, | |
| 1789 stub_kind, | |
| 1790 strict_mode, | |
| 1791 stub); | |
| 1792 stub = maybe_stub->IsFailure() ? | |
| 1793 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); | |
| 1794 } | 1786 } |
| 1795 } | 1787 } |
| 1796 } | 1788 } |
| 1797 if (stub != NULL) set_target(stub); | 1789 if (!stub.is_null()) set_target(*stub); |
| 1798 } | 1790 } |
| 1799 | 1791 |
| 1800 #ifdef DEBUG | 1792 #ifdef DEBUG |
| 1801 TraceIC("KeyedStoreIC", key, state, target()); | 1793 TraceIC("KeyedStoreIC", key, state, target()); |
| 1802 #endif | 1794 #endif |
| 1803 | 1795 |
| 1804 // Set the property. | 1796 // Set the property. |
| 1805 return Runtime::SetObjectProperty( | 1797 return Runtime::SetObjectProperty( |
| 1806 isolate(), object , key, value, NONE, strict_mode); | 1798 isolate(), object , key, value, NONE, strict_mode); |
| 1807 } | 1799 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1824 if (lookup->IsReadOnly()) return; | 1816 if (lookup->IsReadOnly()) return; |
| 1825 | 1817 |
| 1826 // If the property has a non-field type allowing map transitions | 1818 // If the property has a non-field type allowing map transitions |
| 1827 // where there is extra room in the object, we leave the IC in its | 1819 // where there is extra room in the object, we leave the IC in its |
| 1828 // current state. | 1820 // current state. |
| 1829 PropertyType type = lookup->type(); | 1821 PropertyType type = lookup->type(); |
| 1830 | 1822 |
| 1831 // Compute the code stub for this store; used for rewriting to | 1823 // Compute the code stub for this store; used for rewriting to |
| 1832 // monomorphic state and making sure that the code stub is in the | 1824 // monomorphic state and making sure that the code stub is in the |
| 1833 // stub cache. | 1825 // stub cache. |
| 1834 MaybeObject* maybe_code = NULL; | 1826 Handle<Code> code; |
| 1835 Object* code = NULL; | |
| 1836 | 1827 |
| 1837 switch (type) { | 1828 switch (type) { |
| 1838 case FIELD: { | 1829 case FIELD: |
| 1839 maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( | 1830 code = isolate()->stub_cache()->ComputeKeyedStoreField( |
| 1840 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); | 1831 name, receiver, lookup->GetFieldIndex(), |
| 1832 Handle<Map>::null(), strict_mode); |
| 1841 break; | 1833 break; |
| 1842 } | 1834 case MAP_TRANSITION: |
| 1843 case MAP_TRANSITION: { | |
| 1844 if (lookup->GetAttributes() == NONE) { | 1835 if (lookup->GetAttributes() == NONE) { |
| 1845 HandleScope scope(isolate()); | |
| 1846 ASSERT(type == MAP_TRANSITION); | 1836 ASSERT(type == MAP_TRANSITION); |
| 1847 Handle<Map> transition(lookup->GetTransitionMap()); | 1837 Handle<Map> transition(lookup->GetTransitionMap()); |
| 1848 int index = transition->PropertyIndexFor(*name); | 1838 int index = transition->PropertyIndexFor(*name); |
| 1849 maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( | 1839 code = isolate()->stub_cache()->ComputeKeyedStoreField( |
| 1850 *name, *receiver, index, *transition, strict_mode); | 1840 name, receiver, index, transition, strict_mode); |
| 1851 break; | 1841 break; |
| 1852 } | 1842 } |
| 1853 // fall through. | 1843 // fall through. |
| 1854 } | 1844 default: |
| 1855 default: { | |
| 1856 // Always rewrite to the generic case so that we do not | 1845 // Always rewrite to the generic case so that we do not |
| 1857 // repeatedly try to rewrite. | 1846 // repeatedly try to rewrite. |
| 1858 maybe_code = (strict_mode == kStrictMode) | 1847 code = (strict_mode == kStrictMode) |
| 1859 ? generic_stub_strict() | 1848 ? generic_stub_strict() |
| 1860 : generic_stub(); | 1849 : generic_stub(); |
| 1861 break; | 1850 break; |
| 1862 } | |
| 1863 } | 1851 } |
| 1864 | 1852 |
| 1865 // If we're unable to compute the stub (not enough memory left), we | 1853 ASSERT(!code.is_null()); |
| 1866 // simply avoid updating the caches. | |
| 1867 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | |
| 1868 | 1854 |
| 1869 // Patch the call site depending on the state of the cache. Make | 1855 // Patch the call site depending on the state of the cache. Make |
| 1870 // sure to always rewrite from monomorphic to megamorphic. | 1856 // sure to always rewrite from monomorphic to megamorphic. |
| 1871 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); | 1857 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); |
| 1872 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { | 1858 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { |
| 1873 set_target(Code::cast(code)); | 1859 set_target(*code); |
| 1874 } else if (state == MONOMORPHIC) { | 1860 } else if (state == MONOMORPHIC) { |
| 1875 set_target((strict_mode == kStrictMode) | 1861 set_target((strict_mode == kStrictMode) |
| 1876 ? megamorphic_stub_strict() | 1862 ? *megamorphic_stub_strict() |
| 1877 : megamorphic_stub()); | 1863 : *megamorphic_stub()); |
| 1878 } | 1864 } |
| 1879 | 1865 |
| 1880 #ifdef DEBUG | 1866 #ifdef DEBUG |
| 1881 TraceIC("KeyedStoreIC", name, state, target()); | 1867 TraceIC("KeyedStoreIC", name, state, target()); |
| 1882 #endif | 1868 #endif |
| 1883 } | 1869 } |
| 1884 | 1870 |
| 1885 | 1871 |
| 1886 // ---------------------------------------------------------------------------- | 1872 // ---------------------------------------------------------------------------- |
| 1887 // Static IC stub generators. | 1873 // Static IC stub generators. |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2028 object->set_properties(new_storage); | 2014 object->set_properties(new_storage); |
| 2029 object->set_map(transition); | 2015 object->set_map(transition); |
| 2030 | 2016 |
| 2031 // Return the stored value. | 2017 // Return the stored value. |
| 2032 return value; | 2018 return value; |
| 2033 } | 2019 } |
| 2034 | 2020 |
| 2035 | 2021 |
| 2036 // Used from ic-<arch>.cc. | 2022 // Used from ic-<arch>.cc. |
| 2037 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { | 2023 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { |
| 2038 NoHandleAllocation na; | 2024 HandleScope scope(isolate); |
| 2039 ASSERT(args.length() == 3); | 2025 ASSERT(args.length() == 3); |
| 2040 KeyedStoreIC ic(isolate); | 2026 KeyedStoreIC ic(isolate); |
| 2041 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2027 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| 2042 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2028 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
| 2043 return ic.Store(state, | 2029 return ic.Store(state, |
| 2044 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 2030 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), |
| 2045 args.at<Object>(0), | 2031 args.at<Object>(0), |
| 2046 args.at<Object>(1), | 2032 args.at<Object>(1), |
| 2047 args.at<Object>(2), | 2033 args.at<Object>(2), |
| 2048 false); | 2034 false); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2062 return Runtime::SetObjectProperty(isolate, | 2048 return Runtime::SetObjectProperty(isolate, |
| 2063 object, | 2049 object, |
| 2064 key, | 2050 key, |
| 2065 value, | 2051 value, |
| 2066 NONE, | 2052 NONE, |
| 2067 strict_mode); | 2053 strict_mode); |
| 2068 } | 2054 } |
| 2069 | 2055 |
| 2070 | 2056 |
| 2071 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { | 2057 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { |
| 2072 NoHandleAllocation na; | 2058 HandleScope scope(isolate); |
| 2073 ASSERT(args.length() == 3); | 2059 ASSERT(args.length() == 3); |
| 2074 KeyedStoreIC ic(isolate); | 2060 KeyedStoreIC ic(isolate); |
| 2075 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2061 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| 2076 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2062 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
| 2077 return ic.Store(state, | 2063 return ic.Store(state, |
| 2078 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 2064 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), |
| 2079 args.at<Object>(0), | 2065 args.at<Object>(0), |
| 2080 args.at<Object>(1), | 2066 args.at<Object>(1), |
| 2081 args.at<Object>(2), | 2067 args.at<Object>(2), |
| 2082 true); | 2068 true); |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2497 #undef ADDR | 2483 #undef ADDR |
| 2498 }; | 2484 }; |
| 2499 | 2485 |
| 2500 | 2486 |
| 2501 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2487 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2502 return IC_utilities[id]; | 2488 return IC_utilities[id]; |
| 2503 } | 2489 } |
| 2504 | 2490 |
| 2505 | 2491 |
| 2506 } } // namespace v8::internal | 2492 } } // namespace v8::internal |
| OLD | NEW |