From 30f2572606a7402dcd8543d658280ccce027fc56 Mon Sep 17 00:00:00 2001 From: Heiher Date: Mon, 4 Jul 2016 22:11:31 +0800 Subject: [PATCH] Bug 1280843 - IonMonkey: MIPS: Fix ma_b(Register, T, JumpTarget) for Wasm. r=nbp --- js/src/jit/mips32/Assembler-mips32.cpp | 56 +++++++++++++++++++++++++------ js/src/jit/mips64/Assembler-mips64.cpp | 60 ++++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 20 deletions(-) --- js/src/jit/mips32/Assembler-mips32.cpp | 54 ++++++++++++++++++++---- js/src/jit/mips64/Assembler-mips64.cpp | 58 ++++++++++++++++++++++---- 2 files changed, 94 insertions(+), 18 deletions(-) diff --git a/js/src/jit/mips32/Assembler-mips32.cpp b/js/src/jit/mips32/Assembler-mips32.cpp index 81fc8c97f93b..23a093c6520b 100644 --- a/js/src/jit/mips32/Assembler-mips32.cpp +++ b/js/src/jit/mips32/Assembler-mips32.cpp @@ -315,19 +315,55 @@ Assembler::bind(RepatchLabel* label) // If the label has a use, then change this use to refer to // the bound label; BufferOffset b(label->offset()); - InstImm* inst1 = (InstImm*)editSrc(b); + InstImm* inst = (InstImm*)editSrc(b); + InstImm inst_beq = InstImm(op_beq, zero, zero, BOffImm16(0)); + uint32_t offset = dest.getOffset() - label->offset(); - // If first instruction is branch, then this is a loop backedge. - if (inst1->extractOpcode() == ((uint32_t)op_beq >> OpcodeShift)) { - // Backedges are short jumps when bound, but can become long - // when patched. - uint32_t offset = dest.getOffset() - label->offset(); + // If first instruction is lui, then this is a long jump. + // If second instruction is lui, then this is a loop backedge. + if (inst[0].extractOpcode() == (uint32_t(op_lui) >> OpcodeShift)) { + // For unconditional long branches generated by ma_liPatchable, + // such as under: + // jumpWithpatch + Assembler::UpdateLuiOriValue(inst, inst->next(), dest.getOffset()); + } else if (inst[1].extractOpcode() == (uint32_t(op_lui) >> OpcodeShift) || + BOffImm16::IsInRange(offset)) + { + // Handle code produced by: + // backedgeJump + // branchWithCode MOZ_ASSERT(BOffImm16::IsInRange(offset)); - inst1->setBOffImm16(BOffImm16(offset)); + MOZ_ASSERT(inst[0].extractOpcode() == (uint32_t(op_beq) >> OpcodeShift) || + inst[0].extractOpcode() == (uint32_t(op_bne) >> OpcodeShift) || + inst[0].extractOpcode() == (uint32_t(op_blez) >> OpcodeShift) || + inst[0].extractOpcode() == (uint32_t(op_bgtz) >> OpcodeShift)); + inst[0].setBOffImm16(BOffImm16(offset)); + } else if (inst[0].encode() == inst_beq.encode()) { + // Handle open long unconditional jumps created by + // MacroAssemblerMIPSShared::ma_b(..., wasm::JumpTarget, ...). + // We need to add it to long jumps array here. + // See MacroAssemblerMIPS::branchWithCode(). + MOZ_ASSERT(inst[1].encode() == NopInst); + MOZ_ASSERT(inst[2].encode() == NopInst); + MOZ_ASSERT(inst[3].encode() == NopInst); + addLongJump(BufferOffset(label->offset())); + Assembler::WriteLuiOriInstructions(inst, &inst[1], ScratchRegister, dest.getOffset()); + inst[2] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode(); } else { - Assembler::UpdateLuiOriValue(inst1, inst1->next(), dest.getOffset()); + // Handle open long conditional jumps created by + // MacroAssemblerMIPSShared::ma_b(..., wasm::JumpTarget, ...). + inst[0] = invertBranch(inst[0], BOffImm16(5 * sizeof(void*))); + // No need for a "nop" here because we can clobber scratch. + // We need to add it to long jumps array here. + // See MacroAssemblerMIPS::branchWithCode(). + MOZ_ASSERT(inst[1].encode() == NopInst); + MOZ_ASSERT(inst[2].encode() == NopInst); + MOZ_ASSERT(inst[3].encode() == NopInst); + MOZ_ASSERT(inst[4].encode() == NopInst); + addLongJump(BufferOffset(label->offset() + sizeof(void*))); + Assembler::WriteLuiOriInstructions(&inst[1], &inst[2], ScratchRegister, dest.getOffset()); + inst[3] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode(); } - } label->bind(dest.getOffset()); } diff --git a/js/src/jit/mips64/Assembler-mips64.cpp b/js/src/jit/mips64/Assembler-mips64.cpp index c3dc89e8f600..bcb97d32a5e2 100644 --- a/js/src/jit/mips64/Assembler-mips64.cpp +++ b/js/src/jit/mips64/Assembler-mips64.cpp @@ -310,19 +310,59 @@ Assembler::bind(RepatchLabel* label) // If the label has a use, then change this use to refer to // the bound label; BufferOffset b(label->offset()); - InstImm* inst1 = (InstImm*)editSrc(b); + InstImm* inst = (InstImm*)editSrc(b); + InstImm inst_beq = InstImm(op_beq, zero, zero, BOffImm16(0)); + uint64_t offset = dest.getOffset() - label->offset(); - // If first instruction is branch, then this is a loop backedge. - if (inst1->extractOpcode() == ((uint32_t)op_beq >> OpcodeShift)) { - // Backedges are short jumps when bound, but can become long - // when patched. - uint64_t offset = dest.getOffset() - label->offset(); + // If first instruction is lui, then this is a long jump. + // If second instruction is lui, then this is a loop backedge. + if (inst[0].extractOpcode() == (uint32_t(op_lui) >> OpcodeShift)) { + // For unconditional long branches generated by ma_liPatchable, + // such as under: + // jumpWithpatch + Assembler::UpdateLoad64Value(inst, dest.getOffset()); + } else if (inst[1].extractOpcode() == (uint32_t(op_lui) >> OpcodeShift) || + BOffImm16::IsInRange(offset)) + { + // Handle code produced by: + // backedgeJump + // branchWithCode MOZ_ASSERT(BOffImm16::IsInRange(offset)); - inst1->setBOffImm16(BOffImm16(offset)); + MOZ_ASSERT(inst[0].extractOpcode() == (uint32_t(op_beq) >> OpcodeShift) || + inst[0].extractOpcode() == (uint32_t(op_bne) >> OpcodeShift) || + inst[0].extractOpcode() == (uint32_t(op_blez) >> OpcodeShift) || + inst[0].extractOpcode() == (uint32_t(op_bgtz) >> OpcodeShift)); + inst[0].setBOffImm16(BOffImm16(offset)); + } else if (inst[0].encode() == inst_beq.encode()) { + // Handle open long unconditional jumps created by + // MacroAssemblerMIPSShared::ma_b(..., wasm::JumpTarget, ...). + // We need to add it to long jumps array here. + // See MacroAssemblerMIPS64::branchWithCode(). + MOZ_ASSERT(inst[1].encode() == NopInst); + MOZ_ASSERT(inst[2].encode() == NopInst); + MOZ_ASSERT(inst[3].encode() == NopInst); + MOZ_ASSERT(inst[4].encode() == NopInst); + MOZ_ASSERT(inst[5].encode() == NopInst); + addLongJump(BufferOffset(label->offset())); + Assembler::WriteLoad64Instructions(inst, ScratchRegister, dest.getOffset()); + inst[4] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode(); } else { - Assembler::UpdateLoad64Value(inst1, dest.getOffset()); + // Handle open long conditional jumps created by + // MacroAssemblerMIPSShared::ma_b(..., wasm::JumpTarget, ...). + inst[0] = invertBranch(inst[0], BOffImm16(7 * sizeof(uint32_t))); + // No need for a "nop" here because we can clobber scratch. + // We need to add it to long jumps array here. + // See MacroAssemblerMIPS64::branchWithCode(). + MOZ_ASSERT(inst[1].encode() == NopInst); + MOZ_ASSERT(inst[2].encode() == NopInst); + MOZ_ASSERT(inst[3].encode() == NopInst); + MOZ_ASSERT(inst[4].encode() == NopInst); + MOZ_ASSERT(inst[5].encode() == NopInst); + MOZ_ASSERT(inst[6].encode() == NopInst); + addLongJump(BufferOffset(label->offset() + sizeof(uint32_t))); + Assembler::WriteLoad64Instructions(&inst[1], ScratchRegister, dest.getOffset()); + inst[5] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode(); } - } label->bind(dest.getOffset()); }