OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/interpreter/interpreter.h" | 5 #include "src/interpreter/interpreter.h" |
6 | 6 |
7 #include <fstream> | 7 #include <fstream> |
8 | 8 |
9 #include "src/ast/prettyprinter.h" | 9 #include "src/ast/prettyprinter.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 1822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1833 void Interpreter::Do##Name(InterpreterAssembler* assembler) { \ | 1833 void Interpreter::Do##Name(InterpreterAssembler* assembler) { \ |
1834 Node* context = __ GetContext(); \ | 1834 Node* context = __ GetContext(); \ |
1835 Node* accumulator = __ GetAccumulator(); \ | 1835 Node* accumulator = __ GetAccumulator(); \ |
1836 Node* original_handler = \ | 1836 Node* original_handler = \ |
1837 __ CallRuntime(Runtime::kDebugBreakOnBytecode, context, accumulator); \ | 1837 __ CallRuntime(Runtime::kDebugBreakOnBytecode, context, accumulator); \ |
1838 __ DispatchToBytecodeHandler(original_handler); \ | 1838 __ DispatchToBytecodeHandler(original_handler); \ |
1839 } | 1839 } |
1840 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK); | 1840 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK); |
1841 #undef DEBUG_BREAK | 1841 #undef DEBUG_BREAK |
1842 | 1842 |
| 1843 void Interpreter::BuildForInPrepareResult(Node* output_register, |
| 1844 Node* cache_type, Node* cache_array, |
| 1845 Node* cache_length, |
| 1846 InterpreterAssembler* assembler) { |
| 1847 __ StoreRegister(cache_type, output_register); |
| 1848 output_register = __ NextRegister(output_register); |
| 1849 __ StoreRegister(cache_array, output_register); |
| 1850 output_register = __ NextRegister(output_register); |
| 1851 __ StoreRegister(cache_length, output_register); |
| 1852 } |
| 1853 |
1843 // ForInPrepare <cache_info_triple> | 1854 // ForInPrepare <cache_info_triple> |
1844 // | 1855 // |
1845 // Returns state for for..in loop execution based on the object in the | 1856 // Returns state for for..in loop execution based on the object in the |
1846 // accumulator. The result is output in registers |cache_info_triple| to | 1857 // accumulator. The result is output in registers |cache_info_triple| to |
1847 // |cache_info_triple + 2|, with the registers holding cache_type, cache_array, | 1858 // |cache_info_triple + 2|, with the registers holding cache_type, cache_array, |
1848 // and cache_length respectively. | 1859 // and cache_length respectively. |
1849 void Interpreter::DoForInPrepare(InterpreterAssembler* assembler) { | 1860 void Interpreter::DoForInPrepare(InterpreterAssembler* assembler) { |
1850 Node* object = __ GetAccumulator(); | 1861 Node* object = __ GetAccumulator(); |
1851 Node* context = __ GetContext(); | 1862 Node* context = __ GetContext(); |
1852 Node* result_triple = __ CallRuntime(Runtime::kForInPrepare, context, object); | 1863 Node* const zero_smi = __ SmiConstant(Smi::FromInt(0)); |
1853 | 1864 |
1854 // Set output registers: | 1865 Label test_if_null(assembler), test_if_undefined(assembler), |
1855 // 0 == cache_type, 1 == cache_array, 2 == cache_length | 1866 nothing_to_iterate(assembler, Label::kDeferred), |
1856 Node* output_register = __ BytecodeOperandReg(0); | 1867 convert_to_receiver(assembler, Label::kDeferred), |
1857 for (int i = 0; i < 3; i++) { | 1868 already_receiver(assembler), check_enum_cache(assembler); |
1858 Node* cache_info = __ Projection(i, result_triple); | 1869 |
1859 __ StoreRegister(cache_info, output_register); | 1870 Variable receiver(assembler, MachineRepresentation::kTagged); |
1860 output_register = __ NextRegister(output_register); | 1871 |
| 1872 // Test if object is already a receiver, no conversion necessary if so. |
| 1873 Node* instance_type = __ LoadInstanceType(object); |
| 1874 Node* first_receiver_type = __ Int32Constant(FIRST_JS_RECEIVER_TYPE); |
| 1875 __ BranchIfInt32GreaterThanOrEqual(instance_type, first_receiver_type, |
| 1876 &already_receiver, &test_if_null); |
| 1877 |
| 1878 __ Bind(&test_if_null); |
| 1879 { |
| 1880 __ BranchIfWordEqual(object, assembler->NullConstant(), ¬hing_to_iterate, |
| 1881 &test_if_undefined); |
1861 } | 1882 } |
1862 __ Dispatch(); | 1883 |
| 1884 __ Bind(&test_if_undefined); |
| 1885 { |
| 1886 __ BranchIfWordEqual(object, assembler->UndefinedConstant(), |
| 1887 ¬hing_to_iterate, &convert_to_receiver); |
| 1888 } |
| 1889 |
| 1890 __ Bind(&convert_to_receiver); |
| 1891 { |
| 1892 Callable callable = CodeFactory::ToObject(assembler->isolate()); |
| 1893 Node* target = __ HeapConstant(callable.code()); |
| 1894 Node* result = __ CallStub(callable.descriptor(), target, context, object); |
| 1895 receiver.Bind(result); |
| 1896 __ Goto(&check_enum_cache); |
| 1897 } |
| 1898 |
| 1899 __ Bind(&already_receiver); |
| 1900 { |
| 1901 receiver.Bind(object); |
| 1902 __ Goto(&check_enum_cache); |
| 1903 } |
| 1904 |
| 1905 Label use_enum_cache(assembler), use_runtime(assembler, Label::kDeferred); |
| 1906 __ Bind(&check_enum_cache); |
| 1907 { __ CheckEnumCache(receiver.value(), &use_enum_cache, &use_runtime); } |
| 1908 |
| 1909 __ Bind(&use_enum_cache); |
| 1910 { |
| 1911 // The enum cache is valid. Load the map of the object being |
| 1912 // iterated over and use the cache for the iteration. |
| 1913 Node* cache_type = __ LoadMap(receiver.value()); |
| 1914 Node* cache_length = __ EnumLength(cache_type); |
| 1915 __ GotoIf(assembler->WordEqual(cache_length, zero_smi), |
| 1916 ¬hing_to_iterate); |
| 1917 Node* descriptors = __ LoadMapDescriptors(cache_type); |
| 1918 Node* cache_offset = |
| 1919 __ LoadObjectField(descriptors, DescriptorArray::kEnumCacheOffset); |
| 1920 Node* cache_array = __ LoadObjectField( |
| 1921 cache_offset, DescriptorArray::kEnumCacheBridgeCacheOffset); |
| 1922 Node* output_register = __ BytecodeOperandReg(0); |
| 1923 BuildForInPrepareResult(output_register, cache_type, cache_array, |
| 1924 cache_length, assembler); |
| 1925 __ Dispatch(); |
| 1926 } |
| 1927 |
| 1928 __ Bind(&use_runtime); |
| 1929 { |
| 1930 Node* result_triple = |
| 1931 __ CallRuntime(Runtime::kForInPrepare, context, object); |
| 1932 Node* cache_type = __ Projection(0, result_triple); |
| 1933 Node* cache_array = __ Projection(1, result_triple); |
| 1934 Node* cache_length = __ Projection(2, result_triple); |
| 1935 Node* output_register = __ BytecodeOperandReg(0); |
| 1936 BuildForInPrepareResult(output_register, cache_type, cache_array, |
| 1937 cache_length, assembler); |
| 1938 __ Dispatch(); |
| 1939 } |
| 1940 |
| 1941 __ Bind(¬hing_to_iterate); |
| 1942 { |
| 1943 // Receiver is null or undefined or descriptors are zero length. |
| 1944 Node* output_register = __ BytecodeOperandReg(0); |
| 1945 BuildForInPrepareResult(output_register, zero_smi, zero_smi, zero_smi, |
| 1946 assembler); |
| 1947 __ Dispatch(); |
| 1948 } |
1863 } | 1949 } |
1864 | 1950 |
1865 // ForInNext <receiver> <index> <cache_info_pair> | 1951 // ForInNext <receiver> <index> <cache_info_pair> |
1866 // | 1952 // |
1867 // Returns the next enumerable property in the the accumulator. | 1953 // Returns the next enumerable property in the the accumulator. |
1868 void Interpreter::DoForInNext(InterpreterAssembler* assembler) { | 1954 void Interpreter::DoForInNext(InterpreterAssembler* assembler) { |
1869 Node* receiver_reg = __ BytecodeOperandReg(0); | 1955 Node* receiver_reg = __ BytecodeOperandReg(0); |
1870 Node* receiver = __ LoadRegister(receiver_reg); | 1956 Node* receiver = __ LoadRegister(receiver_reg); |
1871 Node* index_reg = __ BytecodeOperandReg(1); | 1957 Node* index_reg = __ BytecodeOperandReg(1); |
1872 Node* index = __ LoadRegister(index_reg); | 1958 Node* index = __ LoadRegister(index_reg); |
1873 Node* cache_type_reg = __ BytecodeOperandReg(2); | 1959 Node* cache_type_reg = __ BytecodeOperandReg(2); |
1874 Node* cache_type = __ LoadRegister(cache_type_reg); | 1960 Node* cache_type = __ LoadRegister(cache_type_reg); |
1875 Node* cache_array_reg = __ NextRegister(cache_type_reg); | 1961 Node* cache_array_reg = __ NextRegister(cache_type_reg); |
1876 Node* cache_array = __ LoadRegister(cache_array_reg); | 1962 Node* cache_array = __ LoadRegister(cache_array_reg); |
1877 | 1963 |
1878 // Load the next key from the enumeration array. | 1964 // Load the next key from the enumeration array. |
1879 Node* key = __ LoadFixedArrayElement(cache_array, index, 0, | 1965 Node* key = __ LoadFixedArrayElement(cache_array, index, 0, |
1880 CodeStubAssembler::SMI_PARAMETERS); | 1966 CodeStubAssembler::SMI_PARAMETERS); |
1881 | 1967 |
1882 // Check if we can use the for-in fast path potentially using the enum cache. | 1968 // Check if we can use the for-in fast path potentially using the enum cache. |
1883 Label if_fast(assembler), if_slow(assembler, Label::kDeferred); | 1969 Label if_fast(assembler), if_slow(assembler, Label::kDeferred); |
1884 Node* receiver_map = __ LoadObjectField(receiver, HeapObject::kMapOffset); | 1970 Node* receiver_map = __ LoadObjectField(receiver, HeapObject::kMapOffset); |
1885 Node* condition = __ WordEqual(receiver_map, cache_type); | 1971 __ BranchIfWordEqual(receiver_map, cache_type, &if_fast, &if_slow); |
1886 __ BranchIf(condition, &if_fast, &if_slow); | |
1887 __ Bind(&if_fast); | 1972 __ Bind(&if_fast); |
1888 { | 1973 { |
1889 // Enum cache in use for {receiver}, the {key} is definitely valid. | 1974 // Enum cache in use for {receiver}, the {key} is definitely valid. |
1890 __ SetAccumulator(key); | 1975 __ SetAccumulator(key); |
1891 __ Dispatch(); | 1976 __ Dispatch(); |
1892 } | 1977 } |
1893 __ Bind(&if_slow); | 1978 __ Bind(&if_slow); |
1894 { | 1979 { |
1895 // Record the fact that we hit the for-in slow path. | 1980 // Record the fact that we hit the for-in slow path. |
1896 Node* vector_index = __ BytecodeOperandIdx(3); | 1981 Node* vector_index = __ BytecodeOperandIdx(3); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2035 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, | 2120 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, |
2036 __ SmiTag(new_state)); | 2121 __ SmiTag(new_state)); |
2037 __ SetAccumulator(old_state); | 2122 __ SetAccumulator(old_state); |
2038 | 2123 |
2039 __ Dispatch(); | 2124 __ Dispatch(); |
2040 } | 2125 } |
2041 | 2126 |
2042 } // namespace interpreter | 2127 } // namespace interpreter |
2043 } // namespace internal | 2128 } // namespace internal |
2044 } // namespace v8 | 2129 } // namespace v8 |
OLD | NEW |