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 |