Chromium Code Reviews| 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 |