< prev index next >

src/hotspot/cpu/ppc/stubGenerator_ppc.cpp

Print this page

   1 /*
   2  * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2012, 2025 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *

 322       // pop frame
 323       __ mr(R1_SP, r_entryframe_fp);
 324 
 325       // Stack on exit from call_stub:
 326       //
 327       //      0       [C_FRAME]
 328       //              ...
 329       //
 330       //  no call_stub frames left.
 331 
 332       __ beq(CR1, ret_is_object);
 333       __ beq(CR5, ret_is_long);
 334       __ beq(CR6, ret_is_float);
 335       __ beq(CR7, ret_is_double);
 336 
 337       // default:
 338       __ stw(R3_RET, 0, r_arg_result_addr);
 339       __ blr(); // return to caller
 340 
 341       // case T_OBJECT:
 342       // case T_LONG:
 343       __ bind(ret_is_object);














 344       __ bind(ret_is_long);
 345       __ std(R3_RET, 0, r_arg_result_addr);
 346       __ blr(); // return to caller
 347 
 348       // case T_FLOAT:
 349       __ bind(ret_is_float);
 350       __ stfs(F1_RET, 0, r_arg_result_addr);
 351       __ blr(); // return to caller
 352 
 353       // case T_DOUBLE:
 354       __ bind(ret_is_double);
 355       __ stfd(F1_RET, 0, r_arg_result_addr);
 356       __ blr(); // return to caller
 357     }
 358 
 359     return start;
 360   }
 361 
 362   // Return point for a Java call if there's an exception thrown in
 363   // Java code.  The exception is caught and transformed into a

2589     // Load layout helper
2590     //
2591     //  |array_tag|     | header_size | element_type |     |log2_element_size|
2592     // 32        30    24            16              8     2                 0
2593     //
2594     //   array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
2595     //
2596 
2597     int lh_offset = in_bytes(Klass::layout_helper_offset());
2598 
2599     // Load 32-bits signed value. Use br() instruction with it to check icc.
2600     __ lwz(lh, lh_offset, src_klass);
2601 
2602     // Handle objArrays completely differently...
2603     jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
2604     __ load_const_optimized(temp, objArray_lh, R0);
2605     __ cmpw(CR0, lh, temp);
2606     __ beq(CR0, L_objArray);
2607 
2608     __ cmpd(CR5, src_klass, dst_klass);          // if (src->klass() != dst->klass()) return -1;
2609     __ cmpwi(CR6, lh, Klass::_lh_neutral_value); // if (!src->is_Array()) return -1;
2610 
2611     __ crnand(CR5, Assembler::equal, CR6, Assembler::less);
2612     __ beq(CR5, L_failed);






2613 
2614     // At this point, it is known to be a typeArray (array_tag 0x3).
2615 #ifdef ASSERT
2616     { Label L;
2617       jint lh_prim_tag_in_place = (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift);
2618       __ load_const_optimized(temp, lh_prim_tag_in_place, R0);
2619       __ cmpw(CR0, lh, temp);
2620       __ bge(CR0, L);
2621       __ stop("must be a primitive array");
2622       __ bind(L);
2623     }
2624 #endif
2625 
2626     arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
2627                            temp, dst_klass, L_failed);
2628 
2629     // TypeArrayKlass
2630     //
2631     // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
2632     // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);

4784       return_barrier_exception = true;
4785       break;
4786     default:
4787       ShouldNotReachHere();
4788     }
4789     StubCodeMark mark(this, stub_id);
4790 
4791     Register tmp1 = R10_ARG8;
4792     Register tmp2 = R9_ARG7;
4793     Register tmp3 = R8_ARG6;
4794     Register nvtmp = R15_esp;   // nonvolatile tmp register
4795     FloatRegister nvftmp = F20; // nonvolatile fp tmp register
4796 
4797     address start = __ pc();
4798 
4799     if (kind == Continuation::thaw_top) {
4800       __ clobber_nonvolatile_registers(); // Except R16_thread and R29_TOC
4801     }
4802 
4803     if (return_barrier) {

4804       __ mr(nvtmp, R3_RET); __ fmr(nvftmp, F1_RET); // preserve possible return value from a method returning to the return barrier
4805       DEBUG_ONLY(__ ld_ptr(tmp1, _abi0(callers_sp), R1_SP);)
4806       __ ld_ptr(R1_SP, JavaThread::cont_entry_offset(), R16_thread);
4807 #ifdef ASSERT
4808       __ ld_ptr(tmp2, _abi0(callers_sp), R1_SP);
4809       __ cmpd(CR0, tmp1, tmp2);
4810       __ asm_assert_eq(FILE_AND_LINE ": callers sp is corrupt");
4811 #endif
4812     }
4813 #ifdef ASSERT
4814     __ ld_ptr(tmp1, JavaThread::cont_entry_offset(), R16_thread);
4815     __ cmpd(CR0, R1_SP, tmp1);
4816     __ asm_assert_eq(FILE_AND_LINE ": incorrect R1_SP");
4817 #endif
4818 
4819     __ li(R4_ARG2, return_barrier ? 1 : 0);
4820     __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::prepare_thaw), R16_thread, R4_ARG2);
4821 
4822 #ifdef ASSERT
4823     DEBUG_ONLY(__ ld_ptr(tmp1, JavaThread::cont_entry_offset(), R16_thread));

4828     // R3_RET contains the size of the frames to thaw, 0 if overflow or no more frames
4829     Label thaw_success;
4830     __ cmpdi(CR0, R3_RET, 0);
4831     __ bne(CR0, thaw_success);
4832     __ load_const_optimized(tmp1, (SharedRuntime::throw_StackOverflowError_entry()), R0);
4833     __ mtctr(tmp1); __ bctr();
4834     __ bind(thaw_success);
4835 
4836     __ addi(R3_RET, R3_RET, frame::native_abi_reg_args_size); // Large abi required for C++ calls.
4837     __ neg(R3_RET, R3_RET);
4838     // align down resulting in a smaller negative offset
4839     __ clrrdi(R3_RET, R3_RET, exact_log2(frame::alignment_in_bytes));
4840     DEBUG_ONLY(__ mr(tmp1, R1_SP);)
4841     __ resize_frame(R3_RET, tmp2);  // make room for the thawed frames
4842 
4843     __ li(R4_ARG2, kind);
4844     __ call_VM_leaf(Continuation::thaw_entry(), R16_thread, R4_ARG2);
4845     __ mr(R1_SP, R3_RET); // R3_RET contains the SP of the thawed top frame
4846 
4847     if (return_barrier) {

4848       // we're now in the caller of the frame that returned to the barrier
4849       __ mr(R3_RET, nvtmp); __ fmr(F1_RET, nvftmp); // restore return value (no safepoint in the call to thaw, so even an oop return value should be OK)
4850     } else {
4851       // we're now on the yield frame (which is in an address above us b/c rsp has been pushed down)
4852       __ li(R3_RET, 0); // return 0 (success) from doYield
4853     }
4854 
4855     if (return_barrier_exception) {
4856       Register ex_pc = R17_tos;   // nonvolatile register
4857       __ ld(ex_pc, _abi0(lr), R1_SP); // LR
4858       __ mr(nvtmp, R3_RET); // save return value containing the exception oop
4859       // The thawed top frame has got a frame::java_abi. This is not sufficient for the runtime call.
4860       __ push_frame_reg_args(0, tmp1);
4861       __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), R16_thread, ex_pc);
4862       __ mtlr(R3_RET); // the exception handler
4863       __ pop_frame();
4864       // See OptoRuntime::generate_exception_blob for register arguments
4865       __ mr(R3_ARG1, nvtmp); // exception oop
4866       __ mr(R4_ARG2, ex_pc); // exception pc
4867     } else {

   1 /*
   2  * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2012, 2026 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *

 322       // pop frame
 323       __ mr(R1_SP, r_entryframe_fp);
 324 
 325       // Stack on exit from call_stub:
 326       //
 327       //      0       [C_FRAME]
 328       //              ...
 329       //
 330       //  no call_stub frames left.
 331 
 332       __ beq(CR1, ret_is_object);
 333       __ beq(CR5, ret_is_long);
 334       __ beq(CR6, ret_is_float);
 335       __ beq(CR7, ret_is_double);
 336 
 337       // default:
 338       __ stw(R3_RET, 0, r_arg_result_addr);
 339       __ blr(); // return to caller
 340 
 341       // case T_OBJECT:

 342       __ bind(ret_is_object);
 343       if (InlineTypeReturnedAsFields) {
 344         // Check for scalarized return value
 345         __ cmpdi(CR0, R3_RET, 0);
 346         __ beq(CR0, ret_is_long);
 347         // Load pack handler address
 348         __ untested("call stub InlineTypeReturnedAsFields"); // TODO: check return registers usage
 349         __ andi(R12_scratch2, R3_RET, -2);
 350         __ ld(R12_scratch2, InlineKlass::adr_members_offset(), R12_scratch2);
 351         __ ld(R12_scratch2, InlineKlass::pack_handler_jobject_offset(), R12_scratch2);
 352         __ mtctr(R12_scratch2);
 353         __ bctr(); // tail call
 354       } // else fall through
 355 
 356       // case T_LONG:
 357       __ bind(ret_is_long);
 358       __ std(R3_RET, 0, r_arg_result_addr);
 359       __ blr(); // return to caller
 360 
 361       // case T_FLOAT:
 362       __ bind(ret_is_float);
 363       __ stfs(F1_RET, 0, r_arg_result_addr);
 364       __ blr(); // return to caller
 365 
 366       // case T_DOUBLE:
 367       __ bind(ret_is_double);
 368       __ stfd(F1_RET, 0, r_arg_result_addr);
 369       __ blr(); // return to caller
 370     }
 371 
 372     return start;
 373   }
 374 
 375   // Return point for a Java call if there's an exception thrown in
 376   // Java code.  The exception is caught and transformed into a

2602     // Load layout helper
2603     //
2604     //  |array_tag|     | header_size | element_type |     |log2_element_size|
2605     // 32        30    24            16              8     2                 0
2606     //
2607     //   array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
2608     //
2609 
2610     int lh_offset = in_bytes(Klass::layout_helper_offset());
2611 
2612     // Load 32-bits signed value. Use br() instruction with it to check icc.
2613     __ lwz(lh, lh_offset, src_klass);
2614 
2615     // Handle objArrays completely differently...
2616     jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
2617     __ load_const_optimized(temp, objArray_lh, R0);
2618     __ cmpw(CR0, lh, temp);
2619     __ beq(CR0, L_objArray);
2620 
2621     __ cmpd(CR5, src_klass, dst_klass);          // if (src->klass() != dst->klass()) return -1;
2622     __ bne(CR5, L_failed);
2623 
2624     // Check for flat inline type array -> return -1
2625     __ test_flat_array_oop(src, temp, L_failed);
2626 
2627     // Check for null-free (non-flat) inline type array -> handle as object array
2628     __ test_null_free_array_oop(src, temp, L_objArray);
2629 
2630     __ cmpwi(CR6, lh, Klass::_lh_neutral_value); // if (!src->is_Array()) return -1;
2631     __ bge(CR6, L_failed);
2632 
2633     // At this point, it is known to be a typeArray (array_tag 0x3).
2634 #ifdef ASSERT
2635     { Label L;
2636       jint lh_prim_tag_in_place = (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift);
2637       __ load_const_optimized(temp, lh_prim_tag_in_place, R0);
2638       __ cmpw(CR0, lh, temp);
2639       __ bge(CR0, L);
2640       __ stop("must be a primitive array");
2641       __ bind(L);
2642     }
2643 #endif
2644 
2645     arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
2646                            temp, dst_klass, L_failed);
2647 
2648     // TypeArrayKlass
2649     //
2650     // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
2651     // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);

4803       return_barrier_exception = true;
4804       break;
4805     default:
4806       ShouldNotReachHere();
4807     }
4808     StubCodeMark mark(this, stub_id);
4809 
4810     Register tmp1 = R10_ARG8;
4811     Register tmp2 = R9_ARG7;
4812     Register tmp3 = R8_ARG6;
4813     Register nvtmp = R15_esp;   // nonvolatile tmp register
4814     FloatRegister nvftmp = F20; // nonvolatile fp tmp register
4815 
4816     address start = __ pc();
4817 
4818     if (kind == Continuation::thaw_top) {
4819       __ clobber_nonvolatile_registers(); // Except R16_thread and R29_TOC
4820     }
4821 
4822     if (return_barrier) {
4823       assert(!InlineTypeReturnedAsFields, "unsupported");
4824       __ mr(nvtmp, R3_RET); __ fmr(nvftmp, F1_RET); // preserve possible return value from a method returning to the return barrier
4825       DEBUG_ONLY(__ ld_ptr(tmp1, _abi0(callers_sp), R1_SP);)
4826       __ ld_ptr(R1_SP, JavaThread::cont_entry_offset(), R16_thread);
4827 #ifdef ASSERT
4828       __ ld_ptr(tmp2, _abi0(callers_sp), R1_SP);
4829       __ cmpd(CR0, tmp1, tmp2);
4830       __ asm_assert_eq(FILE_AND_LINE ": callers sp is corrupt");
4831 #endif
4832     }
4833 #ifdef ASSERT
4834     __ ld_ptr(tmp1, JavaThread::cont_entry_offset(), R16_thread);
4835     __ cmpd(CR0, R1_SP, tmp1);
4836     __ asm_assert_eq(FILE_AND_LINE ": incorrect R1_SP");
4837 #endif
4838 
4839     __ li(R4_ARG2, return_barrier ? 1 : 0);
4840     __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::prepare_thaw), R16_thread, R4_ARG2);
4841 
4842 #ifdef ASSERT
4843     DEBUG_ONLY(__ ld_ptr(tmp1, JavaThread::cont_entry_offset(), R16_thread));

4848     // R3_RET contains the size of the frames to thaw, 0 if overflow or no more frames
4849     Label thaw_success;
4850     __ cmpdi(CR0, R3_RET, 0);
4851     __ bne(CR0, thaw_success);
4852     __ load_const_optimized(tmp1, (SharedRuntime::throw_StackOverflowError_entry()), R0);
4853     __ mtctr(tmp1); __ bctr();
4854     __ bind(thaw_success);
4855 
4856     __ addi(R3_RET, R3_RET, frame::native_abi_reg_args_size); // Large abi required for C++ calls.
4857     __ neg(R3_RET, R3_RET);
4858     // align down resulting in a smaller negative offset
4859     __ clrrdi(R3_RET, R3_RET, exact_log2(frame::alignment_in_bytes));
4860     DEBUG_ONLY(__ mr(tmp1, R1_SP);)
4861     __ resize_frame(R3_RET, tmp2);  // make room for the thawed frames
4862 
4863     __ li(R4_ARG2, kind);
4864     __ call_VM_leaf(Continuation::thaw_entry(), R16_thread, R4_ARG2);
4865     __ mr(R1_SP, R3_RET); // R3_RET contains the SP of the thawed top frame
4866 
4867     if (return_barrier) {
4868       assert(!InlineTypeReturnedAsFields, "unsupported");
4869       // we're now in the caller of the frame that returned to the barrier
4870       __ mr(R3_RET, nvtmp); __ fmr(F1_RET, nvftmp); // restore return value (no safepoint in the call to thaw, so even an oop return value should be OK)
4871     } else {
4872       // we're now on the yield frame (which is in an address above us b/c rsp has been pushed down)
4873       __ li(R3_RET, 0); // return 0 (success) from doYield
4874     }
4875 
4876     if (return_barrier_exception) {
4877       Register ex_pc = R17_tos;   // nonvolatile register
4878       __ ld(ex_pc, _abi0(lr), R1_SP); // LR
4879       __ mr(nvtmp, R3_RET); // save return value containing the exception oop
4880       // The thawed top frame has got a frame::java_abi. This is not sufficient for the runtime call.
4881       __ push_frame_reg_args(0, tmp1);
4882       __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), R16_thread, ex_pc);
4883       __ mtlr(R3_RET); // the exception handler
4884       __ pop_frame();
4885       // See OptoRuntime::generate_exception_blob for register arguments
4886       __ mr(R3_ARG1, nvtmp); // exception oop
4887       __ mr(R4_ARG2, ex_pc); // exception pc
4888     } else {
< prev index next >