Index: src/interpreter/interpreter.cc |
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc |
index decc0724300cbaf3ae8a54c4aad3df34c27b51c5..7bd992b3e228377481011fb911f79646ee229289 100644 |
--- a/src/interpreter/interpreter.cc |
+++ b/src/interpreter/interpreter.cc |
@@ -4,6 +4,7 @@ |
#include "src/interpreter/interpreter.h" |
+#include <array> |
#include <fstream> |
#include <memory> |
@@ -130,20 +131,47 @@ void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode, |
BytecodeGeneratorFunc generator) { |
if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; |
- InterpreterDispatchDescriptor descriptor(isolate_); |
- compiler::CodeAssemblerState state( |
- isolate_, zone, descriptor, Code::ComputeFlags(Code::BYTECODE_HANDLER), |
- Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); |
- InterpreterAssembler assembler(&state, bytecode, operand_scale); |
- (this->*generator)(&assembler); |
- Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); |
size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
- dispatch_table_[index] = code->entry(); |
- TraceCodegen(code); |
- PROFILE(isolate_, CodeCreateEvent( |
- CodeEventListener::BYTECODE_HANDLER_TAG, |
- AbstractCode::cast(*code), |
- Bytecodes::ToString(bytecode, operand_scale).c_str())); |
+ switch (bytecode) { |
+ case Bytecode::kCallProperty: |
+ case Bytecode::kCallProperty0: |
+ case Bytecode::kCallProperty1: |
+ case Bytecode::kCallProperty2: { |
+ const int offset = static_cast<int>(Bytecode::kCallProperty) - |
+ static_cast<int>(Bytecode::kCall); |
+ STATIC_ASSERT(offset == |
+ static_cast<int>(Bytecode::kCallProperty0) - |
+ static_cast<int>(Bytecode::kCall0)); |
+ STATIC_ASSERT(offset == |
+ static_cast<int>(Bytecode::kCallProperty1) - |
+ static_cast<int>(Bytecode::kCall1)); |
+ STATIC_ASSERT(offset == |
+ static_cast<int>(Bytecode::kCallProperty2) - |
+ static_cast<int>(Bytecode::kCall2)); |
+ dispatch_table_[index] = dispatch_table_[index - offset]; |
+ break; |
+ } |
+ |
+ default: { |
+ InterpreterDispatchDescriptor descriptor(isolate_); |
+ compiler::CodeAssemblerState state( |
+ isolate_, zone, descriptor, |
+ Code::ComputeFlags(Code::BYTECODE_HANDLER), |
+ Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); |
+ InterpreterAssembler assembler(&state, bytecode, operand_scale); |
+ (this->*generator)(&assembler); |
+ Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); |
+ size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
+ dispatch_table_[index] = code->entry(); |
+ TraceCodegen(code); |
+ PROFILE(isolate_, |
+ CodeCreateEvent( |
+ CodeEventListener::BYTECODE_HANDLER_TAG, |
+ AbstractCode::cast(*code), |
+ Bytecodes::ToString(bytecode, operand_scale).c_str())); |
+ break; |
+ } |
+ } |
} |
Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, |
@@ -2064,6 +2092,32 @@ void Interpreter::DoJSCall(InterpreterAssembler* assembler, |
__ Dispatch(); |
} |
+void Interpreter::DoJSCallN(InterpreterAssembler* assembler, int n) { |
+ const int kFunctionOperandCount = 1; |
+ const int kReceiverOperandCount = 1; |
+ const int kBoilerplatParameterCount = 7; |
+ const int kReceiveParameterOffset = 5; |
+ Node* function_reg = __ BytecodeOperandReg(0); |
+ Node* function = __ LoadRegister(function_reg); |
+ std::array<Node*, Bytecodes::kMaxOperands + kBoilerplatParameterCount> temp; |
+ for (int i = 0; i < (n + kReceiverOperandCount); ++i) { |
+ Node* reg = __ BytecodeOperandReg(i + kFunctionOperandCount); |
+ temp[i + kReceiveParameterOffset] = __ LoadRegister(reg); |
+ } |
+ Callable call_ic = CodeFactory::CallIC(isolate_); |
+ temp[0] = __ HeapConstant(call_ic.code()); |
+ temp[1] = function; |
+ temp[2] = __ Int32Constant(n); |
+ temp[3] = __ BytecodeOperandIdxInt32(n + kFunctionOperandCount + |
+ kReceiverOperandCount); |
+ temp[4] = __ LoadTypeFeedbackVector(); |
+ temp[n + 6] = __ GetContext(); |
+ Node* result = __ CallStubN(call_ic.descriptor(), 1, |
+ n + kBoilerplatParameterCount, &temp[0]); |
+ __ SetAccumulator(result); |
+ __ Dispatch(); |
+} |
+ |
// Call <callable> <receiver> <arg_count> <feedback_slot_id> |
// |
// Call a JSfunction or Callable in |callable| with the |receiver| and |
@@ -2073,15 +2127,36 @@ void Interpreter::DoCall(InterpreterAssembler* assembler) { |
DoJSCall(assembler, TailCallMode::kDisallow); |
} |
-// CallProperty <callable> <receiver> <arg_count> <feedback_slot_id> |
-// |
-// Call a JSfunction or Callable in |callable| with the |receiver| and |
-// |arg_count| arguments in subsequent registers. Collect type feedback into |
-// |feedback_slot_id|. The callable is known to be a property of the receiver. |
+void Interpreter::DoCall0(InterpreterAssembler* assembler) { |
+ DoJSCallN(assembler, 0); |
+} |
+ |
+void Interpreter::DoCall1(InterpreterAssembler* assembler) { |
+ DoJSCallN(assembler, 1); |
+} |
+ |
+void Interpreter::DoCall2(InterpreterAssembler* assembler) { |
+ DoJSCallN(assembler, 2); |
+} |
+ |
void Interpreter::DoCallProperty(InterpreterAssembler* assembler) { |
- // TODO(leszeks): Look into making the interpreter use the fact that the |
- // receiver is non-null. |
- DoJSCall(assembler, TailCallMode::kDisallow); |
+ // Same as Call |
+ UNREACHABLE(); |
+} |
+ |
+void Interpreter::DoCallProperty0(InterpreterAssembler* assembler) { |
+ // Same as Call0 |
+ UNREACHABLE(); |
+} |
+ |
+void Interpreter::DoCallProperty1(InterpreterAssembler* assembler) { |
+ // Same as Call1 |
+ UNREACHABLE(); |
+} |
+ |
+void Interpreter::DoCallProperty2(InterpreterAssembler* assembler) { |
+ // Same as Call2 |
+ UNREACHABLE(); |
} |
// TailCall <callable> <receiver> <arg_count> <feedback_slot_id> |