[loong64][mips] Fix safepoint record of CallCFunction
Currently, the safepoint is last call instruction's return address on
mips and loongarch64 platform. But in `CallCFunction`, there are some
other instructions after calling, which leading to a wrong safepoint
record on mips and loongarch64.
So I record the pc for safepoint at the end of `CallCFunction`
function, and change `last_call_pc_` to `pc_for_safepoint_`.
Besides, commit 48b2b89176
introduced
a typo on loong64 platform, I also fixed it in this CL.
Change-Id: Ia3ea77ae2f6f1c8c604e35f420a7632a78c9725a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3258875
Commit-Queue: Zhao Jiazhong <zhaojiazhong-hf@loongson.cn>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77694}
This commit is contained in:
parent
92eae6d126
commit
f385232a87
@ -2137,7 +2137,7 @@ void Assembler::GrowBuffer() {
|
||||
buffer_ = std::move(new_buffer);
|
||||
buffer_start_ = new_start;
|
||||
pc_ += pc_delta;
|
||||
last_call_pc_ += pc_delta;
|
||||
pc_for_safepoint_ += pc_delta;
|
||||
reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
|
||||
reloc_info_writer.last_pc() + pc_delta);
|
||||
|
||||
|
@ -142,14 +142,13 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
void MaybeEmitOutOfLineConstantPool() {}
|
||||
|
||||
// Loong64 uses BlockTrampolinePool to prevent generating trampoline inside a
|
||||
// continuous instruction block. In the destructor of
|
||||
// BlockTrampolinePool, it must check if it needs to generate trampoline
|
||||
// immediately, if it does not do this, the branch range will go beyond the
|
||||
// max branch offset, that means the pc_offset after call CheckTrampolinePool
|
||||
// may be not the Call instruction's location. So we use last_call_pc here for
|
||||
// safepoint record.
|
||||
// continuous instruction block. In the destructor of BlockTrampolinePool, it
|
||||
// must check if it needs to generate trampoline immediately, if it does not
|
||||
// do this, the branch range will go beyond the max branch offset, that means
|
||||
// the pc_offset after call CheckTrampolinePool may have changed. So we use
|
||||
// pc_for_safepoint_ here for safepoint record.
|
||||
int pc_offset_for_safepoint() {
|
||||
return static_cast<int>(last_call_pc_ - buffer_start_);
|
||||
return static_cast<int>(pc_for_safepoint_ - buffer_start_);
|
||||
}
|
||||
|
||||
// TODO(LOONG_dev): LOONG64 Check this comment
|
||||
@ -890,7 +889,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
}
|
||||
}
|
||||
|
||||
void set_last_call_pc_(byte* pc) { last_call_pc_ = pc; }
|
||||
void set_pc_for_safepoint() { pc_for_safepoint_ = pc_; }
|
||||
|
||||
private:
|
||||
// Avoid overflows for displacements etc.
|
||||
@ -1062,7 +1061,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
// Keep track of the last Call's position to ensure that safepoint can get the
|
||||
// correct information even if there is a trampoline immediately after the
|
||||
// Call.
|
||||
byte* last_call_pc_;
|
||||
byte* pc_for_safepoint_;
|
||||
|
||||
RegList scratch_register_list_;
|
||||
|
||||
|
@ -2653,7 +2653,7 @@ void TurboAssembler::Call(Register target, Condition cond, Register rj,
|
||||
jirl(ra, target, 0);
|
||||
bind(&skip);
|
||||
}
|
||||
set_last_call_pc_(pc_);
|
||||
set_pc_for_safepoint();
|
||||
}
|
||||
|
||||
void MacroAssembler::JumpIfIsInRange(Register value, unsigned lower_limit,
|
||||
@ -2708,7 +2708,7 @@ void TurboAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
|
||||
RecordCommentForOffHeapTrampoline(builtin);
|
||||
RecordRelocInfo(RelocInfo::RELATIVE_CODE_TARGET);
|
||||
bl(code_target_index);
|
||||
set_last_call_pc_(pc_);
|
||||
set_pc_for_safepoint();
|
||||
bind(&skip);
|
||||
RecordComment("]");
|
||||
return;
|
||||
@ -4010,15 +4010,17 @@ void TurboAssembler::CallCFunctionHelper(Register function,
|
||||
li(scratch, ExternalReference::fast_c_call_caller_fp_address(isolate()));
|
||||
St_d(zero_reg, MemOperand(scratch, 0));
|
||||
}
|
||||
}
|
||||
|
||||
int stack_passed_arguments =
|
||||
CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
|
||||
int stack_passed_arguments =
|
||||
CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
|
||||
|
||||
if (base::OS::ActivationFrameAlignment() > kPointerSize) {
|
||||
Ld_d(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
|
||||
} else {
|
||||
Add_d(sp, sp, Operand(stack_passed_arguments * kPointerSize));
|
||||
if (base::OS::ActivationFrameAlignment() > kPointerSize) {
|
||||
Ld_d(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
|
||||
} else {
|
||||
Add_d(sp, sp, Operand(stack_passed_arguments * kPointerSize));
|
||||
}
|
||||
|
||||
set_pc_for_safepoint();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3564,7 +3564,7 @@ void Assembler::GrowBuffer() {
|
||||
buffer_ = std::move(new_buffer);
|
||||
buffer_start_ = new_start;
|
||||
pc_ += pc_delta;
|
||||
last_call_pc_ += pc_delta;
|
||||
pc_for_safepoint_ += pc_delta;
|
||||
reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
|
||||
reloc_info_writer.last_pc() + pc_delta);
|
||||
|
||||
@ -3828,7 +3828,7 @@ void Assembler::GenPCRelativeJumpAndLink(Register t, int32_t imm32,
|
||||
addu(t, ra, t);
|
||||
jalr(t);
|
||||
if (bdslot == PROTECT) nop();
|
||||
set_last_call_pc_(pc_);
|
||||
set_pc_for_safepoint();
|
||||
}
|
||||
|
||||
UseScratchRegisterScope::UseScratchRegisterScope(Assembler* assembler)
|
||||
|
@ -176,27 +176,9 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
// BlockTrampolinePool, it must check if it needs to generate trampoline
|
||||
// immediately, if it does not do this, the branch range will go beyond the
|
||||
// max branch offset, that means the pc_offset after call CheckTrampolinePool
|
||||
// may be not the Call instruction's location. So we use last_call_pc here for
|
||||
// safepoint record.
|
||||
// may have changed. So we use pc_for_safepoint_ here for safepoint record.
|
||||
int pc_offset_for_safepoint() {
|
||||
#ifdef DEBUG
|
||||
Instr instr1 =
|
||||
instr_at(static_cast<int>(last_call_pc_ - buffer_start_ - kInstrSize));
|
||||
Instr instr2 = instr_at(
|
||||
static_cast<int>(last_call_pc_ - buffer_start_ - kInstrSize * 2));
|
||||
if (GetOpcodeField(instr1) != SPECIAL) { // instr1 == jialc.
|
||||
DCHECK(IsMipsArchVariant(kMips32r6) && GetOpcodeField(instr1) == POP76 &&
|
||||
GetRs(instr1) == 0);
|
||||
} else {
|
||||
if (GetFunctionField(instr1) == SLL) { // instr1 == nop, instr2 == jalr.
|
||||
DCHECK(GetOpcodeField(instr2) == SPECIAL &&
|
||||
GetFunctionField(instr2) == JALR);
|
||||
} else { // instr1 == jalr.
|
||||
DCHECK(GetFunctionField(instr1) == JALR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return static_cast<int>(last_call_pc_ - buffer_start_);
|
||||
return static_cast<int>(pc_for_safepoint_ - buffer_start_);
|
||||
}
|
||||
|
||||
// Label operations & relative jumps (PPUM Appendix D).
|
||||
@ -1625,7 +1607,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
void GenPCRelativeJumpAndLink(Register t, int32_t imm32,
|
||||
RelocInfo::Mode rmode, BranchDelaySlot bdslot);
|
||||
|
||||
void set_last_call_pc_(byte* pc) { last_call_pc_ = pc; }
|
||||
void set_pc_for_safepoint() { pc_for_safepoint_ = pc_; }
|
||||
|
||||
private:
|
||||
// Avoid overflows for displacements etc.
|
||||
@ -1893,7 +1875,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
// Keep track of the last Call's position to ensure that safepoint can get the
|
||||
// correct information even if there is a trampoline immediately after the
|
||||
// Call.
|
||||
byte* last_call_pc_;
|
||||
byte* pc_for_safepoint_;
|
||||
|
||||
private:
|
||||
void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
|
||||
|
@ -3851,7 +3851,7 @@ void TurboAssembler::Call(Register target, int16_t offset, Condition cond,
|
||||
// Emit a nop in the branch delay slot if required.
|
||||
if (bd == PROTECT) nop();
|
||||
}
|
||||
set_last_call_pc_(pc_);
|
||||
set_pc_for_safepoint();
|
||||
}
|
||||
|
||||
// Note: To call gcc-compiled C code on mips, you must call through t9.
|
||||
@ -3884,7 +3884,7 @@ void TurboAssembler::Call(Register target, Register base, int16_t offset,
|
||||
// Emit a nop in the branch delay slot if required.
|
||||
if (bd == PROTECT) nop();
|
||||
}
|
||||
set_last_call_pc_(pc_);
|
||||
set_pc_for_safepoint();
|
||||
}
|
||||
|
||||
void TurboAssembler::Call(Address target, RelocInfo::Mode rmode, Condition cond,
|
||||
@ -5489,15 +5489,17 @@ void TurboAssembler::CallCFunctionHelper(Register function_base,
|
||||
li(scratch, ExternalReference::fast_c_call_caller_fp_address(isolate()));
|
||||
sw(zero_reg, MemOperand(scratch));
|
||||
}
|
||||
}
|
||||
|
||||
int stack_passed_arguments =
|
||||
CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
|
||||
int stack_passed_arguments =
|
||||
CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
|
||||
|
||||
if (base::OS::ActivationFrameAlignment() > kPointerSize) {
|
||||
lw(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
|
||||
} else {
|
||||
Addu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
|
||||
if (base::OS::ActivationFrameAlignment() > kPointerSize) {
|
||||
lw(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
|
||||
} else {
|
||||
Addu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
|
||||
}
|
||||
|
||||
set_pc_for_safepoint();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3764,7 +3764,7 @@ void Assembler::GrowBuffer() {
|
||||
buffer_ = std::move(new_buffer);
|
||||
buffer_start_ = new_start;
|
||||
pc_ += pc_delta;
|
||||
last_call_pc_ += pc_delta;
|
||||
pc_for_safepoint_ += pc_delta;
|
||||
reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
|
||||
reloc_info_writer.last_pc() + pc_delta);
|
||||
|
||||
|
@ -176,27 +176,9 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
// BlockTrampolinePool, it must check if it needs to generate trampoline
|
||||
// immediately, if it does not do this, the branch range will go beyond the
|
||||
// max branch offset, that means the pc_offset after call CheckTrampolinePool
|
||||
// may be not the Call instruction's location. So we use last_call_pc here for
|
||||
// safepoint record.
|
||||
// may have changed. So we use pc_for_safepoint_ here for safepoint record.
|
||||
int pc_offset_for_safepoint() {
|
||||
#ifdef DEBUG
|
||||
Instr instr1 =
|
||||
instr_at(static_cast<int>(last_call_pc_ - buffer_start_ - kInstrSize));
|
||||
Instr instr2 = instr_at(
|
||||
static_cast<int>(last_call_pc_ - buffer_start_ - kInstrSize * 2));
|
||||
if (GetOpcodeField(instr1) != SPECIAL) { // instr1 == jialc.
|
||||
DCHECK((kArchVariant == kMips64r6) && GetOpcodeField(instr1) == POP76 &&
|
||||
GetRs(instr1) == 0);
|
||||
} else {
|
||||
if (GetFunctionField(instr1) == SLL) { // instr1 == nop, instr2 == jalr.
|
||||
DCHECK(GetOpcodeField(instr2) == SPECIAL &&
|
||||
GetFunctionField(instr2) == JALR);
|
||||
} else { // instr1 == jalr.
|
||||
DCHECK(GetFunctionField(instr1) == JALR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return static_cast<int>(last_call_pc_ - buffer_start_);
|
||||
return static_cast<int>(pc_for_safepoint_ - buffer_start_);
|
||||
}
|
||||
|
||||
// Label operations & relative jumps (PPUM Appendix D).
|
||||
@ -1663,7 +1645,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
}
|
||||
}
|
||||
|
||||
void set_last_call_pc_(byte* pc) { last_call_pc_ = pc; }
|
||||
void set_pc_for_safepoint() { pc_for_safepoint_ = pc_; }
|
||||
|
||||
private:
|
||||
// Avoid overflows for displacements etc.
|
||||
@ -1921,7 +1903,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
// Keep track of the last Call's position to ensure that safepoint can get the
|
||||
// correct information even if there is a trampoline immediately after the
|
||||
// Call.
|
||||
byte* last_call_pc_;
|
||||
byte* pc_for_safepoint_;
|
||||
|
||||
RegList scratch_register_list_;
|
||||
|
||||
|
@ -4384,7 +4384,7 @@ void TurboAssembler::Call(Register target, Condition cond, Register rs,
|
||||
// Emit a nop in the branch delay slot if required.
|
||||
if (bd == PROTECT) nop();
|
||||
}
|
||||
set_last_call_pc_(pc_);
|
||||
set_pc_for_safepoint();
|
||||
}
|
||||
|
||||
void MacroAssembler::JumpIfIsInRange(Register value, unsigned lower_limit,
|
||||
@ -6030,15 +6030,17 @@ void TurboAssembler::CallCFunctionHelper(Register function,
|
||||
li(scratch, ExternalReference::fast_c_call_caller_fp_address(isolate()));
|
||||
Sd(zero_reg, MemOperand(scratch));
|
||||
}
|
||||
}
|
||||
|
||||
int stack_passed_arguments =
|
||||
CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
|
||||
int stack_passed_arguments =
|
||||
CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
|
||||
|
||||
if (base::OS::ActivationFrameAlignment() > kPointerSize) {
|
||||
Ld(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
|
||||
} else {
|
||||
Daddu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
|
||||
if (base::OS::ActivationFrameAlignment() > kPointerSize) {
|
||||
Ld(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
|
||||
} else {
|
||||
Daddu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
|
||||
}
|
||||
|
||||
set_pc_for_safepoint();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -703,7 +703,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (isWasmCapiFunction) {
|
||||
__ bind(&start_call);
|
||||
__ pcaddi(t7, -4);
|
||||
__ pcaddi(t7, offset >> kInstrSizeLog2);
|
||||
__ St_d(t7, MemOperand(fp, WasmExitFrameConstants::kCallingPCOffset));
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
@ -2216,7 +2216,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (call_descriptor->IsWasmImportWrapper() ||
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
|
@ -5545,15 +5545,15 @@ TEST(Call_with_trampoline) {
|
||||
__ Call(FUNCTION_ADDR(DummyFunction), RelocInfo::RUNTIME_ENTRY);
|
||||
}
|
||||
int pc_offset_after = __ pc_offset();
|
||||
int last_call_pc = __ pc_offset_for_safepoint();
|
||||
int safepoint_pc_offset = __ pc_offset_for_safepoint();
|
||||
|
||||
// Without trampoline, the Call emits no more than 6 instructions, otherwise
|
||||
// more than 6 instructions will be generated.
|
||||
int num_instrs = 6;
|
||||
// pc_offset_after records the offset after trampoline.
|
||||
CHECK_GT(pc_offset_after - pc_offset_before, num_instrs * kInstrSize);
|
||||
// last_call_pc records the offset before trampoline.
|
||||
CHECK_LE(last_call_pc - pc_offset_before, num_instrs * kInstrSize);
|
||||
// safepoint_pc_offset records the offset before trampoline.
|
||||
CHECK_LE(safepoint_pc_offset - pc_offset_before, num_instrs * kInstrSize);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
@ -6236,15 +6236,15 @@ TEST(Call_with_trampoline) {
|
||||
__ Call(FUNCTION_ADDR(DummyFunction), RelocInfo::RUNTIME_ENTRY);
|
||||
}
|
||||
int pc_offset_after = __ pc_offset();
|
||||
int last_call_pc = __ pc_offset_for_safepoint();
|
||||
int safepoint_pc_offset = __ pc_offset_for_safepoint();
|
||||
|
||||
// Without trampoline, the Call emits no more than 8 instructions, otherwise
|
||||
// more than 8 instructions will be generated.
|
||||
int num_instrs = 8;
|
||||
// pc_offset_after records the offset after trampoline.
|
||||
CHECK_GT(pc_offset_after - pc_offset_before, num_instrs * kInstrSize);
|
||||
// last_call_pc records the offset before trampoline.
|
||||
CHECK_LE(last_call_pc - pc_offset_before, num_instrs * kInstrSize);
|
||||
// safepoint_pc_offset records the offset before trampoline.
|
||||
CHECK_LE(safepoint_pc_offset - pc_offset_before, num_instrs * kInstrSize);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user