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 <array> |
7 #include <fstream> | 8 #include <fstream> |
8 #include <memory> | 9 #include <memory> |
9 | 10 |
10 #include "src/ast/prettyprinter.h" | 11 #include "src/ast/prettyprinter.h" |
11 #include "src/builtins/builtins-constructor.h" | 12 #include "src/builtins/builtins-constructor.h" |
12 #include "src/code-factory.h" | 13 #include "src/code-factory.h" |
13 #include "src/compilation-info.h" | 14 #include "src/compilation-info.h" |
14 #include "src/compiler.h" | 15 #include "src/compiler.h" |
15 #include "src/factory.h" | 16 #include "src/factory.h" |
16 #include "src/interpreter/bytecode-flags.h" | 17 #include "src/interpreter/bytecode-flags.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 | 124 |
124 // Initialization should have been successful. | 125 // Initialization should have been successful. |
125 DCHECK(IsDispatchTableInitialized()); | 126 DCHECK(IsDispatchTableInitialized()); |
126 } | 127 } |
127 | 128 |
128 void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode, | 129 void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode, |
129 OperandScale operand_scale, | 130 OperandScale operand_scale, |
130 BytecodeGeneratorFunc generator) { | 131 BytecodeGeneratorFunc generator) { |
131 if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; | 132 if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; |
132 | 133 |
133 InterpreterDispatchDescriptor descriptor(isolate_); | |
134 compiler::CodeAssemblerState state( | |
135 isolate_, zone, descriptor, Code::ComputeFlags(Code::BYTECODE_HANDLER), | |
136 Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); | |
137 InterpreterAssembler assembler(&state, bytecode, operand_scale); | |
138 (this->*generator)(&assembler); | |
139 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); | |
140 size_t index = GetDispatchTableIndex(bytecode, operand_scale); | 134 size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
141 dispatch_table_[index] = code->entry(); | 135 switch (bytecode) { |
142 TraceCodegen(code); | 136 case Bytecode::kCallProperty: |
143 PROFILE(isolate_, CodeCreateEvent( | 137 case Bytecode::kCallProperty0: |
144 CodeEventListener::BYTECODE_HANDLER_TAG, | 138 case Bytecode::kCallProperty1: |
145 AbstractCode::cast(*code), | 139 case Bytecode::kCallProperty2: { |
146 Bytecodes::ToString(bytecode, operand_scale).c_str())); | 140 const int offset = static_cast<int>(Bytecode::kCallProperty) - |
| 141 static_cast<int>(Bytecode::kCall); |
| 142 STATIC_ASSERT(offset == |
| 143 static_cast<int>(Bytecode::kCallProperty0) - |
| 144 static_cast<int>(Bytecode::kCall0)); |
| 145 STATIC_ASSERT(offset == |
| 146 static_cast<int>(Bytecode::kCallProperty1) - |
| 147 static_cast<int>(Bytecode::kCall1)); |
| 148 STATIC_ASSERT(offset == |
| 149 static_cast<int>(Bytecode::kCallProperty2) - |
| 150 static_cast<int>(Bytecode::kCall2)); |
| 151 dispatch_table_[index] = dispatch_table_[index - offset]; |
| 152 break; |
| 153 } |
| 154 |
| 155 default: { |
| 156 InterpreterDispatchDescriptor descriptor(isolate_); |
| 157 compiler::CodeAssemblerState state( |
| 158 isolate_, zone, descriptor, |
| 159 Code::ComputeFlags(Code::BYTECODE_HANDLER), |
| 160 Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); |
| 161 InterpreterAssembler assembler(&state, bytecode, operand_scale); |
| 162 (this->*generator)(&assembler); |
| 163 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); |
| 164 size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
| 165 dispatch_table_[index] = code->entry(); |
| 166 TraceCodegen(code); |
| 167 PROFILE(isolate_, |
| 168 CodeCreateEvent( |
| 169 CodeEventListener::BYTECODE_HANDLER_TAG, |
| 170 AbstractCode::cast(*code), |
| 171 Bytecodes::ToString(bytecode, operand_scale).c_str())); |
| 172 break; |
| 173 } |
| 174 } |
147 } | 175 } |
148 | 176 |
149 Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, | 177 Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, |
150 OperandScale operand_scale) { | 178 OperandScale operand_scale) { |
151 DCHECK(IsDispatchTableInitialized()); | 179 DCHECK(IsDispatchTableInitialized()); |
152 DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale)); | 180 DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale)); |
153 size_t index = GetDispatchTableIndex(bytecode, operand_scale); | 181 size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
154 Address code_entry = dispatch_table_[index]; | 182 Address code_entry = dispatch_table_[index]; |
155 return Code::GetCodeFromTargetAddress(code_entry); | 183 return Code::GetCodeFromTargetAddress(code_entry); |
156 } | 184 } |
(...skipping 1900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2057 Node* slot_id = __ BytecodeOperandIdx(3); | 2085 Node* slot_id = __ BytecodeOperandIdx(3); |
2058 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); | 2086 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
2059 Node* context = __ GetContext(); | 2087 Node* context = __ GetContext(); |
2060 Node* result = | 2088 Node* result = |
2061 __ CallJSWithFeedback(function, context, receiver_arg, args_count, | 2089 __ CallJSWithFeedback(function, context, receiver_arg, args_count, |
2062 slot_id, type_feedback_vector, tail_call_mode); | 2090 slot_id, type_feedback_vector, tail_call_mode); |
2063 __ SetAccumulator(result); | 2091 __ SetAccumulator(result); |
2064 __ Dispatch(); | 2092 __ Dispatch(); |
2065 } | 2093 } |
2066 | 2094 |
| 2095 void Interpreter::DoJSCallN(InterpreterAssembler* assembler, int n) { |
| 2096 const int kFunctionOperandCount = 1; |
| 2097 const int kReceiverOperandCount = 1; |
| 2098 const int kBoilerplatParameterCount = 7; |
| 2099 const int kReceiveParameterOffset = 5; |
| 2100 Node* function_reg = __ BytecodeOperandReg(0); |
| 2101 Node* function = __ LoadRegister(function_reg); |
| 2102 std::array<Node*, Bytecodes::kMaxOperands + kBoilerplatParameterCount> temp; |
| 2103 for (int i = 0; i < (n + kReceiverOperandCount); ++i) { |
| 2104 Node* reg = __ BytecodeOperandReg(i + kFunctionOperandCount); |
| 2105 temp[i + kReceiveParameterOffset] = __ LoadRegister(reg); |
| 2106 } |
| 2107 Callable call_ic = CodeFactory::CallIC(isolate_); |
| 2108 temp[0] = __ HeapConstant(call_ic.code()); |
| 2109 temp[1] = function; |
| 2110 temp[2] = __ Int32Constant(n); |
| 2111 temp[3] = __ BytecodeOperandIdxInt32(n + kFunctionOperandCount + |
| 2112 kReceiverOperandCount); |
| 2113 temp[4] = __ LoadTypeFeedbackVector(); |
| 2114 temp[n + 6] = __ GetContext(); |
| 2115 Node* result = __ CallStubN(call_ic.descriptor(), 1, |
| 2116 n + kBoilerplatParameterCount, &temp[0]); |
| 2117 __ SetAccumulator(result); |
| 2118 __ Dispatch(); |
| 2119 } |
| 2120 |
2067 // Call <callable> <receiver> <arg_count> <feedback_slot_id> | 2121 // Call <callable> <receiver> <arg_count> <feedback_slot_id> |
2068 // | 2122 // |
2069 // Call a JSfunction or Callable in |callable| with the |receiver| and | 2123 // Call a JSfunction or Callable in |callable| with the |receiver| and |
2070 // |arg_count| arguments in subsequent registers. Collect type feedback | 2124 // |arg_count| arguments in subsequent registers. Collect type feedback |
2071 // into |feedback_slot_id| | 2125 // into |feedback_slot_id| |
2072 void Interpreter::DoCall(InterpreterAssembler* assembler) { | 2126 void Interpreter::DoCall(InterpreterAssembler* assembler) { |
2073 DoJSCall(assembler, TailCallMode::kDisallow); | 2127 DoJSCall(assembler, TailCallMode::kDisallow); |
2074 } | 2128 } |
2075 | 2129 |
2076 // CallProperty <callable> <receiver> <arg_count> <feedback_slot_id> | 2130 void Interpreter::DoCall0(InterpreterAssembler* assembler) { |
2077 // | 2131 DoJSCallN(assembler, 0); |
2078 // Call a JSfunction or Callable in |callable| with the |receiver| and | 2132 } |
2079 // |arg_count| arguments in subsequent registers. Collect type feedback into | 2133 |
2080 // |feedback_slot_id|. The callable is known to be a property of the receiver. | 2134 void Interpreter::DoCall1(InterpreterAssembler* assembler) { |
| 2135 DoJSCallN(assembler, 1); |
| 2136 } |
| 2137 |
| 2138 void Interpreter::DoCall2(InterpreterAssembler* assembler) { |
| 2139 DoJSCallN(assembler, 2); |
| 2140 } |
| 2141 |
2081 void Interpreter::DoCallProperty(InterpreterAssembler* assembler) { | 2142 void Interpreter::DoCallProperty(InterpreterAssembler* assembler) { |
2082 // TODO(leszeks): Look into making the interpreter use the fact that the | 2143 // Same as Call |
2083 // receiver is non-null. | 2144 UNREACHABLE(); |
2084 DoJSCall(assembler, TailCallMode::kDisallow); | 2145 } |
| 2146 |
| 2147 void Interpreter::DoCallProperty0(InterpreterAssembler* assembler) { |
| 2148 // Same as Call0 |
| 2149 UNREACHABLE(); |
| 2150 } |
| 2151 |
| 2152 void Interpreter::DoCallProperty1(InterpreterAssembler* assembler) { |
| 2153 // Same as Call1 |
| 2154 UNREACHABLE(); |
| 2155 } |
| 2156 |
| 2157 void Interpreter::DoCallProperty2(InterpreterAssembler* assembler) { |
| 2158 // Same as Call2 |
| 2159 UNREACHABLE(); |
2085 } | 2160 } |
2086 | 2161 |
2087 // TailCall <callable> <receiver> <arg_count> <feedback_slot_id> | 2162 // TailCall <callable> <receiver> <arg_count> <feedback_slot_id> |
2088 // | 2163 // |
2089 // Tail call a JSfunction or Callable in |callable| with the |receiver| and | 2164 // Tail call a JSfunction or Callable in |callable| with the |receiver| and |
2090 // |arg_count| arguments in subsequent registers. Collect type feedback | 2165 // |arg_count| arguments in subsequent registers. Collect type feedback |
2091 // into |feedback_slot_id| | 2166 // into |feedback_slot_id| |
2092 void Interpreter::DoTailCall(InterpreterAssembler* assembler) { | 2167 void Interpreter::DoTailCall(InterpreterAssembler* assembler) { |
2093 DoJSCall(assembler, TailCallMode::kAllow); | 2168 DoJSCall(assembler, TailCallMode::kAllow); |
2094 } | 2169 } |
(...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3311 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, | 3386 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, |
3312 __ SmiTag(new_state)); | 3387 __ SmiTag(new_state)); |
3313 __ SetAccumulator(old_state); | 3388 __ SetAccumulator(old_state); |
3314 | 3389 |
3315 __ Dispatch(); | 3390 __ Dispatch(); |
3316 } | 3391 } |
3317 | 3392 |
3318 } // namespace interpreter | 3393 } // namespace interpreter |
3319 } // namespace internal | 3394 } // namespace internal |
3320 } // namespace v8 | 3395 } // namespace v8 |
OLD | NEW |