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), |
rmcilroy
2016/07/19 11:08:54
Just wondering if nothing_to_iterate should be kDe
oth
2016/07/19 12:59:25
I expect this is the lesser trodden path - it's de
| |
1856 Node* output_register = __ BytecodeOperandReg(0); | 1867 convert_to_receiver(assembler), already_receiver(assembler), |
1857 for (int i = 0; i < 3; i++) { | 1868 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 __ BranchIf( | |
1876 assembler->Int32GreaterThanOrEqual(instance_type, first_receiver_type), | |
rmcilroy
2016/07/19 11:08:54
There is a BranchIfInt32GreaterThanOrEqual (I thin
oth
2016/07/19 12:59:25
Thanks! Done.
| |
1877 &already_receiver, &test_if_null); | |
1878 | |
1879 __ Bind(&test_if_null); | |
1880 { | |
1881 __ BranchIf(assembler->WordEqual(object, assembler->NullConstant()), | |
rmcilroy
2016/07/19 11:08:54
BranchIfWordEqual (and below)
oth
2016/07/19 12:59:25
Done.
| |
1882 ¬hing_to_iterate, &test_if_undefined); | |
1861 } | 1883 } |
1862 __ Dispatch(); | 1884 |
1885 __ Bind(&test_if_undefined); | |
1886 { | |
1887 __ BranchIf(assembler->WordEqual(object, assembler->UndefinedConstant()), | |
1888 ¬hing_to_iterate, &convert_to_receiver); | |
1889 } | |
1890 | |
1891 __ Bind(&convert_to_receiver); | |
rmcilroy
2016/07/19 11:08:54
I'm assuming this is relatively uncommon. If so, c
oth
2016/07/19 12:59:25
Done.
| |
1892 { | |
1893 Callable callable = CodeFactory::ToObject(assembler->isolate()); | |
1894 Node* target = __ HeapConstant(callable.code()); | |
1895 Node* result = __ CallStub(callable.descriptor(), target, context, object); | |
1896 receiver.Bind(result); | |
1897 __ Goto(&check_enum_cache); | |
1898 } | |
1899 | |
1900 __ Bind(&already_receiver); | |
1901 { | |
1902 receiver.Bind(object); | |
1903 __ Goto(&check_enum_cache); | |
1904 } | |
1905 | |
1906 Label use_enum_cache(assembler), use_runtime(assembler); | |
rmcilroy
2016/07/19 11:08:54
make use_runtime kDeferred.
oth
2016/07/19 12:59:25
Done.
| |
1907 __ Bind(&check_enum_cache); | |
1908 { __ CheckEnumCache(receiver.value(), &use_enum_cache, &use_runtime); } | |
1909 | |
1910 __ Bind(&use_enum_cache); | |
1911 { | |
1912 // The enum cache is valid. Load the map of the object being | |
1913 // iterated over and use the cache for the iteration. | |
1914 Node* cache_type = __ LoadMap(receiver.value()); | |
1915 Node* cache_length = __ EnumLength(cache_type); | |
1916 __ GotoIf(assembler->WordEqual(cache_length, zero_smi), | |
1917 ¬hing_to_iterate); | |
1918 Node* descriptors = __ LoadMapDescriptors(cache_type); | |
1919 Node* cache_offset = | |
1920 __ LoadObjectField(descriptors, DescriptorArray::kEnumCacheOffset); | |
1921 Node* cache_array = __ LoadObjectField( | |
1922 cache_offset, DescriptorArray::kEnumCacheBridgeCacheOffset); | |
1923 Node* output_register = __ BytecodeOperandReg(0); | |
1924 BuildForInPrepareResult(output_register, cache_type, cache_array, | |
1925 cache_length, assembler); | |
1926 __ Dispatch(); | |
1927 } | |
1928 | |
1929 __ Bind(&use_runtime); | |
1930 { | |
1931 Node* result_triple = | |
1932 __ CallRuntime(Runtime::kForInPrepare, context, object); | |
1933 Node* cache_type = __ Projection(0, result_triple); | |
1934 Node* cache_array = __ Projection(1, result_triple); | |
1935 Node* cache_length = __ Projection(2, result_triple); | |
1936 Node* output_register = __ BytecodeOperandReg(0); | |
1937 BuildForInPrepareResult(output_register, cache_type, cache_array, | |
1938 cache_length, assembler); | |
1939 __ Dispatch(); | |
1940 } | |
1941 | |
1942 __ Bind(¬hing_to_iterate); | |
1943 { | |
1944 // Receiver is null or undefined or descriptors are zero length. | |
1945 Node* output_register = __ BytecodeOperandReg(0); | |
1946 BuildForInPrepareResult(output_register, zero_smi, zero_smi, zero_smi, | |
1947 assembler); | |
1948 __ Dispatch(); | |
1949 } | |
1863 } | 1950 } |
1864 | 1951 |
1865 // ForInNext <receiver> <index> <cache_info_pair> | 1952 // ForInNext <receiver> <index> <cache_info_pair> |
1866 // | 1953 // |
1867 // Returns the next enumerable property in the the accumulator. | 1954 // Returns the next enumerable property in the the accumulator. |
1868 void Interpreter::DoForInNext(InterpreterAssembler* assembler) { | 1955 void Interpreter::DoForInNext(InterpreterAssembler* assembler) { |
1869 Node* receiver_reg = __ BytecodeOperandReg(0); | 1956 Node* receiver_reg = __ BytecodeOperandReg(0); |
1870 Node* receiver = __ LoadRegister(receiver_reg); | 1957 Node* receiver = __ LoadRegister(receiver_reg); |
1871 Node* index_reg = __ BytecodeOperandReg(1); | 1958 Node* index_reg = __ BytecodeOperandReg(1); |
1872 Node* index = __ LoadRegister(index_reg); | 1959 Node* index = __ LoadRegister(index_reg); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2035 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, | 2122 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, |
2036 __ SmiTag(new_state)); | 2123 __ SmiTag(new_state)); |
2037 __ SetAccumulator(old_state); | 2124 __ SetAccumulator(old_state); |
2038 | 2125 |
2039 __ Dispatch(); | 2126 __ Dispatch(); |
2040 } | 2127 } |
2041 | 2128 |
2042 } // namespace interpreter | 2129 } // namespace interpreter |
2043 } // namespace internal | 2130 } // namespace internal |
2044 } // namespace v8 | 2131 } // namespace v8 |
OLD | NEW |