< prev index next >

src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp

Print this page

        

@@ -318,18 +318,20 @@
     // 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_VALUETYPE, 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);
     __ br(Assembler::EQ, is_long);
+    __ cmp(j_rarg1, (u1)T_VALUETYPE);
+    __ br(Assembler::EQ, is_long);
     __ cmp(j_rarg1, (u1)T_LONG);
     __ br(Assembler::EQ, is_long);
     __ cmp(j_rarg1, (u1)T_FLOAT);
     __ br(Assembler::EQ, is_float);
     __ cmp(j_rarg1, (u1)T_DOUBLE);

@@ -1827,11 +1829,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);

@@ -5648,10 +5650,188 @@
     //     t0 = sub(Pm_base, Pn_base, t0, len);
     // }
   };
 
 
+  // Call here from the interpreter or compiled code to either load
+  // multiple returned values from the value type instance being
+  // returned to registers or to store returned values to a newly
+  // allocated value type instance.
+  address generate_return_value_stub(address destination, const char* name, bool has_res) {
+
+    // Information about frame layout at time of blocking runtime call.
+    // Note that we only have to preserve callee-saved registers since
+    // the compilers are responsible for supplying a continuation point
+    // if they expect all registers to be preserved.
+    // n.b. aarch64 asserts that frame::arg_reg_save_area_bytes == 0
+    enum layout {
+      rfp_off = 0, rfp_off2,
+
+      j_rarg7_off, j_rarg7_2,
+      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_farg0_off, j_farg0_2,
+      j_farg1_off, j_farg1_2,
+      j_farg2_off, j_farg2_2,
+      j_farg3_off, j_farg3_2,
+      j_farg4_off, j_farg4_2,
+      j_farg5_off, j_farg5_2,
+      j_farg6_off, j_farg6_2,
+      j_farg7_off, j_farg7_2,
+ 
+      return_off, return_off2,
+      framesize // inclusive of return address
+    };
+
+    int insts_size = 512;
+    int locs_size  = 64;
+
+    CodeBuffer code(name, insts_size, locs_size);
+    OopMapSet* oop_maps  = new OopMapSet();
+    MacroAssembler* masm = new MacroAssembler(&code);
+
+    address start = __ pc();
+
+    const Address f7_save       (rfp, j_farg7_off * wordSize);
+    const Address f6_save       (rfp, j_farg6_off * wordSize);
+    const Address f5_save       (rfp, j_farg5_off * wordSize);
+    const Address f4_save       (rfp, j_farg4_off * wordSize);
+    const Address f3_save       (rfp, j_farg3_off * wordSize);
+    const Address f2_save       (rfp, j_farg2_off * wordSize);
+    const Address f1_save       (rfp, j_farg1_off * wordSize);
+    const Address f0_save       (rfp, j_farg0_off * wordSize);
+
+    const Address r0_save      (rfp, j_rarg0_off * wordSize);
+    const Address r1_save      (rfp, j_rarg1_off * wordSize);
+    const Address r2_save      (rfp, j_rarg2_off * wordSize);
+    const Address r3_save      (rfp, j_rarg3_off * wordSize);
+    const Address r4_save      (rfp, j_rarg4_off * wordSize);
+    const Address r5_save      (rfp, j_rarg5_off * wordSize);
+    const Address r6_save      (rfp, j_rarg6_off * wordSize);
+    const Address r7_save      (rfp, j_rarg7_off * wordSize);
+
+    // Generate oop map
+    OopMap* map = new OopMap(framesize, 0);
+
+    map->set_callee_saved(VMRegImpl::stack2reg(rfp_off), rfp->as_VMReg());
+    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());
+
+    // This is an inlined and slightly modified version of call_VM
+    // which has the ability to fetch the return PC out of
+    // thread-local storage and also sets up last_Java_sp slightly
+    // differently than the real call_VM
+
+    __ enter(); // Save FP and LR before call
+
+    assert(is_even(framesize/2), "sp not 16-byte aligned");
+
+    // lr and fp are already in place
+    __ sub(sp, rfp, ((unsigned)framesize - 4) << LogBytesPerInt); // prolog
+
+    __ strd(j_farg7, f7_save); 
+    __ strd(j_farg6, f6_save); 
+    __ strd(j_farg5, f5_save); 
+    __ strd(j_farg4, f4_save); 
+    __ strd(j_farg3, f3_save); 
+    __ strd(j_farg2, f2_save); 
+    __ strd(j_farg1, f1_save); 
+    __ strd(j_farg0, f0_save); 
+
+    __ str(j_rarg0, r0_save); 
+    __ str(j_rarg1, r1_save); 
+    __ str(j_rarg2, r2_save); 
+    __ str(j_rarg3, r3_save); 
+    __ str(j_rarg4, r4_save); 
+    __ str(j_rarg5, r5_save); 
+    __ str(j_rarg6, r6_save); 
+    __ str(j_rarg7, r7_save); 
+
+    int frame_complete = __ pc() - start;
+
+    // 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_rarg0, rthread);
+    __ mov(c_rarg1, r0);
+
+    BLOCK_COMMENT("call runtime_entry");
+    __ mov(rscratch1, destination);
+    __ blrt(rscratch1, 2 /* number_of_arguments */, 0, 1);
+
+    oop_maps->add_gc_map(the_pc - start, map);
+
+    __ reset_last_Java_frame(false); 
+    __ maybe_isb(); 
+
+    __ ldrd(j_farg7, f7_save); 
+    __ ldrd(j_farg6, f6_save); 
+    __ ldrd(j_farg5, f5_save); 
+    __ ldrd(j_farg4, f4_save); 
+    __ ldrd(j_farg3, f3_save); 
+    __ ldrd(j_farg3, f2_save); 
+    __ ldrd(j_farg1, f1_save); 
+    __ ldrd(j_farg0, f0_save); 
+
+    __ ldr(j_rarg0, r0_save); 
+    __ ldr(j_rarg1, r1_save); 
+    __ ldr(j_rarg2, r2_save); 
+    __ ldr(j_rarg3, r3_save); 
+    __ ldr(j_rarg4, r4_save); 
+    __ ldr(j_rarg5, r5_save); 
+    __ ldr(j_rarg6, r6_save); 
+    __ ldr(j_rarg7, r7_save); 
+
+    __ leave();
+
+    // check for pending exceptions
+    Label pending;
+    __ ldr(rscratch1, Address(rthread, in_bytes(Thread::pending_exception_offset())));
+    __ cmp(rscratch1, (u1)NULL_WORD);
+    __ br(Assembler::NE, pending);
+
+    if (has_res) {
+      __ get_vm_result(r0, rthread);
+    }
+    __ ret(lr);
+
+    __ bind(pending);
+    __ ldr(r0, Address(rthread, in_bytes(Thread::pending_exception_offset())));
+    __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
+
+
+    // codeBlob framesize is in words (not VMRegImpl::slot_size)
+    int frame_size_in_words = (framesize >> (LogBytesPerWord - LogBytesPerInt));
+    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

@@ -5697,10 +5877,16 @@
     }
 
     if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dcos)) {
       StubRoutines::_dcos = generate_dsin_dcos(/* isCos = */ true);
     }
+
+
+    StubRoutines::_load_value_type_fields_in_regs = 
+         generate_return_value_stub(CAST_FROM_FN_PTR(address, SharedRuntime::load_value_type_fields_in_regs), "load_value_type_fields_in_regs", false);
+    StubRoutines::_store_value_type_fields_to_buf = 
+         generate_return_value_stub(CAST_FROM_FN_PTR(address, SharedRuntime::store_value_type_fields_to_buf), "store_value_type_fields_to_buf", true);
   }
 
   void generate_all() {
     // support for verify_oop (must happen after universe_init)
     StubRoutines::_verify_oop_subroutine_entry     = generate_verify_oop();
< prev index next >