Robustified address calculations on A64.

We no longer rely on the (adventurous) assumption that the class
Instruction is empty, implying sizeof(Instruction) == 1. This will
greatly simplify upcoming refactorings.

R=rodolph.perfetta@gmail.com

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4b01e032
...@@ -1607,8 +1607,8 @@ int Disassembler::SubstitutePCRelAddressField(Instruction* instr, ...@@ -1607,8 +1607,8 @@ int Disassembler::SubstitutePCRelAddressField(Instruction* instr,
offset = -offset; offset = -offset;
sign = '-'; sign = '-';
} }
STATIC_ASSERT(sizeof(*instr) == 1); AppendToOutput("#%c0x%x (addr %p)", sign, offset,
AppendToOutput("#%c0x%x (addr %p)", sign, offset, instr + offset); instr->InstructionAtOffset(offset, Instruction::NO_CHECK));
return 13; return 13;
} }
...@@ -1635,8 +1635,8 @@ int Disassembler::SubstituteBranchTargetField(Instruction* instr, ...@@ -1635,8 +1635,8 @@ int Disassembler::SubstituteBranchTargetField(Instruction* instr,
offset = -offset; offset = -offset;
sign = '-'; sign = '-';
} }
STATIC_ASSERT(sizeof(*instr) == 1); AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, offset,
AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, offset, instr + offset); instr->InstructionAtOffset(offset), Instruction::NO_CHECK);
return 8; return 8;
} }
......
...@@ -226,7 +226,7 @@ ptrdiff_t Instruction::ImmPCOffset() { ...@@ -226,7 +226,7 @@ ptrdiff_t Instruction::ImmPCOffset() {
Instruction* Instruction::ImmPCOffsetTarget() { Instruction* Instruction::ImmPCOffsetTarget() {
return this + ImmPCOffset(); return InstructionAtOffset(ImmPCOffset());
} }
...@@ -237,8 +237,7 @@ bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type, ...@@ -237,8 +237,7 @@ bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type,
bool Instruction::IsTargetInImmPCOffsetRange(Instruction* target) { bool Instruction::IsTargetInImmPCOffsetRange(Instruction* target) {
int offset = target - this; return IsValidImmPCOffset(BranchType(), DistanceTo(target));
return IsValidImmPCOffset(BranchType(), offset);
} }
...@@ -257,17 +256,17 @@ void Instruction::SetPCRelImmTarget(Instruction* target) { ...@@ -257,17 +256,17 @@ void Instruction::SetPCRelImmTarget(Instruction* target) {
// ADRP is not supported, so 'this' must point to an ADR instruction. // ADRP is not supported, so 'this' must point to an ADR instruction.
ASSERT(Mask(PCRelAddressingMask) == ADR); ASSERT(Mask(PCRelAddressingMask) == ADR);
Instr imm = Assembler::ImmPCRelAddress(target - this); Instr imm = Assembler::ImmPCRelAddress(DistanceTo(target));
SetInstructionBits(Mask(~ImmPCRel_mask) | imm); SetInstructionBits(Mask(~ImmPCRel_mask) | imm);
} }
void Instruction::SetBranchImmTarget(Instruction* target) { void Instruction::SetBranchImmTarget(Instruction* target) {
ASSERT(((target - this) & 3) == 0); ASSERT(IsAligned(DistanceTo(target), kInstructionSize));
Instr branch_imm = 0; Instr branch_imm = 0;
uint32_t imm_mask = 0; uint32_t imm_mask = 0;
int offset = (target - this) >> kInstructionSizeLog2; ptrdiff_t offset = DistanceTo(target) >> kInstructionSizeLog2;
switch (BranchType()) { switch (BranchType()) {
case CondBranchType: { case CondBranchType: {
branch_imm = Assembler::ImmCondBranch(offset); branch_imm = Assembler::ImmCondBranch(offset);
...@@ -296,8 +295,8 @@ void Instruction::SetBranchImmTarget(Instruction* target) { ...@@ -296,8 +295,8 @@ void Instruction::SetBranchImmTarget(Instruction* target) {
void Instruction::SetImmLLiteral(Instruction* source) { void Instruction::SetImmLLiteral(Instruction* source) {
ASSERT(((source - this) & 3) == 0); ASSERT(IsAligned(DistanceTo(source), kInstructionSize));
int offset = (source - this) >> kLiteralEntrySizeLog2; ptrdiff_t offset = DistanceTo(source) >> kLiteralEntrySizeLog2;
Instr imm = Assembler::ImmLLiteral(offset); Instr imm = Assembler::ImmLLiteral(offset);
Instr mask = ImmLLiteral_mask; Instr mask = ImmLLiteral_mask;
......
...@@ -144,12 +144,12 @@ class Instruction { ...@@ -144,12 +144,12 @@ class Instruction {
return InstructionBits() & mask; return InstructionBits() & mask;
} }
Instruction* following(int count = 1) { V8_INLINE Instruction* following(int count = 1) {
return this + count * kInstructionSize; return InstructionAtOffset(count * static_cast<int>(kInstructionSize));
} }
Instruction* preceding(int count = 1) { V8_INLINE Instruction* preceding(int count = 1) {
return this - count * kInstructionSize; return following(-count);
} }
#define DEFINE_GETTER(Name, HighBit, LowBit, Func) \ #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \
...@@ -367,20 +367,25 @@ class Instruction { ...@@ -367,20 +367,25 @@ class Instruction {
return reinterpret_cast<uint8_t*>(this) + offset; return reinterpret_cast<uint8_t*>(this) + offset;
} }
Instruction* NextInstruction() { enum CheckAlignment { NO_CHECK, CHECK_ALIGNMENT };
return this + kInstructionSize;
}
Instruction* InstructionAtOffset(int64_t offset) { V8_INLINE Instruction* InstructionAtOffset(
ASSERT(IsAligned(reinterpret_cast<uintptr_t>(this) + offset, int64_t offset,
kInstructionSize)); CheckAlignment check = CHECK_ALIGNMENT) {
return this + offset; Address addr = reinterpret_cast<Address>(this) + offset;
// The FUZZ_disasm test relies on no check being done.
ASSERT(check == NO_CHECK || IsAddressAligned(addr, kInstructionSize));
return Cast(addr);
} }
template<typename T> static Instruction* Cast(T src) { template<typename T> V8_INLINE static Instruction* Cast(T src) {
return reinterpret_cast<Instruction*>(src); return reinterpret_cast<Instruction*>(src);
} }
V8_INLINE ptrdiff_t DistanceTo(Instruction* target) {
return reinterpret_cast<Address>(target) - reinterpret_cast<Address>(this);
}
void SetPCRelImmTarget(Instruction* target); void SetPCRelImmTarget(Instruction* target);
void SetBranchImmTarget(Instruction* target); void SetBranchImmTarget(Instruction* target);
......
...@@ -5135,7 +5135,7 @@ InlineSmiCheckInfo::InlineSmiCheckInfo(Address info) ...@@ -5135,7 +5135,7 @@ InlineSmiCheckInfo::InlineSmiCheckInfo(Address info)
reg_ = Register::XRegFromCode(reg_code); reg_ = Register::XRegFromCode(reg_code);
uint64_t smi_check_delta = DeltaBits::decode(payload); uint64_t smi_check_delta = DeltaBits::decode(payload);
ASSERT(smi_check_delta != 0); ASSERT(smi_check_delta != 0);
smi_check_ = inline_data - (smi_check_delta * kInstructionSize); smi_check_ = inline_data->preceding(smi_check_delta);
} }
} }
} }
......
...@@ -807,7 +807,7 @@ void Simulator::CheckBreakpoints() { ...@@ -807,7 +807,7 @@ void Simulator::CheckBreakpoints() {
void Simulator::CheckBreakNext() { void Simulator::CheckBreakNext() {
// If the current instruction is a BL, insert a breakpoint just after it. // If the current instruction is a BL, insert a breakpoint just after it.
if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) { if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) {
SetBreakpoint(pc_->NextInstruction()); SetBreakpoint(pc_->following());
break_on_next_ = false; break_on_next_ = false;
} }
} }
...@@ -815,7 +815,7 @@ void Simulator::CheckBreakNext() { ...@@ -815,7 +815,7 @@ void Simulator::CheckBreakNext() {
void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) { void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) {
Instruction* end = start->InstructionAtOffset(count * kInstructionSize); Instruction* end = start->InstructionAtOffset(count * kInstructionSize);
for (Instruction* pc = start; pc < end; pc = pc->NextInstruction()) { for (Instruction* pc = start; pc < end; pc = pc->following()) {
disassembler_decoder_->Decode(pc); disassembler_decoder_->Decode(pc);
} }
} }
...@@ -996,7 +996,7 @@ void Simulator::VisitPCRelAddressing(Instruction* instr) { ...@@ -996,7 +996,7 @@ void Simulator::VisitPCRelAddressing(Instruction* instr) {
void Simulator::VisitUnconditionalBranch(Instruction* instr) { void Simulator::VisitUnconditionalBranch(Instruction* instr) {
switch (instr->Mask(UnconditionalBranchMask)) { switch (instr->Mask(UnconditionalBranchMask)) {
case BL: case BL:
set_lr(instr->NextInstruction()); set_lr(instr->following());
// Fall through. // Fall through.
case B: case B:
set_pc(instr->ImmPCOffsetTarget()); set_pc(instr->ImmPCOffsetTarget());
...@@ -1019,7 +1019,7 @@ void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) { ...@@ -1019,7 +1019,7 @@ void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
Instruction* target = reg<Instruction*>(instr->Rn()); Instruction* target = reg<Instruction*>(instr->Rn());
switch (instr->Mask(UnconditionalBranchToRegisterMask)) { switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
case BLR: { case BLR: {
set_lr(instr->NextInstruction()); set_lr(instr->following());
if (instr->Rn() == 31) { if (instr->Rn() == 31) {
// BLR XZR is used as a guard for the constant pool. We should never hit // BLR XZR is used as a guard for the constant pool. We should never hit
// this, but if we do trap to allow debugging. // this, but if we do trap to allow debugging.
...@@ -3362,12 +3362,16 @@ void Simulator::VisitException(Instruction* instr) { ...@@ -3362,12 +3362,16 @@ void Simulator::VisitException(Instruction* instr) {
// Read the arguments encoded inline in the instruction stream. // Read the arguments encoded inline in the instruction stream.
uint32_t code; uint32_t code;
uint32_t parameters; uint32_t parameters;
char const * message;
ASSERT(sizeof(*pc_) == 1); memcpy(&code,
memcpy(&code, pc_ + kDebugCodeOffset, sizeof(code)); pc_->InstructionAtOffset(kDebugCodeOffset),
memcpy(&parameters, pc_ + kDebugParamsOffset, sizeof(parameters)); sizeof(code));
message = reinterpret_cast<char const *>(pc_ + kDebugMessageOffset); memcpy(&parameters,
pc_->InstructionAtOffset(kDebugParamsOffset),
sizeof(parameters));
char const *message =
reinterpret_cast<char const*>(
pc_->InstructionAtOffset(kDebugMessageOffset));
// Always print something when we hit a debug point that breaks. // Always print something when we hit a debug point that breaks.
// We are going to break, so printing something is not an issue in // We are going to break, so printing something is not an issue in
...@@ -3415,14 +3419,13 @@ void Simulator::VisitException(Instruction* instr) { ...@@ -3415,14 +3419,13 @@ void Simulator::VisitException(Instruction* instr) {
// The stop parameters are inlined in the code. Skip them: // The stop parameters are inlined in the code. Skip them:
// - Skip to the end of the message string. // - Skip to the end of the message string.
pc_ += kDebugMessageOffset + strlen(message) + 1; size_t size = kDebugMessageOffset + strlen(message) + 1;
// - Advance to the next aligned location. pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize));
pc_ = AlignUp(pc_, kInstructionSize);
// - Verify that the unreachable marker is present. // - Verify that the unreachable marker is present.
ASSERT(pc_->Mask(ExceptionMask) == HLT); ASSERT(pc_->Mask(ExceptionMask) == HLT);
ASSERT(pc_->ImmException() == kImmExceptionIsUnreachable); ASSERT(pc_->ImmException() == kImmExceptionIsUnreachable);
// - Skip past the unreachable marker. // - Skip past the unreachable marker.
set_pc(pc_->NextInstruction()); set_pc(pc_->following());
// Check if the debugger should break. // Check if the debugger should break.
if (parameters & BREAK) Debug(); if (parameters & BREAK) Debug();
...@@ -3615,8 +3618,9 @@ void Simulator::VisitException(Instruction* instr) { ...@@ -3615,8 +3618,9 @@ void Simulator::VisitException(Instruction* instr) {
} else if (instr->ImmException() == kImmExceptionIsPrintf) { } else if (instr->ImmException() == kImmExceptionIsPrintf) {
// Read the argument encoded inline in the instruction stream. // Read the argument encoded inline in the instruction stream.
uint32_t type; uint32_t type;
ASSERT(sizeof(*pc_) == 1); memcpy(&type,
memcpy(&type, pc_ + kPrintfTypeOffset, sizeof(type)); pc_->InstructionAtOffset(kPrintfTypeOffset),
sizeof(type));
const char* format = reg<const char*>(0); const char* format = reg<const char*>(0);
......
...@@ -329,7 +329,7 @@ class Simulator : public DecoderVisitor { ...@@ -329,7 +329,7 @@ class Simulator : public DecoderVisitor {
void increment_pc() { void increment_pc() {
if (!pc_modified_) { if (!pc_modified_) {
pc_ = pc_->NextInstruction(); pc_ = pc_->following();
} }
pc_modified_ = false; pc_modified_ = false;
......
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