Index: src/interpreter/interpreter-assembler.cc |
diff --git a/src/interpreter/interpreter-assembler.cc b/src/interpreter/interpreter-assembler.cc |
index 5d9929e3ae49e2f0f6d8586d3a38a1cf27007227..f770f8ad6a4c07f75a16db73a4b6309a1e1080dc 100644 |
--- a/src/interpreter/interpreter-assembler.cc |
+++ b/src/interpreter/interpreter-assembler.cc |
@@ -22,12 +22,13 @@ 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), |
@@ -84,7 +85,7 @@ Node* InterpreterAssembler::LoadRegister(int offset) { |
} |
Node* InterpreterAssembler::LoadRegister(Register reg) { |
- return LoadRegister(reg.ToOperand() << kPointerSizeLog2); |
+ return LoadRegister(IntPtrConstant(-reg.index())); |
} |
Node* InterpreterAssembler::RegisterFrameOffset(Node* index) { |
@@ -103,7 +104,7 @@ Node* InterpreterAssembler::StoreRegister(Node* value, int offset) { |
} |
Node* InterpreterAssembler::StoreRegister(Node* value, Register reg) { |
- return StoreRegister(value, reg.ToOperand() << kPointerSizeLog2); |
+ return StoreRegister(value, IntPtrConstant(-reg.index())); |
} |
Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) { |
@@ -117,24 +118,24 @@ Node* InterpreterAssembler::NextRegister(Node* reg_index) { |
return IntPtrAdd(reg_index, IntPtrConstant(-1)); |
} |
-Node* InterpreterAssembler::BytecodeOperand(int operand_index) { |
+Node* InterpreterAssembler::BytecodeOperandUnsignedByte(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) { |
+Node* InterpreterAssembler::BytecodeOperandSignedByte(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); |
@@ -142,17 +143,19 @@ Node* InterpreterAssembler::BytecodeOperandSignExtended(int operand_index) { |
return load; |
} |
-Node* InterpreterAssembler::BytecodeOperandShort(int operand_index) { |
+Node* InterpreterAssembler::BytecodeOperandUnsignedShort(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,21 +163,24 @@ 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 |
} |
} |
-Node* InterpreterAssembler::BytecodeOperandShortSignExtended( |
- int operand_index) { |
+Node* InterpreterAssembler::BytecodeOperandSignedShort(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,57 +210,163 @@ Node* InterpreterAssembler::BytecodeOperandShortSignExtended( |
return load; |
} |
-Node* InterpreterAssembler::BytecodeOperandCount(int operand_index) { |
- switch (Bytecodes::GetOperandSize(bytecode_, operand_index)) { |
+Node* InterpreterAssembler::BytecodeOperandUnsignedQuad(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::BytecodeOperandSignedQuad(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::BytecodeSignedOperand(int operand_index, |
+ OperandSize operand_size) { |
+ DCHECK(!Bytecodes::IsUnsignedOperandType( |
+ Bytecodes::GetOperandType(bytecode_, operand_index))); |
+ switch (operand_size) { |
case OperandSize::kByte: |
- DCHECK_EQ(OperandType::kRegCount8, |
- Bytecodes::GetOperandType(bytecode_, operand_index)); |
- return BytecodeOperand(operand_index); |
+ return BytecodeOperandSignedByte(operand_index); |
case OperandSize::kShort: |
- DCHECK_EQ(OperandType::kRegCount16, |
- Bytecodes::GetOperandType(bytecode_, operand_index)); |
- return BytecodeOperandShort(operand_index); |
+ return BytecodeOperandSignedShort(operand_index); |
+ case OperandSize::kQuad: |
+ return BytecodeOperandSignedQuad(operand_index); |
case OperandSize::kNone: |
UNREACHABLE(); |
} |
return nullptr; |
} |
-Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) { |
- DCHECK_EQ(OperandType::kImm8, |
- Bytecodes::GetOperandType(bytecode_, operand_index)); |
- return BytecodeOperandSignExtended(operand_index); |
-} |
- |
-Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) { |
- switch (Bytecodes::GetOperandSize(bytecode_, operand_index)) { |
+Node* InterpreterAssembler::BytecodeUnsignedOperand(int operand_index, |
+ OperandSize operand_size) { |
+ DCHECK(Bytecodes::IsUnsignedOperandType( |
+ Bytecodes::GetOperandType(bytecode_, operand_index))); |
+ switch (operand_size) { |
case OperandSize::kByte: |
- DCHECK_EQ(OperandType::kIdx8, |
- Bytecodes::GetOperandType(bytecode_, operand_index)); |
- return BytecodeOperand(operand_index); |
+ return BytecodeOperandUnsignedByte(operand_index); |
case OperandSize::kShort: |
- DCHECK_EQ(OperandType::kIdx16, |
- Bytecodes::GetOperandType(bytecode_, operand_index)); |
- return BytecodeOperandShort(operand_index); |
+ return BytecodeOperandUnsignedShort(operand_index); |
+ case OperandSize::kQuad: |
+ return BytecodeOperandUnsignedQuad(operand_index); |
case OperandSize::kNone: |
UNREACHABLE(); |
} |
return nullptr; |
} |
+Node* InterpreterAssembler::BytecodeOperandCount(int operand_index) { |
+ DCHECK_EQ(OperandType::kRegCount, |
+ Bytecodes::GetOperandType(bytecode_, operand_index)); |
+ OperandSize operand_size = |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
+ return BytecodeUnsignedOperand(operand_index, operand_size); |
+} |
+ |
+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()); |
+ DCHECK_EQ(operand_size, OperandSize::kByte); |
+ return BytecodeUnsignedOperand(operand_index, operand_size); |
+} |
+ |
+Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) { |
+ DCHECK_EQ(OperandType::kImm, |
+ Bytecodes::GetOperandType(bytecode_, operand_index)); |
+ OperandSize operand_size = |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
+ return BytecodeSignedOperand(operand_index, operand_size); |
+} |
+ |
+Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) { |
+ DCHECK(OperandType::kIdx == |
+ Bytecodes::GetOperandType(bytecode_, operand_index)); |
+ OperandSize operand_size = |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
+ return BytecodeUnsignedOperand(operand_index, operand_size); |
+} |
+ |
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) { |
- return BytecodeOperandSignExtended(operand_index); |
- } else if (operand_size == OperandSize::kShort) { |
- return BytecodeOperandShortSignExtended(operand_index); |
- } |
- } |
- UNREACHABLE(); |
- return nullptr; |
+ DCHECK(Bytecodes::IsRegisterOperandType( |
+ Bytecodes::GetOperandType(bytecode_, operand_index))); |
+ OperandSize operand_size = |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
+ return BytecodeSignedOperand(operand_index, operand_size); |
+} |
+ |
+Node* InterpreterAssembler::BytecodeOperandRuntimeId(int operand_index) { |
+ DCHECK(OperandType::kRuntimeId == |
+ Bytecodes::GetOperandType(bytecode_, operand_index)); |
+ OperandSize operand_size = |
+ Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
+ DCHECK_EQ(operand_size, OperandSize::kShort); |
+ return BytecodeUnsignedOperand(operand_index, operand_size); |
} |
Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) { |
@@ -432,7 +544,8 @@ void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs, |
} |
void InterpreterAssembler::Dispatch() { |
- DispatchTo(Advance(Bytecodes::Size(bytecode_))); |
+ DCHECK(base::bits::IsPowerOfTwo32(operand_scale_)); |
rmcilroy
2016/03/16 11:55:54
Not sure why this DCHECK is needed here, the code
oth
2016/03/17 13:48:38
Done.
|
+ DispatchTo(Advance(Bytecodes::Size(bytecode_, operand_scale_))); |
} |
void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) { |
@@ -464,6 +577,26 @@ void InterpreterAssembler::DispatchToBytecodeHandler(Node* handler, |
TailCall(descriptor, handler, args, 0); |
} |
+void InterpreterAssembler::RedispatchWide(int operand_scale) { |
+ DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(operand_scale))); |
+ DCHECK(operand_scale == 2 || operand_scale == 4); |
+ uint32_t log2_scale = |
+ base::bits::CountTrailingZeros32(static_cast<uint32_t>(operand_scale)); |
+ Node* target_bytecode_hi = IntPtrConstant(log2_scale << kBitsPerByte); |
+ Node* target_bytecode_lo_offset = Advance(1); |
+ Node* target_bytecode_lo = |
+ Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
+ target_bytecode_lo_offset); |
+ if (kPointerSize == 8) { |
+ target_bytecode_lo = ChangeUint32ToUint64(target_bytecode_lo); |
+ } |
+ Node* target_bytecode = WordOr(target_bytecode_hi, target_bytecode_lo); |
+ Node* target_code_object = |
+ Load(MachineType::Pointer(), DispatchTableRawPointer(), |
+ WordShl(target_bytecode, kPointerSizeLog2)); |
+ DispatchToBytecodeHandler(target_code_object, target_bytecode_lo_offset); |
+} |
+ |
void InterpreterAssembler::InterpreterReturn() { |
// TODO(rmcilroy): Investigate whether it is worth supporting self |
// optimization of primitive functions like FullCodegen. |