/* * Copyright (c) 2020, 2022, Oracle and/or its affiliates. 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
constexpr int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions
staticvoid preserve_callee_saved_registers(MacroAssembler* _masm, const ABIDescriptor& abi, int reg_save_area_offset) { // 1. iterate all registers in the architecture // - check if they are volatile or not for the given abi // - if NOT, we need to save it here // 2. save mxcsr on non-windows platforms
int offset = reg_save_area_offset;
__ block_comment("{ preserve_callee_saved_regs "); for (Register reg = as_Register(0); reg->is_valid(); reg = reg->successor()) { if (reg == rbp || reg == rsp) continue; // saved/restored by prologue/epilogue if (!abi.is_volatile_reg(reg)) {
__ movptr(Address(rsp, offset), reg);
offset += 8;
}
}
staticvoid restore_callee_saved_registers(MacroAssembler* _masm, const ABIDescriptor& abi, int reg_save_area_offset) { // 1. iterate all registers in the architecture // - check if they are volatile or not for the given abi // - if NOT, we need to restore it here // 2. restore mxcsr on non-windows platforms
int offset = reg_save_area_offset;
__ block_comment("{ restore_callee_saved_regs "); for (Register reg = as_Register(0); reg->is_valid(); reg = reg->successor()) { if (reg == rbp || reg == rsp) continue; // saved/restored by prologue/epilogue if (!abi.is_volatile_reg(reg)) {
__ movptr(reg, Address(rsp, offset));
offset += 8;
}
}
// out_arg_area (for stack arguments) doubles as shadow space for native calls. // make sure it is big enough. if (out_arg_area < frame::arg_reg_save_area_bytes) {
out_arg_area = frame::arg_reg_save_area_bytes;
}
int reg_save_area_size = compute_reg_save_area_size(abi);
RegSpiller arg_spilller(call_regs._arg_regs);
RegSpiller result_spiller(call_regs._ret_regs);
int shuffle_area_offset = 0; int res_save_area_offset = shuffle_area_offset + out_arg_area; int arg_save_area_offset = res_save_area_offset + result_spiller.spill_size_bytes(); int reg_save_area_offset = arg_save_area_offset + arg_spilller.spill_size_bytes(); int frame_data_offset = reg_save_area_offset + reg_save_area_size; int frame_bottom_offset = frame_data_offset + sizeof(UpcallStub::FrameData);
StubLocations locs; int ret_buf_offset = -1; if (needs_return_buffer) {
ret_buf_offset = frame_bottom_offset;
frame_bottom_offset += ret_buf_size; // use a free register for shuffling code to pick up return // buffer address from
locs.set(StubLocations::RETURN_BUFFER, abi._scratch1);
}
int frame_size = frame_bottom_offset;
frame_size = align_up(frame_size, StackAlignmentInBytes);
// Ok The space we have allocated will look like: // // // FP-> | | // |---------------------| = frame_bottom_offset = frame_size // | (optional) | // | ret_buf | // |---------------------| = ret_buf_offset // | | // | FrameData | // |---------------------| = frame_data_offset // | | // | reg_save_area | // |---------------------| = reg_save_are_offset // | | // | arg_save_area | // |---------------------| = arg_save_are_offset // | | // | res_save_area | // |---------------------| = res_save_are_offset // | | // SP-> | out_arg_area | needs to be at end for shadow space // //
MacroAssembler* _masm = new MacroAssembler(&buffer);
address start = __ pc();
__ enter(); // set up frame if ((abi._stack_alignment_bytes % 16) != 0) { // stack alignment of caller is not a multiple of 16
__ andptr(rsp, -StackAlignmentInBytes); // align stack
} // allocate frame (frame_size is also aligned, so stack is still aligned)
__ subptr(rsp, frame_size);
// we have to always spill args since we need to do a call to get the thread // (and maybe attach it).
arg_spilller.generate_spill(_masm, arg_save_area_offset);
// return value shuffle if (!needs_return_buffer) { #ifdef ASSERT if (call_regs._ret_regs.length() == 1) { // 0 or 1
VMStorage j_expected_result_reg; switch (ret_type) { case T_BOOLEAN: case T_BYTE: case T_SHORT: case T_CHAR: case T_INT: case T_LONG:
j_expected_result_reg = as_VMStorage(rax); break; case T_FLOAT: case T_DOUBLE:
j_expected_result_reg = as_VMStorage(xmm0); break; default:
fatal("unexpected return type: %s", type2name(ret_type));
} // No need to move for now, since CallArranger can pick a return type // that goes in the same reg for both CCs. But, at least assert they are the same
assert(call_regs._ret_regs.at(0) == j_expected_result_reg, "unexpected result register");
} #endif
} else {
assert(ret_buf_offset != -1, "no return buffer allocated");
__ lea(rscratch1, Address(rsp, ret_buf_offset)); int offset = 0; for (int i = 0; i < call_regs._ret_regs.length(); i++) {
VMStorage reg = call_regs._ret_regs.at(i); if (reg.type() == StorageType::INTEGER) {
__ movptr(as_Register(reg), Address(rscratch1, offset));
offset += 8;
} elseif (reg.type() == StorageType::VECTOR) {
__ movdqu(as_XMMRegister(reg), Address(rscratch1, offset));
offset += 16;
} else {
ShouldNotReachHere();
}
}
}
// TODO: this is always the same, can we bypass and call handle_uncaught_exception directly?
// native caller has no idea how to handle exceptions // we just crash here. Up to callee to catch exceptions.
__ verify_oop(rax);
__ vzeroupper();
__ mov(c_rarg0, rax);
__ andptr(rsp, -StackAlignmentInBytes); // align stack as required by ABI
__ subptr(rsp, frame::arg_reg_save_area_bytes); // windows (not really needed)
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, UpcallLinker::handle_uncaught_exception)));
__ should_not_reach_here();
__ block_comment("} exception handler");
_masm->flush();
#ifndef PRODUCT
stringStream ss;
ss.print("upcall_stub_%s", entry->signature()->as_C_string()); constchar* name = _masm->code_string(ss.freeze()); #else// PRODUCT constchar* name = "upcall_stub"; #endif// PRODUCT
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-04-26)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.