Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
* Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -442,15 +442,13 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
return; // CodeCache is full
}

bool success = ce->emit_trampoline_stub_for_call(SharedRuntime::get_resolve_static_call_stub());
if (!success) { return; }

__ relocate(relocInfo::static_call_type);
// Note: At this point we do not have the address of the trampoline
// stub, and the entry point might be too far away for bl, so __ pc()
// serves as dummy and the bl will be patched later.
__ code()->set_insts_mark();
__ bl(__ pc());
AddressLiteral resolve(SharedRuntime::get_resolve_static_call_stub(),
relocInfo::static_call_type);
address call_pc = __ trampoline_call(resolve);
if (call_pc == nullptr) {
ce->bailout("const/stub overflow in call with trampoline");
return;
}
ce->add_call_info_here(info());
ce->verify_oop_map(info());

Expand Down
60 changes: 9 additions & 51 deletions src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -610,67 +610,25 @@ void LIR_Assembler::align_call(LIR_Code) {
// do nothing since all instructions are word aligned on ppc
}


bool LIR_Assembler::emit_trampoline_stub_for_call(address target, Register Rtoc) {
int start_offset = __ offset();
// Put the entry point as a constant into the constant pool.
const address entry_point_toc_addr = __ address_constant(target, RelocationHolder::none);
if (entry_point_toc_addr == nullptr) {
bailout("const section overflow");
return false;
}
const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);

// Emit the trampoline stub which will be related to the branch-and-link below.
address stub = __ emit_trampoline_stub(entry_point_toc_offset, start_offset, Rtoc);
if (!stub) {
bailout("no space for trampoline stub");
return false;
}
return true;
}


void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
assert(rtype==relocInfo::opt_virtual_call_type || rtype==relocInfo::static_call_type, "unexpected rtype");

bool success = emit_trampoline_stub_for_call(op->addr());
if (!success) { return; }

__ relocate(rtype);
// Note: At this point we do not have the address of the trampoline
// stub, and the entry point might be too far away for bl, so __ pc()
// serves as dummy and the bl will be patched later.
__ code()->set_insts_mark();
__ bl(__ pc());
address call_pc = __ trampoline_call(AddressLiteral(op->addr(), rtype));
if (call_pc == nullptr) {
bailout("const/stub overflow in call with trampoline");
return;
}
add_call_info(code_offset(), op->info());
__ post_call_nop();
}


void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
__ calculate_address_from_global_toc(R2_TOC, __ method_toc());

// Virtual call relocation will point to ic load.
address virtual_call_meta_addr = __ pc();
// Load a clear inline cache.
AddressLiteral empty_ic((address) Universe::non_oop_word());
bool success = __ load_const_from_method_toc(R19_inline_cache_reg, empty_ic, R2_TOC);
bool success = __ ic_call(R2_TOC, op->addr());
if (!success) {
bailout("const section overflow");
bailout("const/stub overflow in ic_call with trampoline");
return;
}
// Call to fixup routine. Fixup routine uses ScopeDesc info
// to determine who we intended to call.
__ relocate(virtual_call_Relocation::spec(virtual_call_meta_addr));

success = emit_trampoline_stub_for_call(op->addr(), R2_TOC);
if (!success) { return; }

// Note: At this point we do not have the address of the trampoline
// stub, and the entry point might be too far away for bl, so __ pc()
// serves as dummy and the bl will be patched later.
__ bl(__ pc());
add_call_info(code_offset(), op->info());
__ post_call_nop();
}
Expand Down
10 changes: 5 additions & 5 deletions src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -26,6 +26,9 @@
#ifndef CPU_PPC_C1_LIRASSEMBLER_PPC_HPP
#define CPU_PPC_C1_LIRASSEMBLER_PPC_HPP

// ArrayCopyStub needs access to bailout
friend class ArrayCopyStub;

private:

//////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -56,9 +59,6 @@
public:
static const ConditionRegister BOOL_RESULT;

// Emit trampoline stub for call. Call bailout() if failed. Return true on success.
bool emit_trampoline_stub_for_call(address target, Register Rtoc = noreg);

enum {
_static_call_stub_size = 4 * BytesPerInstWord + MacroAssembler::b64_patchable_size, // or smaller
_call_stub_size = _static_call_stub_size + MacroAssembler::trampoline_stub_size, // or smaller
Expand Down
131 changes: 69 additions & 62 deletions src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,75 @@ address MacroAssembler::call_c_using_toc(const FunctionDescriptor* fd,
}
#endif // ABI_ELFv2

bool MacroAssembler::ic_call(Register Rmethod_toc,
address target,
jint method_index,
bool scratch_emit,
bool fixed_size) {
AddressLiteral target_al(target, virtual_call_Relocation::spec(pc(), method_index));
DEBUG_ONLY(int ic_load_offset = offset());

// Load a clear inline cache.
AddressLiteral empty_ic((address) Universe::non_oop_word());
bool success = load_const_from_method_toc(R19_inline_cache_reg, empty_ic, Rmethod_toc, fixed_size);
if (!success) return false;

assert(MacroAssembler::is_load_const_from_method_toc_at(addr_at(ic_load_offset)),
"should be load from TOC");

address call_pc = trampoline_call(target_al, Rmethod_toc, scratch_emit);
return call_pc != nullptr;
}

address MacroAssembler::trampoline_call(AddressLiteral target,
Register Rmethod_toc,
bool scratch_emit) {
// First, emit the trampoline stub
if (!scratch_emit) {
RelocationHolder rh = trampoline_stub_Relocation::spec(pc() /* of the bl below */);

// Put the target's entry point as a constant into the constant pool.
const address target_toc_addr = address_constant((address)target.value());
if (target_toc_addr == nullptr) return nullptr;

const int target_toc_offset = offset_to_method_toc(target_toc_addr);
address stub = start_a_stub(64);
if (stub == nullptr) return nullptr;

// Annotate the stub with a relocation that points to the owning call instruction.
relocate(rh);
DEBUG_ONLY(int stub_start_offset = offset());

// For java_to_interp stubs we use R11_scratch1 as scratch register
// and in call trampoline stubs we use R12_scratch2. This way we
// can distinguish them (see is_NativeCallTrampolineStub_at()).
Register reg_scratch = R12_scratch2;

if (Rmethod_toc == noreg) {
calculate_address_from_global_toc(reg_scratch, method_toc());
Rmethod_toc = reg_scratch;
}

ld_largeoffset_unchecked(reg_scratch, target_toc_offset, Rmethod_toc, false);
mtctr(reg_scratch);
bctr();

assert(target_toc_offset == NativeCallTrampolineStub_at(addr_at(stub_start_offset))->destination_toc_offset(),
"encoded offset into the constant pool must match");
assert((uint)(offset() - stub_start_offset) <= trampoline_stub_size, "should be good size");
assert(is_NativeCallTrampolineStub_at(addr_at(stub_start_offset)), "doesn't look like a trampoline");

// End the stub.
end_a_stub();
}

// The call will be resolved / patched later.
address call_pc = pc();
relocate(target.rspec());
bl(call_pc);
return call_pc;
}

void MacroAssembler::post_call_nop() {
// Make inline again when loom is always enabled.
if (!Continuations::enabled()) {
Expand Down Expand Up @@ -2626,50 +2695,6 @@ void MacroAssembler::tlab_allocate(
//verify_tlab(); not implemented
}

address MacroAssembler::emit_trampoline_stub(int destination_toc_offset,
int insts_call_instruction_offset, Register Rtoc) {
// Start the stub.
address stub = start_a_stub(64);
if (stub == nullptr) { return nullptr; } // CodeCache full: bail out

// Create a trampoline stub relocation which relates this trampoline stub
// with the call instruction at insts_call_instruction_offset in the
// instructions code-section.
relocate(trampoline_stub_Relocation::spec(code()->insts()->start() + insts_call_instruction_offset));
const int stub_start_offset = offset();

// For java_to_interp stubs we use R11_scratch1 as scratch register
// and in call trampoline stubs we use R12_scratch2. This way we
// can distinguish them (see is_NativeCallTrampolineStub_at()).
Register reg_scratch = R12_scratch2;

// Now, create the trampoline stub's code:
// - load the TOC
// - load the call target from the constant pool
// - call
if (Rtoc == noreg) {
calculate_address_from_global_toc(reg_scratch, method_toc());
Rtoc = reg_scratch;
}

ld_largeoffset_unchecked(reg_scratch, destination_toc_offset, Rtoc, false);
mtctr(reg_scratch);
bctr();

const address stub_start_addr = addr_at(stub_start_offset);

// Assert that the encoded destination_toc_offset can be identified and that it is correct.
assert(destination_toc_offset == NativeCallTrampolineStub_at(stub_start_addr)->destination_toc_offset(),
"encoded offset into the constant pool must match");
// Trampoline_stub_size should be good.
assert((uint)(offset() - stub_start_offset) <= trampoline_stub_size, "should be good size");
assert(is_NativeCallTrampolineStub_at(stub_start_addr), "doesn't look like a trampoline");

// End the stub.
end_a_stub();
return stub;
}

// "The box" is the space on the stack where we copy the object mark.
void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register oop, Register box,
Register temp, Register displaced_header, Register current_header) {
Expand Down Expand Up @@ -3436,24 +3461,6 @@ void MacroAssembler::store_klass_gap(Register dst_oop, Register val) {
}
}

int MacroAssembler::instr_size_for_load_klass() {
static int computed_size = -1;

// Not yet computed?
if (computed_size == -1) {

// Determine by scratch emit.
ResourceMark rm;
int code_size = 16 * BytesPerInstWord;
CodeBuffer cb("load_klass scratch buffer", code_size, 0);
MacroAssembler* a = new MacroAssembler(&cb);
a->load_klass(R11_scratch1, R11_scratch1);
computed_size = a->offset();
}

return computed_size;
}

void MacroAssembler::decode_klass_not_null(Register dst, Register src) {
assert(dst != R0, "Dst reg may not be R0, as R0 is used here.");
if (src == noreg) src = dst;
Expand Down
15 changes: 11 additions & 4 deletions src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,20 @@ class MacroAssembler: public Assembler {
Register toc);
#endif

// CompiledIC call
bool ic_call(Register Rmethod_toc,
address target,
jint method_index = 0,
bool scratch_emit = false,
bool fixed_size = false);
static int ic_check_size();
int ic_check(int end_alignment);

enum { trampoline_stub_size = 6 * 4 };
address trampoline_call(AddressLiteral target,
Register Rmethod_toc = noreg,
bool scratch_emit = false);

protected:

// It is imperative that all calls into the VM are handled via the
Expand Down Expand Up @@ -704,9 +715,6 @@ class MacroAssembler: public Assembler {
Label& slow_case // continuation point if fast allocation fails
);

enum { trampoline_stub_size = 6 * 4 };
address emit_trampoline_stub(int destination_toc_offset, int insts_call_instruction_offset, Register Rtoc = noreg);

void compiler_fast_lock_object(ConditionRegister flag, Register oop, Register box,
Register tmp1, Register tmp2, Register tmp3);

Expand Down Expand Up @@ -810,7 +818,6 @@ class MacroAssembler: public Assembler {
MacroAssembler::PreservationLevel preservation_level);
void load_method_holder(Register holder, Register method);

static int instr_size_for_load_klass();
void decode_klass_not_null(Register dst, Register src = noreg);
Register encode_klass_not_null(Register dst, Register src = noreg);

Expand Down
Loading