< prev index next >

src/hotspot/cpu/x86/stubGenerator_x86_64.cpp

Print this page
*** 20,26 ***
--- 20,30 ---
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   *
   */
  
+ #include "asm/assembler.hpp"
  #include "asm/macroAssembler.hpp"
  #include "classfile/javaClasses.hpp"
  #include "classfile/vmIntrinsics.hpp"
  #include "compiler/oopMap.hpp"
  #include "gc/shared/barrierSet.hpp"
  #include "gc/shared/barrierSetAssembler.hpp"
  #include "gc/shared/barrierSetNMethod.hpp"
  #include "gc/shared/gc_globals.hpp"
  #include "memory/universe.hpp"
+ #include "oops/inlineKlass.hpp"
  #include "prims/jvmtiExport.hpp"
  #include "prims/upcallLinker.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/continuationEntry.hpp"
  #include "runtime/javaThread.hpp"
  #include "runtime/sharedRuntime.hpp"
  #include "runtime/stubRoutines.hpp"
+ #include "utilities/macros.hpp"
+ #include "vmreg_x86.inline.hpp"
  #include "stubGenerator_x86_64.hpp"
  #ifdef COMPILER2
  #include "opto/runtime.hpp"
  #include "opto/c2_globals.hpp"
  #endif

*** 305,36 ***
  
    BLOCK_COMMENT("call_stub_return_address:");
    return_address = __ pc();
    entries.append(return_address);
  
    // store result depending on type (everything that is not
    // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
!   __ movptr(c_rarg0, result);
!   Label is_long, is_float, is_double, exit;
!   __ movl(c_rarg1, result_type);
!   __ cmpl(c_rarg1, T_OBJECT);
!   __ jcc(Assembler::equal, is_long);
!   __ cmpl(c_rarg1, T_LONG);
    __ jcc(Assembler::equal, is_long);
!   __ cmpl(c_rarg1, T_FLOAT);
    __ jcc(Assembler::equal, is_float);
!   __ cmpl(c_rarg1, T_DOUBLE);
    __ jcc(Assembler::equal, is_double);
  #ifdef ASSERT
    // make sure the type is INT
    {
      Label L;
!     __ cmpl(c_rarg1, T_INT);
      __ jcc(Assembler::equal, L);
      __ stop("StubRoutines::call_stub: unexpected result type");
      __ bind(L);
    }
  #endif
  
    // handle T_INT case
!   __ movl(Address(c_rarg0, 0), rax);
  
    __ BIND(exit);
  
    // pop parameters
    __ lea(rsp, rsp_after_call);
--- 309,39 ---
  
    BLOCK_COMMENT("call_stub_return_address:");
    return_address = __ pc();
    entries.append(return_address);
  
+   // All of j_rargN + rax may be used to return inline type fields so be careful
+   // not to clobber those.  See SharedRuntime::java_return_convention().
+ 
    // store result depending on type (everything that is not
    // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
!   __ movptr(r13, result);
!   Label is_long, is_float, is_double, check_prim, exit;
!   __ movl(rbx, result_type);
!   __ cmpl(rbx, T_OBJECT);
!   __ jcc(Assembler::equal, check_prim);
!   __ cmpl(rbx, T_LONG);
    __ jcc(Assembler::equal, is_long);
!   __ cmpl(rbx, T_FLOAT);
    __ jcc(Assembler::equal, is_float);
!   __ cmpl(rbx, T_DOUBLE);
    __ jcc(Assembler::equal, is_double);
  #ifdef ASSERT
    // make sure the type is INT
    {
      Label L;
!     __ cmpl(rbx, T_INT);
      __ jcc(Assembler::equal, L);
      __ stop("StubRoutines::call_stub: unexpected result type");
      __ bind(L);
    }
  #endif
  
    // handle T_INT case
!   __ movl(Address(r13, 0), rax);
  
    __ BIND(exit);
  
    // pop parameters
    __ lea(rsp, rsp_after_call);

*** 388,20 ***
    __ vzeroupper();
    __ pop(rbp);
    __ ret(0);
  
    // handle return types different from T_INT
    __ BIND(is_long);
!   __ movq(Address(c_rarg0, 0), rax);
    __ jmp(exit);
  
    __ BIND(is_float);
!   __ movflt(Address(c_rarg0, 0), xmm0);
    __ jmp(exit);
  
    __ BIND(is_double);
!   __ movdbl(Address(c_rarg0, 0), xmm0);
    __ jmp(exit);
  
    // record the stub entry and end plus the auxiliary entry
    store_archive_data(stub_id, start, __ pc(), &entries);
  
--- 395,33 ---
    __ vzeroupper();
    __ pop(rbp);
    __ ret(0);
  
    // handle return types different from T_INT
+   __ BIND(check_prim);
+   if (InlineTypeReturnedAsFields) {
+     // Check for scalarized return value
+     __ testptr(rax, 1);
+     __ jcc(Assembler::zero, is_long);
+     // Load pack handler address
+     __ andptr(rax, -2);
+     __ movptr(rax, Address(rax, InlineKlass::adr_members_offset()));
+     __ movptr(rbx, Address(rax, InlineKlass::pack_handler_jobject_offset()));
+     // Call pack handler to initialize the buffer
+     __ call(rbx);
+     __ jmp(exit);
+   }
    __ BIND(is_long);
!   __ movq(Address(r13, 0), rax);
    __ jmp(exit);
  
    __ BIND(is_float);
!   __ movflt(Address(r13, 0), xmm0);
    __ jmp(exit);
  
    __ BIND(is_double);
!   __ movdbl(Address(r13, 0), xmm0);
    __ jmp(exit);
  
    // record the stub entry and end plus the auxiliary entry
    store_archive_data(stub_id, start, __ pc(), &entries);
  

