< prev index next >

src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp

Print this page
@@ -502,24 +502,29 @@
  
      // store result depending on type (everything that is not
      // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
      // n.b. this assumes Java returns an integral result in r0
      // and a floating result in j_farg0
-     __ ldr(j_rarg2, result);
-     Label is_long, is_float, is_double, exit;
-     __ ldr(j_rarg1, result_type);
-     __ cmp(j_rarg1, (u1)T_OBJECT);
+     // All of j_rargN may be used to return inline type fields so be careful
+     // not to clobber those.
+     // SharedRuntime::generate_buffered_inline_type_adapter() knows the register
+     // assignment of Rresult below.
+     Register Rresult = r14, Rresult_type = r15;
+     __ ldr(Rresult, result);
+     Label is_long, is_float, is_double, check_prim, exit;
+     __ ldr(Rresult_type, result_type);
+     __ cmp(Rresult_type, (u1)T_OBJECT);
+     __ br(Assembler::EQ, check_prim);
+     __ cmp(Rresult_type, (u1)T_LONG);
      __ br(Assembler::EQ, is_long);
-     __ cmp(j_rarg1, (u1)T_LONG);
-     __ br(Assembler::EQ, is_long);
-     __ cmp(j_rarg1, (u1)T_FLOAT);
+     __ cmp(Rresult_type, (u1)T_FLOAT);
      __ br(Assembler::EQ, is_float);
-     __ cmp(j_rarg1, (u1)T_DOUBLE);
+     __ cmp(Rresult_type, (u1)T_DOUBLE);
      __ br(Assembler::EQ, is_double);
  
      // handle T_INT case
-     __ strw(r0, Address(j_rarg2));
+     __ strw(r0, Address(Rresult));
  
      __ BIND(exit);
  
      // pop parameters
      __ sub(esp, rfp, -sp_after_call_off * wordSize);

@@ -567,21 +572,32 @@
      // leave frame and return to caller
      __ leave();
      __ ret(lr);
  
      // handle return types different from T_INT
+     __ BIND(check_prim);
+     if (InlineTypeReturnedAsFields) {
+       // Check for scalarized return value
+       __ tbz(r0, 0, is_long);
+       // Load pack handler address
+       __ andr(rscratch1, r0, -2);
+       __ ldr(rscratch1, Address(rscratch1, InlineKlass::adr_members_offset()));
+       __ ldr(rscratch1, Address(rscratch1, InlineKlass::pack_handler_jobject_offset()));
+       __ blr(rscratch1);
+       __ b(exit);
+     }
  
      __ BIND(is_long);
-     __ str(r0, Address(j_rarg2, 0));
+     __ str(r0, Address(Rresult, 0));
      __ br(Assembler::AL, exit);
  
      __ BIND(is_float);
-     __ strs(j_farg0, Address(j_rarg2, 0));
+     __ strs(j_farg0, Address(Rresult, 0));
      __ br(Assembler::AL, exit);
  
      __ BIND(is_double);
-     __ strd(j_farg0, Address(j_rarg2, 0));
+     __ strd(j_farg0, Address(Rresult, 0));
      __ br(Assembler::AL, exit);
  
      // record the stub entry and end plus the auxiliary entry
      store_archive_data(stub_id, start, __ pc(), &entries);
  

@@ -2605,10 +2621,16 @@
      //  if (src->klass() != dst->klass()) return -1;
      __ load_klass(rscratch2, dst, rscratch1);
      __ eor(rscratch2, rscratch2, scratch_src_klass);
      __ cbnz(rscratch2, L_failed);
  
+     // Check for flat inline type array -> return -1
+     __ test_flat_array_oop(src, rscratch2, L_failed);
+ 
+     // Check for null-free (non-flat) inline type array -> handle as object array
+     __ test_null_free_array_oop(src, rscratch2, L_objArray);
+ 
      //  if (!src->is_Array()) return -1;
      __ tbz(lh, 31, L_failed);  // i.e. (lh >= 0)
  
      // At this point, it is known to be a typeArray (array_tag 0x3).
  #ifdef ASSERT

