< prev index next >

src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp

Print this page

   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  *
   24  */
   25 
   26 #include "asm/macroAssembler.hpp"
   27 #include "asm/macroAssembler.inline.hpp"
   28 #include "asm/register.hpp"
   29 #include "atomic_aarch64.hpp"

   30 #include "compiler/oopMap.hpp"
   31 #include "gc/shared/barrierSet.hpp"
   32 #include "gc/shared/barrierSetAssembler.hpp"
   33 #include "gc/shared/gc_globals.hpp"
   34 #include "gc/shared/tlab_globals.hpp"
   35 #include "interpreter/interpreter.hpp"
   36 #include "memory/universe.hpp"
   37 #include "nativeInst_aarch64.hpp"
   38 #include "oops/instanceOop.hpp"
   39 #include "oops/method.hpp"
   40 #include "oops/objArrayKlass.hpp"
   41 #include "oops/oop.inline.hpp"
   42 #include "prims/methodHandles.hpp"
   43 #include "prims/upcallLinker.hpp"
   44 #include "runtime/arguments.hpp"
   45 #include "runtime/atomic.hpp"
   46 #include "runtime/continuation.hpp"
   47 #include "runtime/continuationEntry.inline.hpp"
   48 #include "runtime/frame.inline.hpp"
   49 #include "runtime/handles.inline.hpp"

 7386     __ add(s1, s1, temp0);
 7387     __ add(s2, s2, temp1);
 7388   }
 7389 
 7390   /**
 7391    *  Arguments:
 7392    *
 7393    *  Input:
 7394    *    c_rarg0   - x address
 7395    *    c_rarg1   - x length
 7396    *    c_rarg2   - y address
 7397    *    c_rarg3   - y length
 7398    *    c_rarg4   - z address
 7399    */
 7400   address generate_multiplyToLen() {
 7401     __ align(CodeEntryAlignment);
 7402     StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
 7403     StubCodeMark mark(this, stub_id);
 7404 
 7405     address start = __ pc();




 7406     const Register x     = r0;
 7407     const Register xlen  = r1;
 7408     const Register y     = r2;
 7409     const Register ylen  = r3;
 7410     const Register z     = r4;
 7411 
 7412     const Register tmp0  = r5;
 7413     const Register tmp1  = r10;
 7414     const Register tmp2  = r11;
 7415     const Register tmp3  = r12;
 7416     const Register tmp4  = r13;
 7417     const Register tmp5  = r14;
 7418     const Register tmp6  = r15;
 7419     const Register tmp7  = r16;
 7420 
 7421     BLOCK_COMMENT("Entry:");
 7422     __ enter(); // required for proper stackwalking of RuntimeStub frame
 7423     __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
 7424     __ leave(); // required for proper stackwalking of RuntimeStub frame
 7425     __ ret(lr);
 7426 

 7427     return start;
 7428   }
 7429 
 7430   address generate_squareToLen() {
 7431     // squareToLen algorithm for sizes 1..127 described in java code works
 7432     // faster than multiply_to_len on some CPUs and slower on others, but
 7433     // multiply_to_len shows a bit better overall results
 7434     __ align(CodeEntryAlignment);
 7435     StubGenStubId stub_id = StubGenStubId::squareToLen_id;
 7436     StubCodeMark mark(this, stub_id);
 7437     address start = __ pc();
 7438 



 7439     const Register x     = r0;
 7440     const Register xlen  = r1;
 7441     const Register z     = r2;
 7442     const Register y     = r4; // == x
 7443     const Register ylen  = r5; // == xlen
 7444 
 7445     const Register tmp0  = r3;
 7446     const Register tmp1  = r10;
 7447     const Register tmp2  = r11;
 7448     const Register tmp3  = r12;
 7449     const Register tmp4  = r13;
 7450     const Register tmp5  = r14;
 7451     const Register tmp6  = r15;
 7452     const Register tmp7  = r16;
 7453 
 7454     RegSet spilled_regs = RegSet::of(y, ylen);
 7455     BLOCK_COMMENT("Entry:");
 7456     __ enter();
 7457     __ push(spilled_regs, sp);
 7458     __ mov(y, x);
 7459     __ mov(ylen, xlen);
 7460     __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
 7461     __ pop(spilled_regs, sp);
 7462     __ leave();
 7463     __ ret(lr);


 7464     return start;
 7465   }
 7466 
 7467   address generate_mulAdd() {
 7468     __ align(CodeEntryAlignment);
 7469     StubGenStubId stub_id = StubGenStubId::mulAdd_id;
 7470     StubCodeMark mark(this, stub_id);
 7471 
 7472     address start = __ pc();
 7473 



 7474     const Register out     = r0;
 7475     const Register in      = r1;
 7476     const Register offset  = r2;
 7477     const Register len     = r3;
 7478     const Register k       = r4;
 7479 
 7480     BLOCK_COMMENT("Entry:");
 7481     __ enter();
 7482     __ mul_add(out, in, offset, len, k);
 7483     __ leave();
 7484     __ ret(lr);
 7485 

 7486     return start;
 7487   }
 7488 
 7489   // Arguments:
 7490   //
 7491   // Input:
 7492   //   c_rarg0   - newArr address
 7493   //   c_rarg1   - oldArr address
 7494   //   c_rarg2   - newIdx
 7495   //   c_rarg3   - shiftCount
 7496   //   c_rarg4   - numIter
 7497   //
 7498   address generate_bigIntegerRightShift() {
 7499     __ align(CodeEntryAlignment);
 7500     StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
 7501     StubCodeMark mark(this, stub_id);
 7502     address start = __ pc();
 7503 
 7504     Label ShiftSIMDLoop, ShiftTwoLoop, ShiftThree, ShiftTwo, ShiftOne, Exit;
 7505 

11276     //       MACC(Ra, Ra, t0, t1, t2);
11277     //     }
11278     //     iters =  (2*len-i)/2;
11279     //     assert(iters == len-j, "must be");
11280     //     for (; iters--; j++) {
11281     //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
11282     //       MACC(Rm, Rn, t0, t1, t2);
11283     //       Rm = *++Pm;
11284     //       Rn = *--Pn;
11285     //     }
11286     //     Pm_base[i-len] = t0;
11287     //     t0 = t1; t1 = t2; t2 = 0;
11288     //   }
11289 
11290     //   while (t0)
11291     //     t0 = sub(Pm_base, Pn_base, t0, len);
11292     // }
11293   };
11294 
11295   // Initialization




