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 |