@@ -12396,10 +12418,34 @@
  
      store_archive_data(stub_id, start, end, &entries);
    }
  #endif // LINUX
  
+   static void save_return_registers(MacroAssembler* masm) {
+     if (InlineTypeReturnedAsFields) {
+       masm->push(RegSet::range(r0, r7), sp);
+       masm->sub(sp, sp, 4 * wordSize);
+       masm->st1(v0, v1, v2, v3, masm->T1D, Address(sp));
+       masm->sub(sp, sp, 4 * wordSize);
+       masm->st1(v4, v5, v6, v7, masm->T1D, Address(sp));
+     } else {
+       masm->fmovd(rscratch1, v0);
+       masm->stp(rscratch1, r0, Address(masm->pre(sp, -2 * wordSize)));
+     }
+   }
+ 
+   static void restore_return_registers(MacroAssembler* masm) {
+     if (InlineTypeReturnedAsFields) {
+       masm->ld1(v4, v5, v6, v7, masm->T1D, Address(masm->post(sp, 4 * wordSize)));
+       masm->ld1(v0, v1, v2, v3, masm->T1D, Address(masm->post(sp, 4 * wordSize)));
+       masm->pop(RegSet::range(r0, r7), sp);
+     } else {
+       masm->ldp(rscratch1, r0, Address(masm->post(sp, 2 * wordSize)));
+       masm->fmovd(v0, rscratch1);
+     }
+   }
+ 
    address generate_cont_thaw(Continuation::thaw_kind kind) {
      bool return_barrier = Continuation::is_thaw_return_barrier(kind);
      bool return_barrier_exception = Continuation::is_thaw_return_barrier_exception(kind);
  
      address start = __ pc();

@@ -12410,22 +12456,20 @@
      }
      assert_asm(_masm, (__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset())), __ cmp(sp, rscratch1)), Assembler::EQ, "incorrect sp");
  
      if (return_barrier) {
        // preserve possible return value from a method returning to the return barrier
-       __ fmovd(rscratch1, v0);
-       __ stp(rscratch1, r0, Address(__ pre(sp, -2 * wordSize)));
+       save_return_registers(_masm);
      }
  
      __ movw(c_rarg1, (return_barrier ? 1 : 0));
      __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::prepare_thaw), rthread, c_rarg1);
      __ mov(rscratch2, r0); // r0 contains the size of the frames to thaw, 0 if overflow or no more frames
  
      if (return_barrier) {
        // restore return value (no safepoint in the call to thaw, so even an oop return value should be OK)
-       __ ldp(rscratch1, r0, Address(__ post(sp, 2 * wordSize)));
-       __ fmovd(v0, rscratch1);
+       restore_return_registers(_masm);
      }
      assert_asm(_masm, (__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset())), __ cmp(sp, rscratch1)), Assembler::EQ, "incorrect sp");
  
  
      Label thaw_success;

@@ -12440,24 +12484,22 @@
      __ andr(rscratch1, rscratch1, -16); // align
      __ mov(sp, rscratch1);
  
      if (return_barrier) {
        // save original return value -- again
-       __ fmovd(rscratch1, v0);
-       __ stp(rscratch1, r0, Address(__ pre(sp, -2 * wordSize)));
+       save_return_registers(_masm);
      }
  
      // If we want, we can templatize thaw by kind, and have three different entries
      __ movw(c_rarg1, (uint32_t)kind);
  
      __ call_VM_leaf(Continuation::thaw_entry(), rthread, c_rarg1);
      __ mov(rscratch2, r0); // r0 is the sp of the yielding frame
  
      if (return_barrier) {
        // restore return value (no safepoint in the call to thaw, so even an oop return value should be OK)
-       __ ldp(rscratch1, r0, Address(__ post(sp, 2 * wordSize)));
-       __ fmovd(v0, rscratch1);
+       restore_return_registers(_masm);
      } else {
        __ mov(r0, zr); // return 0 (success) from doYield
      }
  
      // we're now on the yield frame (which is in an address above us b/c rsp has been pushed down)
< prev index next >