Index: src/interpreter/interpreter-assembler.cc |
diff --git a/src/interpreter/interpreter-assembler.cc b/src/interpreter/interpreter-assembler.cc |
index 5d9929e3ae49e2f0f6d8586d3a38a1cf27007227..03bb5e810d6c3f57dec311e9c5681f1dff2be6e2 100644 |
--- a/src/interpreter/interpreter-assembler.cc |
+++ b/src/interpreter/interpreter-assembler.cc |
@@ -22,12 +22,34 @@ namespace interpreter { |
using compiler::Node; |
InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, |
- Bytecode bytecode) |
+ Bytecode bytecode, int operand_scale) |
: compiler::CodeStubAssembler(isolate, zone, |
InterpreterDispatchDescriptor(isolate), |
Code::ComputeFlags(Code::BYTECODE_HANDLER), |
Bytecodes::ToString(bytecode), 0), |
bytecode_(bytecode), |
+ operand_scale_(operand_scale), |
+ accumulator_(this, MachineRepresentation::kTagged), |
+ context_(this, MachineRepresentation::kTagged), |
+ bytecode_array_(this, MachineRepresentation::kTagged), |
+ disable_stack_check_across_call_(false), |
+ stack_pointer_before_call_(nullptr) { |
+ accumulator_.Bind( |
+ Parameter(InterpreterDispatchDescriptor::kAccumulatorParameter)); |
+ context_.Bind(Parameter(InterpreterDispatchDescriptor::kContextParameter)); |
+ bytecode_array_.Bind( |
+ Parameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter)); |
+ if (FLAG_trace_ignition) { |
+ TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry); |
+ } |
+} |
+ |
+InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone) |
+ : compiler::CodeStubAssembler( |
+ isolate, zone, InterpreterDispatchDescriptor(isolate), |
+ Code::ComputeFlags(Code::STUB), "InvalidBytecode", 0), |
+ bytecode_(static_cast<Bytecode>(-1)), |
+ operand_scale_(-1), |
accumulator_(this, MachineRepresentation::kTagged), |
context_(this, MachineRepresentation::kTagged), |
bytecode_array_(this, MachineRepresentation::kTagged), |
@@ -119,22 +141,22 @@ Node* InterpreterAssembler::NextRegister(Node* reg_index) { |
Node* InterpreterAssembler::BytecodeOperand(int operand_index) { |
DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
- DCHECK_EQ(OperandSize::kByte, |
- Bytecodes::GetOperandSize(bytecode_, operand_index)); |
- return Load( |
- MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
- IntPtrAdd(BytecodeOffset(), IntPtrConstant(Bytecodes::GetOperandOffset( |
- bytecode_, operand_index)))); |
+ DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize( |
+ bytecode_, operand_index, operand_scale())); |
+ return Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
+ IntPtrAdd(BytecodeOffset(), |
+ IntPtrConstant(Bytecodes::GetOperandOffset( |
+ bytecode_, operand_index, operand_scale())))); |
} |
Node* InterpreterAssembler::BytecodeOperandSignExtended(int operand_index) { |
DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
- DCHECK_EQ(OperandSize::kByte, |
- Bytecodes::GetOperandSize(bytecode_, operand_index)); |
- Node* load = Load( |
- MachineType::Int8(), BytecodeArrayTaggedPointer(), |
- IntPtrAdd(BytecodeOffset(), IntPtrConstant(Bytecodes::GetOperandOffset( |
- bytecode_, operand_index)))); |
+ DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize( |
+ bytecode_, operand_index, operand_scale())); |
+ Node* load = Load(MachineType::Int8(), BytecodeArrayTaggedPointer(), |
+ IntPtrAdd(BytecodeOffset(), |
+ IntPtrConstant(Bytecodes::GetOperandOffset( |
+ bytecode_, operand_index, operand_scale())))); |
// Ensure that we sign extend to full pointer size |
if (kPointerSize == 8) { |
load = ChangeInt32ToInt64(load); |
@@ -144,15 +166,17 @@ Node* InterpreterAssembler::BytecodeOperandSignExtended(int operand_index) { |
Node* InterpreterAssembler::BytecodeOperandShort(int operand_index) { |
DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
- DCHECK_EQ(OperandSize::kShort, |
- Bytecodes::GetOperandSize(bytecode_, operand_index)); |
+ DCHECK_EQ( |
+ OperandSize::kShort, |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale())); |
if (TargetSupportsUnalignedAccess()) { |
- return Load( |
- MachineType::Uint16(), BytecodeArrayTaggedPointer(), |
- IntPtrAdd(BytecodeOffset(), IntPtrConstant(Bytecodes::GetOperandOffset( |
- bytecode_, operand_index)))); |
+ return Load(MachineType::Uint16(), BytecodeArrayTaggedPointer(), |
+ IntPtrAdd(BytecodeOffset(), |
+ IntPtrConstant(Bytecodes::GetOperandOffset( |
+ bytecode_, operand_index, operand_scale())))); |
} else { |
- int offset = Bytecodes::GetOperandOffset(bytecode_, operand_index); |
+ int offset = |
+ Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
Node* first_byte = |
Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
IntPtrAdd(BytecodeOffset(), IntPtrConstant(offset))); |
@@ -160,9 +184,11 @@ Node* InterpreterAssembler::BytecodeOperandShort(int operand_index) { |
Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
IntPtrAdd(BytecodeOffset(), IntPtrConstant(offset + 1))); |
#if V8_TARGET_LITTLE_ENDIAN |
- return WordOr(WordShl(second_byte, kBitsPerByte), first_byte); |
+ return WordOr(WordShl(second_byte, IntPtrConstant(kBitsPerByte)), |
+ first_byte); |
#elif V8_TARGET_BIG_ENDIAN |
- return WordOr(WordShl(first_byte, kBitsPerByte), second_byte); |
+ return WordOr(WordShl(first_byte, IntPtrConstant(kBitsPerByte)), |
+ second_byte); |
#else |
#error "Unknown Architecture" |
#endif |
@@ -172,9 +198,11 @@ Node* InterpreterAssembler::BytecodeOperandShort(int operand_index) { |
Node* InterpreterAssembler::BytecodeOperandShortSignExtended( |
int operand_index) { |
DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
- DCHECK_EQ(OperandSize::kShort, |
- Bytecodes::GetOperandSize(bytecode_, operand_index)); |
- int operand_offset = Bytecodes::GetOperandOffset(bytecode_, operand_index); |
+ DCHECK_EQ( |
+ OperandSize::kShort, |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale())); |
+ int operand_offset = |
+ Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
Node* load; |
if (TargetSupportsUnalignedAccess()) { |
load = Load(MachineType::Int16(), BytecodeArrayTaggedPointer(), |
@@ -204,16 +232,109 @@ Node* InterpreterAssembler::BytecodeOperandShortSignExtended( |
return load; |
} |
+Node* InterpreterAssembler::BytecodeOperandQuad(int operand_index) { |
+ DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
+ DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( |
+ bytecode_, operand_index, operand_scale())); |
+ int operand_offset = |
+ Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
+ if (TargetSupportsUnalignedAccess()) { |
+ return Load(MachineType::Uint32(), BytecodeArrayTaggedPointer(), |
+ IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); |
+ } else { |
+ Node* bytes[4]; |
+ for (int i = 0; i < static_cast<int>(arraysize(bytes)); ++i) { |
+ bytes[i] = |
+ Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
+ IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset + i))); |
+ } |
+#if V8_TARGET_LITTLE_ENDIAN |
+ Node* upper = |
+ WordOr(WordShl(bytes[3], IntPtrConstant(kBitsPerByte)), bytes[2]); |
+ Node* lower = |
+ WordOr(WordShl(bytes[1], IntPtrConstant(kBitsPerByte)), bytes[0]); |
+ return WordOr(WordShl(upper, IntPtrConstant(2 * kBitsPerByte)), lower); |
+#elif V8_TARGET_BIG_ENDIAN |
+ Node* upper = |
+ WordOr(WordShl(bytes[0], IntPtrConstant(kBitsPerByte)), bytes[1]); |
+ Node* lower = |
+ WordOr(WordShl(bytes[2], IntPtrConstant(kBitsPerByte)), bytes[3]); |
+ return WordOr(WordShl(upper, IntPtrConstant(2 * kBitsPerByte)), lower); |
+#else |
+#error "Unknown Architecture" |
+#endif |
+ } |
+} |
+ |
+Node* InterpreterAssembler::BytecodeOperandQuadSignExtended(int operand_index) { |
+ DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
+ DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( |
+ bytecode_, operand_index, operand_scale())); |
+ int operand_offset = |
+ Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
+ Node* load; |
+ if (TargetSupportsUnalignedAccess()) { |
+ load = Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), |
+ IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); |
+ } else { |
+ Node* bytes[4]; |
+ for (int i = 0; i < static_cast<int>(arraysize(bytes)); ++i) { |
+ bytes[i] = |
+ Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
+ IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset + i))); |
+ } |
+#if V8_TARGET_LITTLE_ENDIAN |
+ Node* upper = |
+ WordOr(WordShl(bytes[3], IntPtrConstant(kBitsPerByte)), bytes[2]); |
+ Node* lower = |
+ WordOr(WordShl(bytes[1], IntPtrConstant(kBitsPerByte)), bytes[0]); |
+ load = WordOr(WordShl(upper, IntPtrConstant(2 * kBitsPerByte)), lower); |
+#elif V8_TARGET_BIG_ENDIAN |
+ Node* upper = |
+ WordOr(WordShl(bytes[0], IntPtrConstant(kBitsPerByte)), bytes[1]); |
+ Node* lower = |
+ WordOr(WordShl(bytes[2], IntPtrConstant(kBitsPerByte)), bytes[3]); |
+ load = WordOr(WordShl(upper, IntPtrConstant(2 * kBitsPerByte)), lower); |
+#else |
+#error "Unknown Architecture" |
+#endif |
+ } |
+ |
+ // Ensure that we sign extend to full pointer size |
+ if (kPointerSize == 8) { |
+ load = ChangeInt32ToInt64(load); |
+ } |
+ return load; |
+} |
+ |
Node* InterpreterAssembler::BytecodeOperandCount(int operand_index) { |
- switch (Bytecodes::GetOperandSize(bytecode_, operand_index)) { |
+ DCHECK_EQ(OperandType::kRegCount8, |
+ Bytecodes::GetOperandType(bytecode_, operand_index)); |
+ OperandSize operand_size = |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
+ switch (operand_size) { |
case OperandSize::kByte: |
- DCHECK_EQ(OperandType::kRegCount8, |
- Bytecodes::GetOperandType(bytecode_, operand_index)); |
return BytecodeOperand(operand_index); |
case OperandSize::kShort: |
- DCHECK_EQ(OperandType::kRegCount16, |
- Bytecodes::GetOperandType(bytecode_, operand_index)); |
return BytecodeOperandShort(operand_index); |
+ case OperandSize::kQuad: |
+ return BytecodeOperandQuad(operand_index); |
+ case OperandSize::kNone: |
+ UNREACHABLE(); |
+ } |
+ return nullptr; |
+} |
+ |
+Node* InterpreterAssembler::BytecodeOperandFlag(int operand_index) { |
+ DCHECK_EQ(OperandType::kFlag8, |
+ Bytecodes::GetOperandType(bytecode_, operand_index)); |
+ OperandSize operand_size = |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
+ switch (operand_size) { |
+ case OperandSize::kByte: |
+ return BytecodeOperand(operand_index); |
+ case OperandSize::kShort: |
+ case OperandSize::kQuad: |
case OperandSize::kNone: |
UNREACHABLE(); |
} |
@@ -223,19 +344,35 @@ Node* InterpreterAssembler::BytecodeOperandCount(int operand_index) { |
Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) { |
DCHECK_EQ(OperandType::kImm8, |
Bytecodes::GetOperandType(bytecode_, operand_index)); |
- return BytecodeOperandSignExtended(operand_index); |
+ OperandSize operand_size = |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
+ switch (operand_size) { |
+ case OperandSize::kByte: |
+ return BytecodeOperandSignExtended(operand_index); |
+ case OperandSize::kShort: |
+ return BytecodeOperandShortSignExtended(operand_index); |
+ case OperandSize::kQuad: |
+ return BytecodeOperandQuadSignExtended(operand_index); |
+ case OperandSize::kNone: |
+ UNREACHABLE(); |
+ } |
+ return nullptr; |
} |
Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) { |
- switch (Bytecodes::GetOperandSize(bytecode_, operand_index)) { |
+ DCHECK(OperandType::kIdx8 == |
+ Bytecodes::GetOperandType(bytecode_, operand_index) || |
+ OperandType::kRuntimeId == |
+ Bytecodes::GetOperandType(bytecode_, operand_index)); |
+ OperandSize operand_size = |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
+ switch (operand_size) { |
case OperandSize::kByte: |
- DCHECK_EQ(OperandType::kIdx8, |
- Bytecodes::GetOperandType(bytecode_, operand_index)); |
return BytecodeOperand(operand_index); |
case OperandSize::kShort: |
- DCHECK_EQ(OperandType::kIdx16, |
- Bytecodes::GetOperandType(bytecode_, operand_index)); |
return BytecodeOperandShort(operand_index); |
+ case OperandSize::kQuad: |
+ return BytecodeOperandQuad(operand_index); |
case OperandSize::kNone: |
UNREACHABLE(); |
} |
@@ -245,15 +382,17 @@ Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) { |
Node* InterpreterAssembler::BytecodeOperandReg(int operand_index) { |
OperandType operand_type = |
Bytecodes::GetOperandType(bytecode_, operand_index); |
- if (Bytecodes::IsRegisterOperandType(operand_type)) { |
- OperandSize operand_size = Bytecodes::SizeOfOperand(operand_type); |
- if (operand_size == OperandSize::kByte) { |
+ DCHECK(Bytecodes::IsRegisterOperandType(operand_type)); |
+ switch (Bytecodes::SizeOfOperand(operand_type, operand_scale())) { |
+ case OperandSize::kByte: |
return BytecodeOperandSignExtended(operand_index); |
- } else if (operand_size == OperandSize::kShort) { |
+ case OperandSize::kShort: |
return BytecodeOperandShortSignExtended(operand_index); |
- } |
+ case OperandSize::kQuad: |
+ return BytecodeOperandQuadSignExtended(operand_index); |
+ case OperandSize::kNone: |
+ UNREACHABLE(); |
} |
- UNREACHABLE(); |
return nullptr; |
} |
@@ -432,7 +571,8 @@ void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs, |
} |
void InterpreterAssembler::Dispatch() { |
- DispatchTo(Advance(Bytecodes::Size(bytecode_))); |
+ DCHECK(base::bits::IsPowerOfTwo32(operand_scale_)); |
+ DispatchTo(Advance(Bytecodes::Size(bytecode_, operand_scale_))); |
} |
void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) { |
@@ -464,6 +604,23 @@ void InterpreterAssembler::DispatchToBytecodeHandler(Node* handler, |
TailCall(descriptor, handler, args, 0); |
} |
+void InterpreterAssembler::RedispatchWide() { |
+ STATIC_ASSERT(static_cast<int>(Bytecode::kExtraWide) == |
+ static_cast<int>(Bytecode::kWide) + 1); |
+ Node* upper = Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
+ BytecodeOffset()); |
+ upper = |
+ IntPtrAdd(upper, Int32Constant(-static_cast<int>(Bytecode::kWide) + 1)); |
+ Node* lower = Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
+ IntPtrAdd(BytecodeOffset(), Int32Constant(1))); |
+ Node* target_bytecode = |
+ Word32Or(Word32Shl(upper, Int32Constant(kBitsPerByte)), lower); |
+ Node* target_code_object = |
+ Load(MachineType::Pointer(), DispatchTableRawPointer(), |
+ Word32Shl(target_bytecode, Int32Constant(kPointerSizeLog2))); |
+ DispatchToBytecodeHandler(target_code_object, Advance(1)); |
+} |
+ |
void InterpreterAssembler::InterpreterReturn() { |
// TODO(rmcilroy): Investigate whether it is worth supporting self |
// optimization of primitive functions like FullCodegen. |