Chromium Code Reviews| 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. |