Commit 53c46f87 authored by akos.palfi's avatar akos.palfi Committed by Commit bot

MIPS: Fix unaligned read/write of bytecodes in interpreter.

On MIPS arch, all memory accesses (including halfword)
must be aligned to their native size or an alignment exception occurs.
The kernel will fix this up, but with performance penalty.

TEST=test-bytecode-generator/CallRuntime
BUG=

Review URL: https://codereview.chromium.org/1423373004

Cr-Commit-Position: refs/heads/master@{#31845}
parent 2a866bc4
...@@ -126,7 +126,7 @@ void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { ...@@ -126,7 +126,7 @@ void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) {
break; break;
case OperandSize::kShort: { case OperandSize::kShort: {
uint8_t operand_bytes[2]; uint8_t operand_bytes[2];
Bytecodes::ShortOperandToBytes(operands[i], operand_bytes); WriteUnalignedUInt16(operand_bytes, operands[i]);
bytecodes()->insert(bytecodes()->end(), operand_bytes, bytecodes()->insert(bytecodes()->end(), operand_bytes,
operand_bytes + 2); operand_bytes + 2);
break; break;
......
...@@ -48,7 +48,7 @@ uint32_t BytecodeArrayIterator::GetRawOperand(int operand_index, ...@@ -48,7 +48,7 @@ uint32_t BytecodeArrayIterator::GetRawOperand(int operand_index,
case OperandSize::kByte: case OperandSize::kByte:
return static_cast<uint32_t>(*operand_start); return static_cast<uint32_t>(*operand_start);
case OperandSize::kShort: case OperandSize::kShort:
return Bytecodes::ShortOperandFromBytes(operand_start); return ReadUnalignedUInt16(operand_start);
} }
} }
......
...@@ -181,18 +181,6 @@ bool Bytecodes::IsJumpConstant(Bytecode bytecode) { ...@@ -181,18 +181,6 @@ bool Bytecodes::IsJumpConstant(Bytecode bytecode) {
} }
// static
uint16_t Bytecodes::ShortOperandFromBytes(const uint8_t* bytes) {
return *reinterpret_cast<const uint16_t*>(bytes);
}
// static
void Bytecodes::ShortOperandToBytes(uint16_t operand, uint8_t* bytes_out) {
*reinterpret_cast<uint16_t*>(bytes_out) = operand;
}
// static // static
std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
int parameter_count) { int parameter_count) {
...@@ -225,7 +213,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, ...@@ -225,7 +213,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
os << "[" << static_cast<unsigned int>(*operand_start) << "]"; os << "[" << static_cast<unsigned int>(*operand_start) << "]";
break; break;
case interpreter::OperandType::kIdx16: { case interpreter::OperandType::kIdx16: {
os << "[" << Bytecodes::ShortOperandFromBytes(operand_start) << "]"; os << "[" << ReadUnalignedUInt16(operand_start) << "]";
break; break;
} }
case interpreter::OperandType::kImm8: case interpreter::OperandType::kImm8:
......
...@@ -328,12 +328,6 @@ class Bytecodes { ...@@ -328,12 +328,6 @@ class Bytecodes {
// constant pool entry (OperandType::kIdx). // constant pool entry (OperandType::kIdx).
static bool IsJumpConstant(Bytecode bytecode); static bool IsJumpConstant(Bytecode bytecode);
// Converts bytes[0] and bytes[1] to a 16 bit 'short' operand value.
static uint16_t ShortOperandFromBytes(const uint8_t* bytes);
// Converts 16 bit 'short' |operand| into bytes_out[0] and bytes_out[1].
static void ShortOperandToBytes(uint16_t operand, uint8_t* bytes_out);
// Decode a single bytecode and operands to |os|. // Decode a single bytecode and operands to |os|.
static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start, static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start,
int number_of_parameters); int number_of_parameters);
......
...@@ -1734,6 +1734,42 @@ static inline void WriteDoubleValue(void* p, double value) { ...@@ -1734,6 +1734,42 @@ static inline void WriteDoubleValue(void* p, double value) {
#endif // V8_TARGET_ARCH_MIPS #endif // V8_TARGET_ARCH_MIPS
} }
static inline uint16_t ReadUnalignedUInt16(const void* p) {
#if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64)
return *reinterpret_cast<const uint16_t*>(p);
#else // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
// Prevent compiler from using load-half (mips lh) on (possibly)
// non-16-bit aligned address.
union conversion {
uint16_t h;
uint8_t b[2];
} c;
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(p);
c.b[0] = *ptr;
c.b[1] = *(ptr + 1);
return c.h;
#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
}
static inline void WriteUnalignedUInt16(void* p, uint16_t value) {
#if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64)
*(reinterpret_cast<uint16_t*>(p)) = value;
#else // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
// Prevent compiler from using store-half (mips sh) on (possibly)
// non-16-bit aligned address.
union conversion {
uint16_t h;
uint8_t b[2];
} c;
c.h = value;
uint8_t* ptr = reinterpret_cast<uint8_t*>(p);
*ptr = c.b[0];
*(ptr + 1) = c.b[1];
#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -210,8 +210,8 @@ static void CheckBytecodeArrayEqual(const ExpectedSnippet<T, C>& expected, ...@@ -210,8 +210,8 @@ static void CheckBytecodeArrayEqual(const ExpectedSnippet<T, C>& expected,
static_cast<uint32_t>(expected.bytecode[operand_index]); static_cast<uint32_t>(expected.bytecode[operand_index]);
break; break;
case OperandSize::kShort: case OperandSize::kShort:
expected_operand = Bytecodes::ShortOperandFromBytes( expected_operand =
&expected.bytecode[operand_index]); ReadUnalignedUInt16(&expected.bytecode[operand_index]);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment