Skip to content
Closed
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
8 changes: 5 additions & 3 deletions src/hotspot/cpu/s390/abstractInterpreter_s390.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -197,8 +197,10 @@ void AbstractInterpreter::layout_activation(Method* method,
assert(is_bottom_frame && (sender_sp == caller->unextended_sp()),
"must initialize sender_sp of bottom skeleton frame when pushing it");
} else {
assert(caller->is_entry_frame() || caller->is_upcall_stub_frame(), "is there a new frame type??");
sender_sp = caller->sp(); // Call_stub only uses it's fp.
// For entry, upcall_stub, and native frames, sender_sp is simply the caller's sp.
// These frames use the standard C ABI and don't require adjustment.
assert(caller->is_entry_frame() || caller->is_upcall_stub_frame() || caller->is_native_frame(), "is there a new frame type??");
sender_sp = caller->sp();
}

interpreter_frame->interpreter_frame_set_method(method);
Expand Down
5 changes: 4 additions & 1 deletion src/hotspot/cpu/s390/assembler_s390.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -3279,6 +3279,9 @@ class Assembler : public AbstractAssembler {
static bool is_z_nop(address x) {
return is_z_nop(* (short *) x);
}
static bool is_z_illtrap(address x) {
return *(uint16_t*)x == 0u;
}
static bool is_z_br(long x) {
return is_z_bcr(x) && ((x & 0x00f0) == 0x00f0);
}
Expand Down
4 changes: 3 additions & 1 deletion src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
__ z_nop();
__ z_brasl(Z_R14, op->addr());
add_call_info(code_offset(), op->info());
__ post_call_nop();
}

void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
Expand All @@ -539,7 +540,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
// CALL to fixup routine. Fixup routine uses ScopeDesc info
// to determine who we intended to call.
__ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr));
call(op, relocInfo::none);
call(op, relocInfo::none); // call will emit a post call nop, see above method.
}

void LIR_Assembler::move_regs(Register from_reg, Register to_reg) {
Expand Down Expand Up @@ -2845,6 +2846,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest,
if (info != nullptr) {
add_call_info_here(info);
}
__ post_call_nop();
}

void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) {
Expand Down
49 changes: 38 additions & 11 deletions src/hotspot/cpu/s390/c1_Runtime1_s390.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -52,13 +52,8 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre
set_num_rt_args(0); // Nothing on stack.
assert(!(oop_result1->is_valid() || metadata_result->is_valid()) || oop_result1 != metadata_result, "registers must be different");

// We cannot trust that code generated by the C++ compiler saves R14
// to z_abi_160.return_pc, because sometimes it spills R14 using stmg at
// z_abi_160.gpr14 (e.g. InterpreterRuntime::_new()).
// Therefore we load the PC into Z_R1_scratch and let set_last_Java_frame() save
// it into the frame anchor.
address pc = get_PC(Z_R1_scratch);
int call_offset = (int)(pc - addr_at(0));
Label resume;
z_larl(Z_R1_scratch, resume);
set_last_Java_frame(Z_SP, Z_R1_scratch);

// ARG1 must hold thread address.
Expand All @@ -67,9 +62,12 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre
address return_pc = nullptr;
align_call_far_patchable(this->pc());
return_pc = call_c_opt(entry_point);

bind(resume);
int call_offset = offset();
assert(return_pc != nullptr, "const section overflow");

reset_last_Java_frame();
reset_last_Java_frame(/* check_last_java_sp= */ false);

// Check for pending exceptions.
{
Expand Down Expand Up @@ -208,8 +206,37 @@ void Runtime1::initialize_pd() {
}

uint Runtime1::runtime_blob_current_thread_offset(frame f) {
Unimplemented();
return 0;
CodeBlob* cb = f.cb();
assert(cb == Runtime1::blob_for(StubId::c1_monitorenter_id) ||
cb == Runtime1::blob_for(StubId::c1_monitorenter_nofpu_id), "must be");
assert(cb != nullptr && cb->is_runtime_stub(), "invalid frame");

// Calculate the offset of Z_thread (Z_R8) in the saved register area.
// Both c1_monitorenter_id and c1_monitorenter_nofpu_id have the same frame layout:
// - c1_monitorenter_id uses RegisterSaver::all_registers (saves FPU regs)
// - c1_monitorenter_nofpu_id uses RegisterSaver::all_integer_registers (excludes FPU regs but reserves space)
//
// From RegisterSaver_LiveRegs and RegisterSaver_LiveIntRegs:
// Both have 15 float register slots (F0, F2-F15, F1 is excluded as scratch)
// Then integer registers: R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13
// Z_thread is Z_R8, which is the 7th integer register (index 6 from R2)
//
// Stack layout from SP:
// [0..159] : z_abi_160
// [160..279] : 15 float register slots (15 * 8 = 120 bytes)
// [280..327] : R2-R7 (6 * 8 = 48 bytes)
// [328..335] : R8 (Z_thread) <- this is what we need
//
// Offset = 160 + 120 + 48 = 328 bytes from SP
// Return value is in 64-bit words: 328 / 8 = 41

const int float_reg_slots = 15; // F0, F2-F15 (F1 is scratch, excluded)
const int int_regs_before_r8 = 6; // R2, R3, R4, R5, R6, R7
const int z_thread_offset = frame::z_abi_160_size +
(float_reg_slots * 8) +
(int_regs_before_r8 * 8);

return z_thread_offset / wordSize;
}

OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) {
Expand Down
6 changes: 5 additions & 1 deletion src/hotspot/cpu/s390/continuationEntry_s390.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2026 IBM Corporation. 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 @@ -25,8 +26,11 @@
#ifndef CPU_S390_CONTINUATIONENTRY_S390_HPP
#define CPU_S390_CONTINUATIONENTRY_S390_HPP

#include "runtime/frame.hpp"

class ContinuationEntryPD {
// empty
// This is needed to position the ContinuationEntry at the unextended sp of the entry frame
frame::z_abi_160_base _abi;
};

#endif // CPU_S390_CONTINUATIONENTRY_S390_HPP
23 changes: 15 additions & 8 deletions src/hotspot/cpu/s390/continuationEntry_s390.inline.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2026 IBM Corporation. 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 @@ -25,22 +26,28 @@
#ifndef CPU_S390_CONTINUATIONENTRY_S390_INLINE_HPP
#define CPU_S390_CONTINUATIONENTRY_S390_INLINE_HPP

#include "oops/method.inline.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/registerMap.hpp"
#include "utilities/macros.hpp"
#include "runtime/continuationEntry.hpp"

// TODO: Implement

inline frame ContinuationEntry::to_frame() const {
Unimplemented();
return frame();
static CodeBlob* cb = CodeCache::find_blob_fast(entry_pc());
assert(cb != nullptr, "");
assert(cb->as_nmethod()->method()->is_continuation_enter_intrinsic(), "");
return frame(entry_sp(), entry_pc(), entry_sp(), entry_fp(), cb);
}

inline intptr_t* ContinuationEntry::entry_fp() const {
Unimplemented();
return nullptr;
return (intptr_t*)((address)this + size());
}

inline void ContinuationEntry::update_register_map(RegisterMap* map) const {
Unimplemented();
// No register map update needed for s390.
// In the Java calling convention on s390, all registers are volatile (caller-saved),
// so there are no non-volatile (callee-saved) registers that need to be tracked
// in the register map for continuation entry frames.
}

#endif // CPU_S390_CONTINUATIONENTRY_S390_INLINE_HPP
Loading