11296   void generate_initial_stubs() {
11297     // Generate initial stubs and initializes the entry points
11298 
11299     // entry points that exist in all platforms Note: This is code
11300     // that could be shared among different platforms - however the
11301     // benefit seems to be smaller than the disadvantage of having a
11302     // much more complicated generator structure. See also comment in
11303     // stubRoutines.hpp.
11304 
11305     StubRoutines::_forward_exception_entry = generate_forward_exception();
11306 
11307     StubRoutines::_call_stub_entry =
11308       generate_call_stub(StubRoutines::_call_stub_return_address);
11309 
11310     // is referenced by megamorphic call
11311     StubRoutines::_catch_exception_entry = generate_catch_exception();
11312 
11313     // Initialize table for copy memory (arraycopy) check.
11314     if (UnsafeMemoryAccess::_table == nullptr) {
11315       UnsafeMemoryAccess::create_table(8 + 4); // 8 for copyMemory; 4 for setMemory

11515       StubRoutines::_sha3_implCompress     = generate_sha3_implCompress(StubGenStubId::sha3_implCompress_id);
11516       StubRoutines::_double_keccak         = generate_double_keccak();
11517       StubRoutines::_sha3_implCompressMB   = generate_sha3_implCompress(StubGenStubId::sha3_implCompressMB_id);
11518     }
11519 
11520     if (UsePoly1305Intrinsics) {
11521       StubRoutines::_poly1305_processBlocks = generate_poly1305_processBlocks();
11522     }
11523 
11524     // generate Adler32 intrinsics code
11525     if (UseAdler32Intrinsics) {
11526       StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32();
11527     }
11528 
11529 #endif // COMPILER2_OR_JVMCI
11530   }
11531 
11532  public:
11533   StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) {
11534     switch(blob_id) {



11535     case initial_id:
11536       generate_initial_stubs();
11537       break;
11538      case continuation_id:
11539       generate_continuation_stubs();
11540       break;
11541     case compiler_id:
11542       generate_compiler_stubs();
11543       break;
11544     case final_id:
11545       generate_final_stubs();
11546       break;
11547     default:
11548       fatal("unexpected blob id: %d", blob_id);
11549       break;
11550     };
11551   }
11552 }; // end class declaration
11553 
11554 void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) {

   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  *
   24  */
   25 
   26 #include "asm/macroAssembler.hpp"
   27 #include "asm/macroAssembler.inline.hpp"
   28 #include "asm/register.hpp"
   29 #include "atomic_aarch64.hpp"
   30 #include "code/aotCodeCache.hpp"
   31 #include "compiler/oopMap.hpp"
   32 #include "gc/shared/barrierSet.hpp"
   33 #include "gc/shared/barrierSetAssembler.hpp"
   34 #include "gc/shared/gc_globals.hpp"
   35 #include "gc/shared/tlab_globals.hpp"
   36 #include "interpreter/interpreter.hpp"
   37 #include "memory/universe.hpp"
   38 #include "nativeInst_aarch64.hpp"
   39 #include "oops/instanceOop.hpp"
   40 #include "oops/method.hpp"
   41 #include "oops/objArrayKlass.hpp"
   42 #include "oops/oop.inline.hpp"
   43 #include "prims/methodHandles.hpp"
   44 #include "prims/upcallLinker.hpp"
   45 #include "runtime/arguments.hpp"
   46 #include "runtime/atomic.hpp"
   47 #include "runtime/continuation.hpp"
   48 #include "runtime/continuationEntry.inline.hpp"
   49 #include "runtime/frame.inline.hpp"
   50 #include "runtime/handles.inline.hpp"

 7387     __ add(s1, s1, temp0);
 7388     __ add(s2, s2, temp1);
 7389   }
 7390 
 7391   /**
 7392    *  Arguments:
 7393    *
 7394    *  Input:
 7395    *    c_rarg0   - x address
 7396    *    c_rarg1   - x length
 7397    *    c_rarg2   - y address
 7398    *    c_rarg3   - y length
 7399    *    c_rarg4   - z address
 7400    */
 7401   address generate_multiplyToLen() {
 7402     __ align(CodeEntryAlignment);
 7403     StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
 7404     StubCodeMark mark(this, stub_id);
 7405 
 7406     address start = __ pc();
 7407  
 7408     if (AOTCodeCache::load_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start)) {
 7409       return start;
 7410     }
 7411     const Register x     = r0;
 7412     const Register xlen  = r1;
 7413     const Register y     = r2;
 7414     const Register ylen  = r3;
 7415     const Register z     = r4;
 7416 
 7417     const Register tmp0  = r5;
 7418     const Register tmp1  = r10;
 7419     const Register tmp2  = r11;
 7420     const Register tmp3  = r12;
 7421     const Register tmp4  = r13;
 7422     const Register tmp5  = r14;
 7423     const Register tmp6  = r15;
 7424     const Register tmp7  = r16;
 7425 
 7426     BLOCK_COMMENT("Entry:");
 7427     __ enter(); // required for proper stackwalking of RuntimeStub frame
 7428     __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
 7429     __ leave(); // required for proper stackwalking of RuntimeStub frame
 7430     __ ret(lr);
 7431 
 7432     AOTCodeCache::store_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start);
 7433     return start;
 7434   }
 7435 
 7436   address generate_squareToLen() {
 7437     // squareToLen algorithm for sizes 1..127 described in java code works
 7438     // faster than multiply_to_len on some CPUs and slower on others, but
 7439     // multiply_to_len shows a bit better overall results
 7440     __ align(CodeEntryAlignment);
 7441     StubGenStubId stub_id = StubGenStubId::squareToLen_id;
 7442     StubCodeMark mark(this, stub_id);
 7443     address start = __ pc();
 7444 
 7445     if (AOTCodeCache::load_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start)) {
 7446       return start;
 7447     }
 7448     const Register x     = r0;
 7449     const Register xlen  = r1;
 7450     const Register z     = r2;
 7451     const Register y     = r4; // == x
 7452     const Register ylen  = r5; // == xlen
 7453 
 7454     const Register tmp0  = r3;
 7455     const Register tmp1  = r10;
 7456     const Register tmp2  = r11;
 7457     const Register tmp3  = r12;
 7458     const Register tmp4  = r13;
 7459     const Register tmp5  = r14;
 7460     const Register tmp6  = r15;
 7461     const Register tmp7  = r16;
 7462 
 7463     RegSet spilled_regs = RegSet::of(y, ylen);
 7464     BLOCK_COMMENT("Entry:");
 7465     __ enter();
 7466     __ push(spilled_regs, sp);
 7467     __ mov(y, x);
 7468     __ mov(ylen, xlen);
 7469     __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
 7470     __ pop(spilled_regs, sp);
 7471     __ leave();
 7472     __ ret(lr);
 7473 
 7474     AOTCodeCache::store_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start);
 7475     return start;
 7476   }
 7477 
 7478   address generate_mulAdd() {
 7479     __ align(CodeEntryAlignment);
 7480     StubGenStubId stub_id = StubGenStubId::mulAdd_id;
 7481     StubCodeMark mark(this, stub_id);
 7482 
 7483     address start = __ pc();
 7484 
 7485     if (AOTCodeCache::load_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start)) {
 7486       return start;
 7487     }
 7488     const Register out     = r0;
 7489     const Register in      = r1;
 7490     const Register offset  = r2;
 7491     const Register len     = r3;
 7492     const Register k       = r4;
 7493 
 7494     BLOCK_COMMENT("Entry:");
 7495     __ enter();
 7496     __ mul_add(out, in, offset, len, k);
 7497     __ leave();
 7498     __ ret(lr);
 7499 
 7500     AOTCodeCache::store_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start);
 7501     return start;
 7502   }
 7503 
 7504   // Arguments:
 7505   //
 7506   // Input:
 7507   //   c_rarg0   - newArr address
 7508   //   c_rarg1   - oldArr address
 7509   //   c_rarg2   - newIdx
 7510   //   c_rarg3   - shiftCount
 7511   //   c_rarg4   - numIter
 7512   //
 7513   address generate_bigIntegerRightShift() {
 7514     __ align(CodeEntryAlignment);
 7515     StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
 7516     StubCodeMark mark(this, stub_id);
 7517     address start = __ pc();
 7518 
 7519     Label ShiftSIMDLoop, ShiftTwoLoop, ShiftThree, ShiftTwo, ShiftOne, Exit;
 7520 

11291     //       MACC(Ra, Ra, t0, t1, t2);
11292     //     }
11293     //     iters =  (2*len-i)/2;
11294     //     assert(iters == len-j, "must be");
11295     //     for (; iters--; j++) {
11296     //       assert(Rm == Pm_base[j] && Rn == Pn_base[i-j], "must be");
11297     //       MACC(Rm, Rn, t0, t1, t2);
11298     //       Rm = *++Pm;
11299     //       Rn = *--Pn;
11300     //     }
11301     //     Pm_base[i-len] = t0;
11302     //     t0 = t1; t1 = t2; t2 = 0;
11303     //   }
11304 
11305     //   while (t0)
11306     //     t0 = sub(Pm_base, Pn_base, t0, len);
11307     // }
11308   };
11309 
11310   // Initialization
11311   void generate_preuniverse_stubs() {
11312     // preuniverse stubs are not needed for aarch64
11313   }
11314 
11315   void generate_initial_stubs() {
11316     // Generate initial stubs and initializes the entry points
11317 
11318     // entry points that exist in all platforms Note: This is code
11319     // that could be shared among different platforms - however the
11320     // benefit seems to be smaller than the disadvantage of having a
11321     // much more complicated generator structure. See also comment in
11322     // stubRoutines.hpp.
11323 
11324     StubRoutines::_forward_exception_entry = generate_forward_exception();
11325 
11326     StubRoutines::_call_stub_entry =
11327       generate_call_stub(StubRoutines::_call_stub_return_address);
11328 
11329     // is referenced by megamorphic call
11330     StubRoutines::_catch_exception_entry = generate_catch_exception();
11331 
11332     // Initialize table for copy memory (arraycopy) check.
11333     if (UnsafeMemoryAccess::_table == nullptr) {
11334       UnsafeMemoryAccess::create_table(8 + 4); // 8 for copyMemory; 4 for setMemory

11534       StubRoutines::_sha3_implCompress     = generate_sha3_implCompress(StubGenStubId::sha3_implCompress_id);
11535       StubRoutines::_double_keccak         = generate_double_keccak();
11536       StubRoutines::_sha3_implCompressMB   = generate_sha3_implCompress(StubGenStubId::sha3_implCompressMB_id);
11537     }
11538 
11539     if (UsePoly1305Intrinsics) {
11540       StubRoutines::_poly1305_processBlocks = generate_poly1305_processBlocks();
11541     }
11542 
11543     // generate Adler32 intrinsics code
11544     if (UseAdler32Intrinsics) {
11545       StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32();
11546     }
11547 
11548 #endif // COMPILER2_OR_JVMCI
11549   }
11550 
11551  public:
11552   StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) {
11553     switch(blob_id) {
11554     case preuniverse_id:
11555       generate_preuniverse_stubs();
11556       break;
11557     case initial_id:
11558       generate_initial_stubs();
11559       break;
11560      case continuation_id:
11561       generate_continuation_stubs();
11562       break;
11563     case compiler_id:
11564       generate_compiler_stubs();
11565       break;
11566     case final_id:
11567       generate_final_stubs();
11568       break;
11569     default:
11570       fatal("unexpected blob id: %d", blob_id);
11571       break;
11572     };
11573   }
11574 }; // end class declaration
11575 
11576 void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) {
< prev index next >