< prev index next >

src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp

Print this page
@@ -307,27 +307,34 @@
      // save current address for use by exception handling code
  
      return_address = __ pc();
  
      // store result depending on type (everything that is not
-     // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
+     // T_OBJECT, T_INLINE_TYPE, 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, is_value, exit;
+     __ ldr(Rresult_type, result_type);
+     __ cmp(Rresult_type, (u1)T_OBJECT);
      __ br(Assembler::EQ, is_long);
-     __ cmp(j_rarg1, (u1)T_LONG);
+     __ cmp(Rresult_type, (u1)T_INLINE_TYPE);
+     __ br(Assembler::EQ, is_value);
+     __ cmp(Rresult_type, (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);

@@ -369,21 +376,32 @@
      // leave frame and return to caller
      __ leave();
      __ ret(lr);
  
      // handle return types different from T_INT
+     __ BIND(is_value);
+     if (InlineTypeReturnedAsFields) {
+       // Check for flattened return value
+       __ tbz(r0, 0, is_long);
+       // Load pack handler address
+       __ andr(rscratch1, r0, -2);
+       __ ldr(rscratch1, Address(rscratch1, InstanceKlass::adr_inlineklass_fixed_block_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);
  
      return start;
    }
  

@@ -1841,11 +1859,11 @@
      //     store_heap_oop(to++, copied_oop);
      //   }
      __ align(OptoLoopAlignment);
  
      __ BIND(L_store_element);
-     __ store_heap_oop(__ post(to, UseCompressedOops ? 4 : 8), copied_oop, noreg, noreg, AS_RAW);  // store the oop
+     __ store_heap_oop(__ post(to, UseCompressedOops ? 4 : 8), copied_oop, noreg, noreg, noreg, AS_RAW);  // store the oop
      __ sub(count, count, 1);
      __ cbz(count, L_do_card_marks);
  
      // ======== loop entry is here ========
      __ BIND(L_load_element);

@@ -2088,10 +2106,18 @@
      //  if (src->klass() != dst->klass()) return -1;
      __ load_klass(rscratch2, dst);
      __ eor(rscratch2, rscratch2, scratch_src_klass);
      __ cbnz(rscratch2, L_failed);
  
+     // Check for flat inline type array -> return -1
+     __ tst(lh, Klass::_lh_array_tag_vt_value_bit_inplace);
+     __ br(Assembler::NE, L_failed);
+ 
+     // Check for null-free (non-flat) inline type array -> handle as object array
+     __ tst(lh, Klass::_lh_null_free_bit_inplace);
+     __ br(Assembler::NE, L_failed);
+ 
      //  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

@@ -7222,10 +7248,138 @@
      //     t0 = sub(Pm_base, Pn_base, t0, len);
      // }
    };
  
  
+   // Call here from the interpreter or compiled code to either load
+   // multiple returned values from the inline type instance being
+   // returned to registers or to store returned values to a newly
+   // allocated inline type instance.
+   address generate_return_value_stub(address destination, const char* name, bool has_res) {
+     // We need to save all registers the calling convention may use so
+     // the runtime calls read or update those registers. This needs to
+     // be in sync with SharedRuntime::java_return_convention().
+     // n.b. aarch64 asserts that frame::arg_reg_save_area_bytes == 0
+     enum layout {
+       j_rarg7_off = 0, j_rarg7_2,    // j_rarg7 is r0
+       j_rarg6_off, j_rarg6_2,
+       j_rarg5_off, j_rarg5_2,
+       j_rarg4_off, j_rarg4_2,
+       j_rarg3_off, j_rarg3_2,
+       j_rarg2_off, j_rarg2_2,
+       j_rarg1_off, j_rarg1_2,
+       j_rarg0_off, j_rarg0_2,
+ 
+       j_farg7_off, j_farg7_2,
+       j_farg6_off, j_farg6_2,
+       j_farg5_off, j_farg5_2,
+       j_farg4_off, j_farg4_2,
+       j_farg3_off, j_farg3_2,
+       j_farg2_off, j_farg2_2,
+       j_farg1_off, j_farg1_2,
+       j_farg0_off, j_farg0_2,
+ 
+       rfp_off, rfp_off2,
+       return_off, return_off2,
+ 
+       framesize // inclusive of return address
+     };
+ 
+     CodeBuffer code(name, 512, 64);
+     MacroAssembler* masm = new MacroAssembler(&code);
+ 
+     int frame_size_in_bytes = align_up(framesize*BytesPerInt, 16);
+     assert(frame_size_in_bytes == framesize*BytesPerInt, "misaligned");
+     int frame_size_in_slots = frame_size_in_bytes / BytesPerInt;
+     int frame_size_in_words = frame_size_in_bytes / wordSize;
+ 
+     OopMapSet* oop_maps = new OopMapSet();
+     OopMap* map = new OopMap(frame_size_in_slots, 0);
+ 
+     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg7_off), j_rarg7->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg6_off), j_rarg6->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg5_off), j_rarg5->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg4_off), j_rarg4->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg3_off), j_rarg3->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg2_off), j_rarg2->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg1_off), j_rarg1->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_rarg0_off), j_rarg0->as_VMReg());
+ 
+     map->set_callee_saved(VMRegImpl::stack2reg(j_farg0_off), j_farg0->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_farg1_off), j_farg1->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_farg2_off), j_farg2->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_farg3_off), j_farg3->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_farg4_off), j_farg4->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_farg5_off), j_farg5->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_farg6_off), j_farg6->as_VMReg());
+     map->set_callee_saved(VMRegImpl::stack2reg(j_farg7_off), j_farg7->as_VMReg());
+ 
+     address start = __ pc();
+ 
+     __ enter(); // Save FP and LR before call
+ 
+     __ stpd(j_farg1, j_farg0, Address(__ pre(sp, -2 * wordSize)));
+     __ stpd(j_farg3, j_farg2, Address(__ pre(sp, -2 * wordSize)));
+     __ stpd(j_farg5, j_farg4, Address(__ pre(sp, -2 * wordSize)));
+     __ stpd(j_farg7, j_farg6, Address(__ pre(sp, -2 * wordSize)));
+ 
+     __ stp(j_rarg1, j_rarg0, Address(__ pre(sp, -2 * wordSize)));
+     __ stp(j_rarg3, j_rarg2, Address(__ pre(sp, -2 * wordSize)));
+     __ stp(j_rarg5, j_rarg4, Address(__ pre(sp, -2 * wordSize)));
+     __ stp(j_rarg7, j_rarg6, Address(__ pre(sp, -2 * wordSize)));
+ 
+     int frame_complete = __ offset();
+ 
+     // Set up last_Java_sp and last_Java_fp
+     address the_pc = __ pc();
+     __ set_last_Java_frame(sp, rfp, the_pc, rscratch1);
+ 
+     // Call runtime
+     __ mov(c_rarg1, r0);
+     __ mov(c_rarg0, rthread);
+ 
+     __ mov(rscratch1, destination);
+     __ blr(rscratch1);
+ 
+     oop_maps->add_gc_map(the_pc - start, map);
+ 
+     __ reset_last_Java_frame(false);
+ 
+     __ ldp(j_rarg7, j_rarg6, Address(__ post(sp, 2 * wordSize)));
+     __ ldp(j_rarg5, j_rarg4, Address(__ post(sp, 2 * wordSize)));
+     __ ldp(j_rarg3, j_rarg2, Address(__ post(sp, 2 * wordSize)));
+     __ ldp(j_rarg1, j_rarg0, Address(__ post(sp, 2 * wordSize)));
+ 
+     __ ldpd(j_farg7, j_farg6, Address(__ post(sp, 2 * wordSize)));
+     __ ldpd(j_farg5, j_farg4, Address(__ post(sp, 2 * wordSize)));
+     __ ldpd(j_farg3, j_farg2, Address(__ post(sp, 2 * wordSize)));
+     __ ldpd(j_farg1, j_farg0, Address(__ post(sp, 2 * wordSize)));
+ 
+     __ leave();
+ 
+     // check for pending exceptions
+     Label pending;
+     __ ldr(rscratch1, Address(rthread, in_bytes(Thread::pending_exception_offset())));
+     __ cbnz(rscratch1, pending);
+ 
+     if (has_res) {
+       __ get_vm_result(r0, rthread);
+     }
+ 
+     __ ret(lr);
+ 
+     __ bind(pending);
+     __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
+ 
+     // -------------
+     // make sure all code is generated
+     masm->flush();
+ 
+     RuntimeStub* stub = RuntimeStub::new_runtime_stub(name, &code, frame_complete, frame_size_in_words, oop_maps, false);
+     return stub->entry_point();
+   }
+ 
    // Initialization
    void generate_initial() {
      // Generate initial stubs and initializes the entry points
  
      // entry points that exist in all platforms Note: This is code

@@ -7272,10 +7426,17 @@
  
      if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dcos)) {
        StubRoutines::_dcos = generate_dsin_dcos(/* isCos = */ true);
      }
  
+     if (InlineTypeReturnedAsFields) {
+       StubRoutines::_load_inline_type_fields_in_regs =
+          generate_return_value_stub(CAST_FROM_FN_PTR(address, SharedRuntime::load_inline_type_fields_in_regs), "load_inline_type_fields_in_regs", false);
+       StubRoutines::_store_inline_type_fields_to_buf =
+          generate_return_value_stub(CAST_FROM_FN_PTR(address, SharedRuntime::store_inline_type_fields_to_buf), "store_inline_type_fields_to_buf", true);
+     }
+ 
      // Safefetch stubs.
      generate_safefetch("SafeFetch32", sizeof(int),     &StubRoutines::_safefetch32_entry,
                                                         &StubRoutines::_safefetch32_fault_pc,
                                                         &StubRoutines::_safefetch32_continuation_pc);
      generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
< prev index next >