OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 1748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1759 } | 1759 } |
1760 | 1760 |
1761 // Check that the left hand side is a JS object and load its map as a side | 1761 // Check that the left hand side is a JS object and load its map as a side |
1762 // effect. | 1762 // effect. |
1763 Register map = x12; | 1763 Register map = x12; |
1764 __ JumpIfSmi(object, ¬_js_object); | 1764 __ JumpIfSmi(object, ¬_js_object); |
1765 __ IsObjectJSObjectType(object, map, scratch2, ¬_js_object); | 1765 __ IsObjectJSObjectType(object, map, scratch2, ¬_js_object); |
1766 | 1766 |
1767 // If there is a call site cache, don't look in the global cache, but do the | 1767 // If there is a call site cache, don't look in the global cache, but do the |
1768 // real lookup and update the call site cache. | 1768 // real lookup and update the call site cache. |
1769 if (!HasCallSiteInlineCheck()) { | 1769 if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) { |
1770 Label miss; | 1770 Label miss; |
1771 __ JumpIfNotRoot(function, Heap::kInstanceofCacheFunctionRootIndex, &miss); | 1771 __ JumpIfNotRoot(function, Heap::kInstanceofCacheFunctionRootIndex, &miss); |
1772 __ JumpIfNotRoot(map, Heap::kInstanceofCacheMapRootIndex, &miss); | 1772 __ JumpIfNotRoot(map, Heap::kInstanceofCacheMapRootIndex, &miss); |
1773 __ LoadRoot(result, Heap::kInstanceofCacheAnswerRootIndex); | 1773 __ LoadRoot(result, Heap::kInstanceofCacheAnswerRootIndex); |
1774 __ Ret(); | 1774 __ Ret(); |
1775 __ Bind(&miss); | 1775 __ Bind(&miss); |
1776 } | 1776 } |
1777 | 1777 |
1778 // Get the prototype of the function. | 1778 // Get the prototype of the function. |
1779 Register prototype = x13; | 1779 Register prototype = x13; |
(...skipping 11 matching lines...) Expand all Loading... |
1791 __ GetRelocatedValueLocation(map_check_site, scratch1); | 1791 __ GetRelocatedValueLocation(map_check_site, scratch1); |
1792 // We have a cell, so need another level of dereferencing. | 1792 // We have a cell, so need another level of dereferencing. |
1793 __ Ldr(scratch1, MemOperand(scratch1)); | 1793 __ Ldr(scratch1, MemOperand(scratch1)); |
1794 __ Str(map, FieldMemOperand(scratch1, Cell::kValueOffset)); | 1794 __ Str(map, FieldMemOperand(scratch1, Cell::kValueOffset)); |
1795 } else { | 1795 } else { |
1796 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); | 1796 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); |
1797 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); | 1797 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); |
1798 } | 1798 } |
1799 | 1799 |
1800 Label return_true, return_result; | 1800 Label return_true, return_result; |
| 1801 Register smi_value = scratch1; |
1801 { | 1802 { |
1802 // Loop through the prototype chain looking for the function prototype. | 1803 // Loop through the prototype chain looking for the function prototype. |
1803 Register chain_map = x1; | 1804 Register chain_map = x1; |
1804 Register chain_prototype = x14; | 1805 Register chain_prototype = x14; |
1805 Register null_value = x15; | 1806 Register null_value = x15; |
1806 Label loop; | 1807 Label loop; |
1807 __ Ldr(chain_prototype, FieldMemOperand(map, Map::kPrototypeOffset)); | 1808 __ Ldr(chain_prototype, FieldMemOperand(map, Map::kPrototypeOffset)); |
1808 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 1809 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
1809 // Speculatively set a result. | 1810 // Speculatively set a result. |
1810 __ Mov(result, res_false); | 1811 __ Mov(result, res_false); |
| 1812 if (!HasCallSiteInlineCheck() && ReturnTrueFalseObject()) { |
| 1813 // Value to store in the cache cannot be an object. |
| 1814 __ Mov(smi_value, Smi::FromInt(1)); |
| 1815 } |
1811 | 1816 |
1812 __ Bind(&loop); | 1817 __ Bind(&loop); |
1813 | 1818 |
1814 // If the chain prototype is the object prototype, return true. | 1819 // If the chain prototype is the object prototype, return true. |
1815 __ Cmp(chain_prototype, prototype); | 1820 __ Cmp(chain_prototype, prototype); |
1816 __ B(eq, &return_true); | 1821 __ B(eq, &return_true); |
1817 | 1822 |
1818 // If the chain prototype is null, we've reached the end of the chain, so | 1823 // If the chain prototype is null, we've reached the end of the chain, so |
1819 // return false. | 1824 // return false. |
1820 __ Cmp(chain_prototype, null_value); | 1825 __ Cmp(chain_prototype, null_value); |
1821 __ B(eq, &return_result); | 1826 __ B(eq, &return_result); |
1822 | 1827 |
1823 // Otherwise, load the next prototype in the chain, and loop. | 1828 // Otherwise, load the next prototype in the chain, and loop. |
1824 __ Ldr(chain_map, FieldMemOperand(chain_prototype, HeapObject::kMapOffset)); | 1829 __ Ldr(chain_map, FieldMemOperand(chain_prototype, HeapObject::kMapOffset)); |
1825 __ Ldr(chain_prototype, FieldMemOperand(chain_map, Map::kPrototypeOffset)); | 1830 __ Ldr(chain_prototype, FieldMemOperand(chain_map, Map::kPrototypeOffset)); |
1826 __ B(&loop); | 1831 __ B(&loop); |
1827 } | 1832 } |
1828 | 1833 |
1829 // Return sequence when no arguments are on the stack. | 1834 // Return sequence when no arguments are on the stack. |
1830 // We cannot fall through to here. | 1835 // We cannot fall through to here. |
1831 __ Bind(&return_true); | 1836 __ Bind(&return_true); |
1832 __ Mov(result, res_true); | 1837 __ Mov(result, res_true); |
| 1838 if (!HasCallSiteInlineCheck() && ReturnTrueFalseObject()) { |
| 1839 // Value to store in the cache cannot be an object. |
| 1840 __ Mov(smi_value, Smi::FromInt(0)); |
| 1841 } |
1833 __ Bind(&return_result); | 1842 __ Bind(&return_result); |
1834 if (HasCallSiteInlineCheck()) { | 1843 if (HasCallSiteInlineCheck()) { |
1835 DCHECK(ReturnTrueFalseObject()); | 1844 DCHECK(ReturnTrueFalseObject()); |
1836 __ Add(map_check_site, map_check_site, kDeltaToLoadBoolResult); | 1845 __ Add(map_check_site, map_check_site, kDeltaToLoadBoolResult); |
1837 __ GetRelocatedValueLocation(map_check_site, scratch2); | 1846 __ GetRelocatedValueLocation(map_check_site, scratch2); |
1838 __ Str(result, MemOperand(scratch2)); | 1847 __ Str(result, MemOperand(scratch2)); |
1839 } else { | 1848 } else { |
1840 __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex); | 1849 Register cached_value = ReturnTrueFalseObject() ? smi_value : result; |
| 1850 __ StoreRoot(cached_value, Heap::kInstanceofCacheAnswerRootIndex); |
1841 } | 1851 } |
1842 __ Ret(); | 1852 __ Ret(); |
1843 | 1853 |
1844 Label object_not_null, object_not_null_or_smi; | 1854 Label object_not_null, object_not_null_or_smi; |
1845 | 1855 |
1846 __ Bind(¬_js_object); | 1856 __ Bind(¬_js_object); |
1847 Register object_type = x14; | 1857 Register object_type = x14; |
1848 // x0 result result return register (uninit) | 1858 // x0 result result return register (uninit) |
1849 // x10 function pointer to function | 1859 // x10 function pointer to function |
1850 // x11 object pointer to object | 1860 // x11 object pointer to object |
(...skipping 3558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5409 MemOperand(fp, 6 * kPointerSize), | 5419 MemOperand(fp, 6 * kPointerSize), |
5410 NULL); | 5420 NULL); |
5411 } | 5421 } |
5412 | 5422 |
5413 | 5423 |
5414 #undef __ | 5424 #undef __ |
5415 | 5425 |
5416 } } // namespace v8::internal | 5426 } } // namespace v8::internal |
5417 | 5427 |
5418 #endif // V8_TARGET_ARCH_ARM64 | 5428 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |