| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 6 | 6 |
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
| 8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 1752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1763 __ pop(esi); | 1763 __ pop(esi); |
| 1764 __ pop(edi); | 1764 __ pop(edi); |
| 1765 __ add(esp, Immediate(2 * kPointerSize)); // remove markers | 1765 __ add(esp, Immediate(2 * kPointerSize)); // remove markers |
| 1766 | 1766 |
| 1767 // Restore frame pointer and return. | 1767 // Restore frame pointer and return. |
| 1768 __ pop(ebp); | 1768 __ pop(ebp); |
| 1769 __ ret(0); | 1769 __ ret(0); |
| 1770 } | 1770 } |
| 1771 | 1771 |
| 1772 | 1772 |
| 1773 void InstanceOfStub::Generate(MacroAssembler* masm) { | |
| 1774 Register const object = edx; // Object (lhs). | |
| 1775 Register const function = eax; // Function (rhs). | |
| 1776 Register const object_map = ecx; // Map of {object}. | |
| 1777 Register const function_map = ebx; // Map of {function}. | |
| 1778 Register const function_prototype = function_map; // Prototype of {function}. | |
| 1779 Register const scratch = edi; | |
| 1780 | |
| 1781 DCHECK(object.is(InstanceOfDescriptor::LeftRegister())); | |
| 1782 DCHECK(function.is(InstanceOfDescriptor::RightRegister())); | |
| 1783 | |
| 1784 // Check if {object} is a smi. | |
| 1785 Label object_is_smi; | |
| 1786 __ JumpIfSmi(object, &object_is_smi, Label::kNear); | |
| 1787 | |
| 1788 // Lookup the {function} and the {object} map in the global instanceof cache. | |
| 1789 // Note: This is safe because we clear the global instanceof cache whenever | |
| 1790 // we change the prototype of any object. | |
| 1791 Label fast_case, slow_case; | |
| 1792 __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset)); | |
| 1793 __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); | |
| 1794 __ j(not_equal, &fast_case, Label::kNear); | |
| 1795 __ CompareRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex); | |
| 1796 __ j(not_equal, &fast_case, Label::kNear); | |
| 1797 __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex); | |
| 1798 __ ret(0); | |
| 1799 | |
| 1800 // If {object} is a smi we can safely return false if {function} is a JS | |
| 1801 // function, otherwise we have to miss to the runtime and throw an exception. | |
| 1802 __ bind(&object_is_smi); | |
| 1803 __ JumpIfSmi(function, &slow_case); | |
| 1804 __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map); | |
| 1805 __ j(not_equal, &slow_case); | |
| 1806 __ LoadRoot(eax, Heap::kFalseValueRootIndex); | |
| 1807 __ ret(0); | |
| 1808 | |
| 1809 // Fast-case: The {function} must be a valid JSFunction. | |
| 1810 __ bind(&fast_case); | |
| 1811 __ JumpIfSmi(function, &slow_case); | |
| 1812 __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map); | |
| 1813 __ j(not_equal, &slow_case); | |
| 1814 | |
| 1815 // Go to the runtime if the function is not a constructor. | |
| 1816 __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), | |
| 1817 Immediate(1 << Map::kIsConstructor)); | |
| 1818 __ j(zero, &slow_case); | |
| 1819 | |
| 1820 // Ensure that {function} has an instance prototype. | |
| 1821 __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), | |
| 1822 Immediate(1 << Map::kHasNonInstancePrototype)); | |
| 1823 __ j(not_zero, &slow_case); | |
| 1824 | |
| 1825 // Get the "prototype" (or initial map) of the {function}. | |
| 1826 __ mov(function_prototype, | |
| 1827 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | |
| 1828 __ AssertNotSmi(function_prototype); | |
| 1829 | |
| 1830 // Resolve the prototype if the {function} has an initial map. Afterwards the | |
| 1831 // {function_prototype} will be either the JSReceiver prototype object or the | |
| 1832 // hole value, which means that no instances of the {function} were created so | |
| 1833 // far and hence we should return false. | |
| 1834 Label function_prototype_valid; | |
| 1835 Register const function_prototype_map = scratch; | |
| 1836 __ CmpObjectType(function_prototype, MAP_TYPE, function_prototype_map); | |
| 1837 __ j(not_equal, &function_prototype_valid, Label::kNear); | |
| 1838 __ mov(function_prototype, | |
| 1839 FieldOperand(function_prototype, Map::kPrototypeOffset)); | |
| 1840 __ bind(&function_prototype_valid); | |
| 1841 __ AssertNotSmi(function_prototype); | |
| 1842 | |
| 1843 // Update the global instanceof cache with the current {object} map and | |
| 1844 // {function}. The cached answer will be set when it is known below. | |
| 1845 __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); | |
| 1846 __ StoreRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex); | |
| 1847 | |
| 1848 // Loop through the prototype chain looking for the {function} prototype. | |
| 1849 // Assume true, and change to false if not found. | |
| 1850 Label done, loop, fast_runtime_fallback; | |
| 1851 __ mov(eax, isolate()->factory()->true_value()); | |
| 1852 __ bind(&loop); | |
| 1853 | |
| 1854 // Check if the object needs to be access checked. | |
| 1855 __ test_b(FieldOperand(object_map, Map::kBitFieldOffset), | |
| 1856 Immediate(1 << Map::kIsAccessCheckNeeded)); | |
| 1857 __ j(not_zero, &fast_runtime_fallback, Label::kNear); | |
| 1858 // Check if the current object is a Proxy. | |
| 1859 __ CmpInstanceType(object_map, JS_PROXY_TYPE); | |
| 1860 __ j(equal, &fast_runtime_fallback, Label::kNear); | |
| 1861 | |
| 1862 __ mov(object, FieldOperand(object_map, Map::kPrototypeOffset)); | |
| 1863 __ cmp(object, function_prototype); | |
| 1864 __ j(equal, &done, Label::kNear); | |
| 1865 __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset)); | |
| 1866 __ cmp(object, isolate()->factory()->null_value()); | |
| 1867 __ j(not_equal, &loop); | |
| 1868 __ mov(eax, isolate()->factory()->false_value()); | |
| 1869 | |
| 1870 __ bind(&done); | |
| 1871 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); | |
| 1872 __ ret(0); | |
| 1873 | |
| 1874 // Found Proxy or access check needed: Call the runtime. | |
| 1875 __ bind(&fast_runtime_fallback); | |
| 1876 __ PopReturnAddressTo(scratch); | |
| 1877 __ Push(object); | |
| 1878 __ Push(function_prototype); | |
| 1879 __ PushReturnAddressFrom(scratch); | |
| 1880 // Invalidate the instanceof cache. | |
| 1881 __ Move(eax, Immediate(Smi::FromInt(0))); | |
| 1882 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex); | |
| 1883 __ TailCallRuntime(Runtime::kHasInPrototypeChain); | |
| 1884 | |
| 1885 // Slow-case: Call the %InstanceOf runtime function. | |
| 1886 __ bind(&slow_case); | |
| 1887 __ PopReturnAddressTo(scratch); | |
| 1888 __ Push(object); | |
| 1889 __ Push(function); | |
| 1890 __ PushReturnAddressFrom(scratch); | |
| 1891 __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance | |
| 1892 : Runtime::kInstanceOf); | |
| 1893 } | |
| 1894 | |
| 1895 | |
| 1896 // ------------------------------------------------------------------------- | 1773 // ------------------------------------------------------------------------- |
| 1897 // StringCharCodeAtGenerator | 1774 // StringCharCodeAtGenerator |
| 1898 | 1775 |
| 1899 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 1776 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
| 1900 // If the receiver is a smi trigger the non-string case. | 1777 // If the receiver is a smi trigger the non-string case. |
| 1901 if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 1778 if (check_mode_ == RECEIVER_IS_UNKNOWN) { |
| 1902 __ JumpIfSmi(object_, receiver_not_string_); | 1779 __ JumpIfSmi(object_, receiver_not_string_); |
| 1903 | 1780 |
| 1904 // Fetch the instance type of the receiver into result register. | 1781 // Fetch the instance type of the receiver into result register. |
| 1905 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 1782 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
| (...skipping 3607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5513 kStackUnwindSpace, nullptr, return_value_operand, | 5390 kStackUnwindSpace, nullptr, return_value_operand, |
| 5514 NULL); | 5391 NULL); |
| 5515 } | 5392 } |
| 5516 | 5393 |
| 5517 #undef __ | 5394 #undef __ |
| 5518 | 5395 |
| 5519 } // namespace internal | 5396 } // namespace internal |
| 5520 } // namespace v8 | 5397 } // namespace v8 |
| 5521 | 5398 |
| 5522 #endif // V8_TARGET_ARCH_X87 | 5399 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |