| 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 #include <memory> | 8 #include <memory> |
| 9 | 9 |
| 10 #include "src/ast/prettyprinter.h" | 10 #include "src/ast/prettyprinter.h" |
| (...skipping 1892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1903 Node* cache_type, Node* cache_array, | 1903 Node* cache_type, Node* cache_array, |
| 1904 Node* cache_length, | 1904 Node* cache_length, |
| 1905 InterpreterAssembler* assembler) { | 1905 InterpreterAssembler* assembler) { |
| 1906 __ StoreRegister(cache_type, output_register); | 1906 __ StoreRegister(cache_type, output_register); |
| 1907 output_register = __ NextRegister(output_register); | 1907 output_register = __ NextRegister(output_register); |
| 1908 __ StoreRegister(cache_array, output_register); | 1908 __ StoreRegister(cache_array, output_register); |
| 1909 output_register = __ NextRegister(output_register); | 1909 output_register = __ NextRegister(output_register); |
| 1910 __ StoreRegister(cache_length, output_register); | 1910 __ StoreRegister(cache_length, output_register); |
| 1911 } | 1911 } |
| 1912 | 1912 |
| 1913 // ForInPrepare <cache_info_triple> | 1913 // ForInPrepare <receiver> <cache_info_triple> |
| 1914 // | 1914 // |
| 1915 // Returns state for for..in loop execution based on the object in the | 1915 // Returns state for for..in loop execution based on the object in the register |
| 1916 // accumulator. The result is output in registers |cache_info_triple| to | 1916 // |receiver|. The object must not be null or undefined and must have been |
| 1917 // converted to a receiver already. |
| 1918 // The result is output in registers |cache_info_triple| to |
| 1917 // |cache_info_triple + 2|, with the registers holding cache_type, cache_array, | 1919 // |cache_info_triple + 2|, with the registers holding cache_type, cache_array, |
| 1918 // and cache_length respectively. | 1920 // and cache_length respectively. |
| 1919 void Interpreter::DoForInPrepare(InterpreterAssembler* assembler) { | 1921 void Interpreter::DoForInPrepare(InterpreterAssembler* assembler) { |
| 1920 Node* object_reg = __ BytecodeOperandReg(0); | 1922 Node* object_reg = __ BytecodeOperandReg(0); |
| 1921 Node* object = __ LoadRegister(object_reg); | 1923 Node* receiver = __ LoadRegister(object_reg); |
| 1922 Node* context = __ GetContext(); | 1924 Node* context = __ GetContext(); |
| 1923 Node* const zero_smi = __ SmiConstant(Smi::FromInt(0)); | 1925 Node* const zero_smi = __ SmiConstant(Smi::FromInt(0)); |
| 1924 | 1926 |
| 1925 Label test_if_null(assembler), test_if_undefined(assembler), | 1927 Label nothing_to_iterate(assembler, Label::kDeferred), |
| 1926 nothing_to_iterate(assembler, Label::kDeferred), | 1928 use_enum_cache(assembler), use_runtime(assembler, Label::kDeferred); |
| 1927 convert_to_receiver(assembler, Label::kDeferred), | |
| 1928 already_receiver(assembler), check_enum_cache(assembler); | |
| 1929 | 1929 |
| 1930 Variable receiver(assembler, MachineRepresentation::kTagged); | 1930 if (FLAG_debug_code) { |
| 1931 | 1931 Label already_receiver(assembler), abort(assembler); |
| 1932 // Test if object is already a receiver, no conversion necessary if so. | 1932 Node* instance_type = __ LoadInstanceType(receiver); |
| 1933 Node* instance_type = __ LoadInstanceType(object); | 1933 Node* first_receiver_type = __ Int32Constant(FIRST_JS_RECEIVER_TYPE); |
| 1934 Node* first_receiver_type = __ Int32Constant(FIRST_JS_RECEIVER_TYPE); | 1934 __ BranchIfInt32GreaterThanOrEqual(instance_type, first_receiver_type, |
| 1935 __ BranchIfInt32GreaterThanOrEqual(instance_type, first_receiver_type, | 1935 &already_receiver, &abort); |
| 1936 &already_receiver, &test_if_null); | 1936 __ Bind(&abort); |
| 1937 | 1937 { |
| 1938 __ Bind(&test_if_null); | 1938 __ Abort(kExpectedJSReceiver); |
| 1939 { | 1939 // TODO(klaasb) remove this unreachable Goto once Abort ends the block |
| 1940 __ BranchIfWordEqual(object, assembler->NullConstant(), ¬hing_to_iterate, | 1940 __ Goto(&already_receiver); |
| 1941 &test_if_undefined); | 1941 } |
| 1942 __ Bind(&already_receiver); |
| 1942 } | 1943 } |
| 1943 | 1944 |
| 1944 __ Bind(&test_if_undefined); | 1945 __ CheckEnumCache(receiver, &use_enum_cache, &use_runtime); |
| 1945 { | |
| 1946 __ BranchIfWordEqual(object, assembler->UndefinedConstant(), | |
| 1947 ¬hing_to_iterate, &convert_to_receiver); | |
| 1948 } | |
| 1949 | |
| 1950 __ Bind(&convert_to_receiver); | |
| 1951 { | |
| 1952 Callable callable = CodeFactory::ToObject(assembler->isolate()); | |
| 1953 Node* target = __ HeapConstant(callable.code()); | |
| 1954 Node* result = __ CallStub(callable.descriptor(), target, context, object); | |
| 1955 receiver.Bind(result); | |
| 1956 __ Goto(&check_enum_cache); | |
| 1957 } | |
| 1958 | |
| 1959 __ Bind(&already_receiver); | |
| 1960 { | |
| 1961 receiver.Bind(object); | |
| 1962 __ Goto(&check_enum_cache); | |
| 1963 } | |
| 1964 | |
| 1965 Label use_enum_cache(assembler), use_runtime(assembler, Label::kDeferred); | |
| 1966 __ Bind(&check_enum_cache); | |
| 1967 { __ CheckEnumCache(receiver.value(), &use_enum_cache, &use_runtime); } | |
| 1968 | 1946 |
| 1969 __ Bind(&use_enum_cache); | 1947 __ Bind(&use_enum_cache); |
| 1970 { | 1948 { |
| 1971 // The enum cache is valid. Load the map of the object being | 1949 // The enum cache is valid. Load the map of the object being |
| 1972 // iterated over and use the cache for the iteration. | 1950 // iterated over and use the cache for the iteration. |
| 1973 Node* cache_type = __ LoadMap(receiver.value()); | 1951 Node* cache_type = __ LoadMap(receiver); |
| 1974 Node* cache_length = __ EnumLength(cache_type); | 1952 Node* cache_length = __ EnumLength(cache_type); |
| 1975 __ GotoIf(assembler->WordEqual(cache_length, zero_smi), | 1953 __ GotoIf(assembler->WordEqual(cache_length, zero_smi), |
| 1976 ¬hing_to_iterate); | 1954 ¬hing_to_iterate); |
| 1977 Node* descriptors = __ LoadMapDescriptors(cache_type); | 1955 Node* descriptors = __ LoadMapDescriptors(cache_type); |
| 1978 Node* cache_offset = | 1956 Node* cache_offset = |
| 1979 __ LoadObjectField(descriptors, DescriptorArray::kEnumCacheOffset); | 1957 __ LoadObjectField(descriptors, DescriptorArray::kEnumCacheOffset); |
| 1980 Node* cache_array = __ LoadObjectField( | 1958 Node* cache_array = __ LoadObjectField( |
| 1981 cache_offset, DescriptorArray::kEnumCacheBridgeCacheOffset); | 1959 cache_offset, DescriptorArray::kEnumCacheBridgeCacheOffset); |
| 1982 Node* output_register = __ BytecodeOperandReg(1); | 1960 Node* output_register = __ BytecodeOperandReg(1); |
| 1983 BuildForInPrepareResult(output_register, cache_type, cache_array, | 1961 BuildForInPrepareResult(output_register, cache_type, cache_array, |
| 1984 cache_length, assembler); | 1962 cache_length, assembler); |
| 1985 __ Dispatch(); | 1963 __ Dispatch(); |
| 1986 } | 1964 } |
| 1987 | 1965 |
| 1988 __ Bind(&use_runtime); | 1966 __ Bind(&use_runtime); |
| 1989 { | 1967 { |
| 1990 Node* result_triple = | 1968 Node* result_triple = |
| 1991 __ CallRuntime(Runtime::kForInPrepare, context, object); | 1969 __ CallRuntime(Runtime::kForInPrepare, context, receiver); |
| 1992 Node* cache_type = __ Projection(0, result_triple); | 1970 Node* cache_type = __ Projection(0, result_triple); |
| 1993 Node* cache_array = __ Projection(1, result_triple); | 1971 Node* cache_array = __ Projection(1, result_triple); |
| 1994 Node* cache_length = __ Projection(2, result_triple); | 1972 Node* cache_length = __ Projection(2, result_triple); |
| 1995 Node* output_register = __ BytecodeOperandReg(1); | 1973 Node* output_register = __ BytecodeOperandReg(1); |
| 1996 BuildForInPrepareResult(output_register, cache_type, cache_array, | 1974 BuildForInPrepareResult(output_register, cache_type, cache_array, |
| 1997 cache_length, assembler); | 1975 cache_length, assembler); |
| 1998 __ Dispatch(); | 1976 __ Dispatch(); |
| 1999 } | 1977 } |
| 2000 | 1978 |
| 2001 __ Bind(¬hing_to_iterate); | 1979 __ Bind(¬hing_to_iterate); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2180 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, | 2158 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, |
| 2181 __ SmiTag(new_state)); | 2159 __ SmiTag(new_state)); |
| 2182 __ SetAccumulator(old_state); | 2160 __ SetAccumulator(old_state); |
| 2183 | 2161 |
| 2184 __ Dispatch(); | 2162 __ Dispatch(); |
| 2185 } | 2163 } |
| 2186 | 2164 |
| 2187 } // namespace interpreter | 2165 } // namespace interpreter |
| 2188 } // namespace internal | 2166 } // namespace internal |
| 2189 } // namespace v8 | 2167 } // namespace v8 |
| OLD | NEW |