*** 4368,10 ***
--- 4388,71 ---
    store_archive_data(stub_id, start, __ pc());
  
    return start;
  }
  
+ static void save_return_registers(MacroAssembler* masm) {
+   masm->push_ppx(rax);
+   if (InlineTypeReturnedAsFields) {
+     masm->push(rdi);
+     masm->push(rsi);
+     masm->push(rdx);
+     masm->push(rcx);
+     masm->push(r8);
+     masm->push(r9);
+   }
+   masm->push_d(xmm0);
+   if (InlineTypeReturnedAsFields) {
+     masm->push_d(xmm1);
+     masm->push_d(xmm2);
+     masm->push_d(xmm3);
+     masm->push_d(xmm4);
+     masm->push_d(xmm5);
+     masm->push_d(xmm6);
+     masm->push_d(xmm7);
+   }
+ #ifdef ASSERT
+   masm->movq(rax, 0xBADC0FFE);
+   masm->movq(rdi, rax);
+   masm->movq(rsi, rax);
+   masm->movq(rdx, rax);
+   masm->movq(rcx, rax);
+   masm->movq(r8, rax);
+   masm->movq(r9, rax);
+   masm->movq(xmm0, rax);
+   masm->movq(xmm1, rax);
+   masm->movq(xmm2, rax);
+   masm->movq(xmm3, rax);
+   masm->movq(xmm4, rax);
+   masm->movq(xmm5, rax);
+   masm->movq(xmm6, rax);
+   masm->movq(xmm7, rax);
+ #endif
+ }
+ 
+ static void restore_return_registers(MacroAssembler* masm) {
+   if (InlineTypeReturnedAsFields) {
+     masm->pop_d(xmm7);
+     masm->pop_d(xmm6);
+     masm->pop_d(xmm5);
+     masm->pop_d(xmm4);
+     masm->pop_d(xmm3);
+     masm->pop_d(xmm2);
+     masm->pop_d(xmm1);
+   }
+   masm->pop_d(xmm0);
+   if (InlineTypeReturnedAsFields) {
+     masm->pop(r9);
+     masm->pop(r8);
+     masm->pop(rcx);
+     masm->pop(rdx);
+     masm->pop(rsi);
+     masm->pop(rdi);
+   }
+   masm->pop_ppx(rax);
+ }
+ 
  address StubGenerator::generate_cont_thaw(StubId stub_id) {
    if (!Continuations::enabled()) return nullptr;
  
    bool return_barrier;
    bool return_barrier_exception;

*** 4425,24 ***
    }
  #endif // ASSERT
  
    if (return_barrier) {
      // Preserve possible return value from a method returning to the return barrier.
!     __ push_ppx(rax);
-     __ push_d(xmm0);
    }
  
    __ movptr(c_rarg0, r15_thread);
    __ movptr(c_rarg1, (return_barrier ? 1 : 0));
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::prepare_thaw), 2);
    __ movptr(rbx, rax);
  
    if (return_barrier) {
      // Restore return value from a method returning to the return barrier.
      // No safepoint in the call to thaw, so even an oop return value should be OK.
!     __ pop_d(xmm0);
-     __ pop_ppx(rax);
    }
  
  #ifdef ASSERT
    {
      Label L_good_sp;
--- 4506,22 ---
    }
  #endif // ASSERT
  
    if (return_barrier) {
      // Preserve possible return value from a method returning to the return barrier.
!     save_return_registers(_masm);
    }
  
    __ movptr(c_rarg0, r15_thread);
    __ movptr(c_rarg1, (return_barrier ? 1 : 0));
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::prepare_thaw), 2);
    __ movptr(rbx, rax);
  
    if (return_barrier) {
      // Restore return value from a method returning to the return barrier.
      // No safepoint in the call to thaw, so even an oop return value should be OK.
!     restore_return_registers(_masm);
    }
  
  #ifdef ASSERT
    {
      Label L_good_sp;

*** 4464,12 ***
    __ subptr(rsp, rbx);
    __ andptr(rsp, -StackAlignmentInBytes);
  
    if (return_barrier) {
      // Preserve possible return value from a method returning to the return barrier. (Again.)
!     __ push_ppx(rax);
-     __ push_d(xmm0);
    }
  
    // If we want, we can templatize thaw by kind, and have three different entries.
    __ movptr(c_rarg0, r15_thread);
    __ movptr(c_rarg1, kind);
--- 4543,11 ---
    __ subptr(rsp, rbx);
    __ andptr(rsp, -StackAlignmentInBytes);
  
    if (return_barrier) {
      // Preserve possible return value from a method returning to the return barrier. (Again.)
!     save_return_registers(_masm);
    }
  
    // If we want, we can templatize thaw by kind, and have three different entries.
    __ movptr(c_rarg0, r15_thread);
    __ movptr(c_rarg1, kind);

*** 4477,12 ***
    __ movptr(rbx, rax);
  
    if (return_barrier) {
      // Restore return value from a method returning to the return barrier. (Again.)
      // No safepoint in the call to thaw, so even an oop return value should be OK.
!     __ pop_d(xmm0);
-     __ pop_ppx(rax);
    } else {
      // Return 0 (success) from doYield.
      __ xorptr(rax, rax);
    }
  
--- 4555,11 ---
    __ movptr(rbx, rax);
  
    if (return_barrier) {
      // Restore return value from a method returning to the return barrier. (Again.)
      // No safepoint in the call to thaw, so even an oop return value should be OK.
!     restore_return_registers(_masm);
    } else {
      // Return 0 (success) from doYield.
      __ xorptr(rax, rax);
    }
  
< prev index next >