| 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 |