< prev index next >

src/hotspot/cpu/x86/stubGenerator_x86_64.cpp

Print this page

   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "asm/macroAssembler.hpp"
  26 #include "classfile/javaClasses.hpp"
  27 #include "classfile/vmIntrinsics.hpp"

  28 #include "compiler/oopMap.hpp"
  29 #include "gc/shared/barrierSet.hpp"
  30 #include "gc/shared/barrierSetAssembler.hpp"
  31 #include "gc/shared/barrierSetNMethod.hpp"
  32 #include "gc/shared/gc_globals.hpp"
  33 #include "memory/universe.hpp"
  34 #include "prims/jvmtiExport.hpp"
  35 #include "prims/upcallLinker.hpp"
  36 #include "runtime/arguments.hpp"
  37 #include "runtime/continuationEntry.hpp"
  38 #include "runtime/javaThread.hpp"
  39 #include "runtime/sharedRuntime.hpp"
  40 #include "runtime/stubRoutines.hpp"
  41 #include "stubGenerator_x86_64.hpp"
  42 #ifdef COMPILER2
  43 #include "opto/runtime.hpp"
  44 #include "opto/c2_globals.hpp"
  45 #endif
  46 #if INCLUDE_JVMCI
  47 #include "jvmci/jvmci_globals.hpp"

3142 
3143 /**
3144  *  Arguments:
3145  *
3146  *  Input:
3147  *    c_rarg0   - x address
3148  *    c_rarg1   - x length
3149  *    c_rarg2   - y address
3150  *    c_rarg3   - y length
3151  * not Win64
3152  *    c_rarg4   - z address
3153  * Win64
3154  *    rsp+40    - z address
3155  */
3156 address StubGenerator::generate_multiplyToLen() {
3157   __ align(CodeEntryAlignment);
3158   StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
3159   StubCodeMark mark(this, stub_id);
3160   address start = __ pc();
3161 




3162   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3163   // Unix:  rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3164   const Register x     = rdi;
3165   const Register xlen  = rax;
3166   const Register y     = rsi;
3167   const Register ylen  = rcx;
3168   const Register z     = r8;
3169 
3170   // Next registers will be saved on stack in multiply_to_len().
3171   const Register tmp0  = r11;
3172   const Register tmp1  = r12;
3173   const Register tmp2  = r13;
3174   const Register tmp3  = r14;
3175   const Register tmp4  = r15;
3176   const Register tmp5  = rbx;
3177 
3178   BLOCK_COMMENT("Entry:");
3179   __ enter(); // required for proper stackwalking of RuntimeStub frame
3180 
3181   setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
3182                      // ylen => rcx, z => r8
3183                      // r9 and r10 may be used to save non-volatile registers
3184 #ifdef _WIN64
3185   // last argument (#4) is on stack on Win64
3186   __ movptr(z, Address(rsp, 6 * wordSize));
3187 #endif
3188 
3189   __ movptr(xlen, rsi);
3190   __ movptr(y,    rdx);
3191   __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
3192 
3193   restore_arg_regs();
3194 
3195   __ leave(); // required for proper stackwalking of RuntimeStub frame
3196   __ ret(0);
3197 

3198   return start;
3199 }
3200 
3201 /**
3202 *  Arguments:
3203 *
3204 *  Input:
3205 *    c_rarg0   - obja     address
3206 *    c_rarg1   - objb     address
3207 *    c_rarg3   - length   length
3208 *    c_rarg4   - scale    log2_array_indxscale
3209 *
3210 *  Output:
3211 *        rax   - int >= mismatched index, < 0 bitwise complement of tail
3212 */
3213 address StubGenerator::generate_vectorizedMismatch() {
3214   __ align(CodeEntryAlignment);
3215   StubGenStubId stub_id = StubGenStubId::vectorizedMismatch_id;
3216   StubCodeMark mark(this, stub_id);
3217   address start = __ pc();

3251   return start;
3252 }
3253 
3254 /**
3255  *  Arguments:
3256  *
3257 //  Input:
3258 //    c_rarg0   - x address
3259 //    c_rarg1   - x length
3260 //    c_rarg2   - z address
3261 //    c_rarg3   - z length
3262  *
3263  */
3264 address StubGenerator::generate_squareToLen() {
3265 
3266   __ align(CodeEntryAlignment);
3267   StubGenStubId stub_id = StubGenStubId::squareToLen_id;
3268   StubCodeMark mark(this, stub_id);
3269   address start = __ pc();
3270 




3271   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3272   // Unix:  rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
3273   const Register x      = rdi;
3274   const Register len    = rsi;
3275   const Register z      = r8;
3276   const Register zlen   = rcx;
3277 
3278  const Register tmp1      = r12;
3279  const Register tmp2      = r13;
3280  const Register tmp3      = r14;
3281  const Register tmp4      = r15;
3282  const Register tmp5      = rbx;
3283 
3284   BLOCK_COMMENT("Entry:");
3285   __ enter(); // required for proper stackwalking of RuntimeStub frame
3286 
3287   setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
3288                      // zlen => rcx
3289                      // r9 and r10 may be used to save non-volatile registers
3290   __ movptr(r8, rdx);
3291   __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3292 
3293   restore_arg_regs();
3294 
3295   __ leave(); // required for proper stackwalking of RuntimeStub frame
3296   __ ret(0);
3297 

3298   return start;
3299 }
3300 
3301 address StubGenerator::generate_method_entry_barrier() {
3302   __ align(CodeEntryAlignment);
3303   StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id;
3304   StubCodeMark mark(this, stub_id);
3305   address start = __ pc();
3306 
3307   Label deoptimize_label;
3308 
3309   __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
3310 
3311   BLOCK_COMMENT("Entry:");
3312   __ enter(); // save rbp
3313 
3314   // save c_rarg0, because we want to use that value.
3315   // We could do without it but then we depend on the number of slots used by pusha
3316   __ push(c_rarg0);
3317 

3377 
3378  /**
3379  *  Arguments:
3380  *
3381  *  Input:
3382  *    c_rarg0   - out address
3383  *    c_rarg1   - in address
3384  *    c_rarg2   - offset
3385  *    c_rarg3   - len
3386  * not Win64
3387  *    c_rarg4   - k
3388  * Win64
3389  *    rsp+40    - k
3390  */
3391 address StubGenerator::generate_mulAdd() {
3392   __ align(CodeEntryAlignment);
3393   StubGenStubId stub_id = StubGenStubId::mulAdd_id;
3394   StubCodeMark mark(this, stub_id);
3395   address start = __ pc();
3396 




3397   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3398   // Unix:  rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3399   const Register out     = rdi;
3400   const Register in      = rsi;
3401   const Register offset  = r11;
3402   const Register len     = rcx;
3403   const Register k       = r8;
3404 
3405   // Next registers will be saved on stack in mul_add().
3406   const Register tmp1  = r12;
3407   const Register tmp2  = r13;
3408   const Register tmp3  = r14;
3409   const Register tmp4  = r15;
3410   const Register tmp5  = rbx;
3411 
3412   BLOCK_COMMENT("Entry:");
3413   __ enter(); // required for proper stackwalking of RuntimeStub frame
3414 
3415   setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3416                      // len => rcx, k => r8
3417                      // r9 and r10 may be used to save non-volatile registers
3418 #ifdef _WIN64
3419   // last argument is on stack on Win64
3420   __ movl(k, Address(rsp, 6 * wordSize));
3421 #endif
3422   __ movptr(r11, rdx);  // move offset in rdx to offset(r11)
3423   __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3424 
3425   restore_arg_regs();
3426 
3427   __ leave(); // required for proper stackwalking of RuntimeStub frame
3428   __ ret(0);
3429 

3430   return start;
3431 }
3432 
3433 address StubGenerator::generate_bigIntegerRightShift() {
3434   __ align(CodeEntryAlignment);
3435   StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
3436   StubCodeMark mark(this, stub_id);
3437   address start = __ pc();
3438 
3439   Label Shift512Loop, ShiftTwo, ShiftTwoLoop, ShiftOne, Exit;
3440   // For Unix, the arguments are as follows: rdi, rsi, rdx, rcx, r8.
3441   const Register newArr = rdi;
3442   const Register oldArr = rsi;
3443   const Register newIdx = rdx;
3444   const Register shiftCount = rcx;  // It was intentional to have shiftCount in rcx since it is used implicitly for shift.
3445   const Register totalNumIter = r8;
3446 
3447   // For windows, we use r9 and r10 as temps to save rdi and rsi. Thus we cannot allocate them for our temps.
3448   // For everything else, we prefer using r9 and r10 since we do not have to save them before use.
3449   const Register tmp1 = r11;                    // Caller save.

4032                                              &L_success);
4033   // bind(L_failure);
4034   __ movl(result, 1);
4035   __ ret(0);
4036 
4037   __ bind(L_success);
4038   __ movl(result, 0);
4039   __ ret(0);
4040 
4041   return start;
4042 }
4043 
4044 void StubGenerator::create_control_words() {
4045   // Round to nearest, 64-bit mode, exceptions masked, flags specialized
4046   StubRoutines::x86::_mxcsr_std = EnableX86ECoreOpts ? 0x1FBF : 0x1F80;
4047   // Round to zero, 64-bit mode, exceptions masked, flags specialized
4048   StubRoutines::x86::_mxcsr_rz = EnableX86ECoreOpts ? 0x7FBF : 0x7F80;
4049 }
4050 
4051 // Initialization





4052 void StubGenerator::generate_initial_stubs() {
4053   // Generates all stubs and initializes the entry points
4054 
4055   // This platform-specific settings are needed by generate_call_stub()
4056   create_control_words();
4057 
4058   // Initialize table for unsafe copy memeory check.
4059   if (UnsafeMemoryAccess::_table == nullptr) {
4060     UnsafeMemoryAccess::create_table(16 + 4); // 16 for copyMemory; 4 for setMemory
4061   }
4062 
4063   // entry points that exist in all platforms Note: This is code
4064   // that could be shared among different platforms - however the
4065   // benefit seems to be smaller than the disadvantage of having a
4066   // much more complicated generator structure. See also comment in
4067   // stubRoutines.hpp.
4068 
4069   StubRoutines::_forward_exception_entry = generate_forward_exception();
4070 
4071   StubRoutines::_call_stub_entry =
4072     generate_call_stub(StubRoutines::_call_stub_return_address);
4073 
4074   // is referenced by megamorphic call
4075   StubRoutines::_catch_exception_entry = generate_catch_exception();
4076 
4077   // atomic calls
4078   StubRoutines::_fence_entry                = generate_orderaccess_fence();
4079 
4080   // platform dependent
4081   StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();
4082 
4083   StubRoutines::x86::_verify_mxcsr_entry    = generate_verify_mxcsr();
4084 
4085   StubRoutines::x86::_f2i_fixup             = generate_f2i_fixup();
4086   StubRoutines::x86::_f2l_fixup             = generate_f2l_fixup();
4087   StubRoutines::x86::_d2i_fixup             = generate_d2i_fixup();
4088   StubRoutines::x86::_d2l_fixup             = generate_d2l_fixup();
4089 
4090   StubRoutines::x86::_float_sign_mask       = generate_fp_mask(StubGenStubId::float_sign_mask_id,  0x7FFFFFFF7FFFFFFF);
4091   StubRoutines::x86::_float_sign_flip       = generate_fp_mask(StubGenStubId::float_sign_flip_id,  0x8000000080000000);
4092   StubRoutines::x86::_double_sign_mask      = generate_fp_mask(StubGenStubId::double_sign_mask_id, 0x7FFFFFFFFFFFFFFF);
4093   StubRoutines::x86::_double_sign_flip      = generate_fp_mask(StubGenStubId::double_sign_flip_id, 0x8000000000000000);
4094 
4095   if (UseCRC32Intrinsics) {
4096     // set table address before stub generation which use it
4097     StubRoutines::_crc_table_adr = (address)StubRoutines::x86::_crc_table;
4098     StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32();
4099   }

4327       libsimdsort = os::dll_load(dll_name_simd_sort, ebuf_, sizeof ebuf_);
4328     }
4329     // Get addresses for SIMD sort and partition routines
4330     if (libsimdsort != nullptr) {
4331       log_info(library)("Loaded library %s, handle " INTPTR_FORMAT, JNI_LIB_PREFIX "simdsort" JNI_LIB_SUFFIX, p2i(libsimdsort));
4332 
4333       snprintf(ebuf_, sizeof(ebuf_), VM_Version::supports_avx512_simd_sort() ? "avx512_sort" : "avx2_sort");
4334       StubRoutines::_array_sort = (address)os::dll_lookup(libsimdsort, ebuf_);
4335 
4336       snprintf(ebuf_, sizeof(ebuf_), VM_Version::supports_avx512_simd_sort() ? "avx512_partition" : "avx2_partition");
4337       StubRoutines::_array_partition = (address)os::dll_lookup(libsimdsort, ebuf_);
4338     }
4339   }
4340 
4341 #endif // COMPILER2
4342 #endif // COMPILER2_OR_JVMCI
4343 }
4344 
4345 StubGenerator::StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) {
4346   switch(blob_id) {



4347   case initial_id:
4348     generate_initial_stubs();
4349     break;
4350   case continuation_id:
4351     generate_continuation_stubs();
4352     break;
4353   case compiler_id:
4354     generate_compiler_stubs();
4355     break;
4356   case final_id:
4357     generate_final_stubs();
4358     break;
4359   default:
4360     fatal("unexpected blob id: %d", blob_id);
4361     break;
4362   };
4363 }
4364 
4365 void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) {
4366   StubGenerator g(code, blob_id);

   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "asm/macroAssembler.hpp"
  26 #include "classfile/javaClasses.hpp"
  27 #include "classfile/vmIntrinsics.hpp"
  28 #include "code/aotCodeCache.hpp"
  29 #include "compiler/oopMap.hpp"
  30 #include "gc/shared/barrierSet.hpp"
  31 #include "gc/shared/barrierSetAssembler.hpp"
  32 #include "gc/shared/barrierSetNMethod.hpp"
  33 #include "gc/shared/gc_globals.hpp"
  34 #include "memory/universe.hpp"
  35 #include "prims/jvmtiExport.hpp"
  36 #include "prims/upcallLinker.hpp"
  37 #include "runtime/arguments.hpp"
  38 #include "runtime/continuationEntry.hpp"
  39 #include "runtime/javaThread.hpp"
  40 #include "runtime/sharedRuntime.hpp"
  41 #include "runtime/stubRoutines.hpp"
  42 #include "stubGenerator_x86_64.hpp"
  43 #ifdef COMPILER2
  44 #include "opto/runtime.hpp"
  45 #include "opto/c2_globals.hpp"
  46 #endif
  47 #if INCLUDE_JVMCI
  48 #include "jvmci/jvmci_globals.hpp"

3143 
3144 /**
3145  *  Arguments:
3146  *
3147  *  Input:
3148  *    c_rarg0   - x address
3149  *    c_rarg1   - x length
3150  *    c_rarg2   - y address
3151  *    c_rarg3   - y length
3152  * not Win64
3153  *    c_rarg4   - z address
3154  * Win64
3155  *    rsp+40    - z address
3156  */
3157 address StubGenerator::generate_multiplyToLen() {
3158   __ align(CodeEntryAlignment);
3159   StubGenStubId stub_id = StubGenStubId::multiplyToLen_id;
3160   StubCodeMark mark(this, stub_id);
3161   address start = __ pc();
3162 
3163   if (AOTCodeCache::load_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start)) {
3164     return start;
3165   }
3166 
3167   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3168   // Unix:  rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3169   const Register x     = rdi;
3170   const Register xlen  = rax;
3171   const Register y     = rsi;
3172   const Register ylen  = rcx;
3173   const Register z     = r8;
3174 
3175   // Next registers will be saved on stack in multiply_to_len().
3176   const Register tmp0  = r11;
3177   const Register tmp1  = r12;
3178   const Register tmp2  = r13;
3179   const Register tmp3  = r14;
3180   const Register tmp4  = r15;
3181   const Register tmp5  = rbx;
3182 
3183   BLOCK_COMMENT("Entry:");
3184   __ enter(); // required for proper stackwalking of RuntimeStub frame
3185 
3186   setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
3187                      // ylen => rcx, z => r8
3188                      // r9 and r10 may be used to save non-volatile registers
3189 #ifdef _WIN64
3190   // last argument (#4) is on stack on Win64
3191   __ movptr(z, Address(rsp, 6 * wordSize));
3192 #endif
3193 
3194   __ movptr(xlen, rsi);
3195   __ movptr(y,    rdx);
3196   __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
3197 
3198   restore_arg_regs();
3199 
3200   __ leave(); // required for proper stackwalking of RuntimeStub frame
3201   __ ret(0);
3202 
3203   AOTCodeCache::store_stub(this, vmIntrinsics::_multiplyToLen, "multiplyToLen", start);
3204   return start;
3205 }
3206 
3207 /**
3208 *  Arguments:
3209 *
3210 *  Input:
3211 *    c_rarg0   - obja     address
3212 *    c_rarg1   - objb     address
3213 *    c_rarg3   - length   length
3214 *    c_rarg4   - scale    log2_array_indxscale
3215 *
3216 *  Output:
3217 *        rax   - int >= mismatched index, < 0 bitwise complement of tail
3218 */
3219 address StubGenerator::generate_vectorizedMismatch() {
3220   __ align(CodeEntryAlignment);
3221   StubGenStubId stub_id = StubGenStubId::vectorizedMismatch_id;
3222   StubCodeMark mark(this, stub_id);
3223   address start = __ pc();

3257   return start;
3258 }
3259 
3260 /**
3261  *  Arguments:
3262  *
3263 //  Input:
3264 //    c_rarg0   - x address
3265 //    c_rarg1   - x length
3266 //    c_rarg2   - z address
3267 //    c_rarg3   - z length
3268  *
3269  */
3270 address StubGenerator::generate_squareToLen() {
3271 
3272   __ align(CodeEntryAlignment);
3273   StubGenStubId stub_id = StubGenStubId::squareToLen_id;
3274   StubCodeMark mark(this, stub_id);
3275   address start = __ pc();
3276 
3277   if (AOTCodeCache::load_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start)) {
3278     return start;
3279   }
3280 
3281   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3282   // Unix:  rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
3283   const Register x      = rdi;
3284   const Register len    = rsi;
3285   const Register z      = r8;
3286   const Register zlen   = rcx;
3287 
3288  const Register tmp1      = r12;
3289  const Register tmp2      = r13;
3290  const Register tmp3      = r14;
3291  const Register tmp4      = r15;
3292  const Register tmp5      = rbx;
3293 
3294   BLOCK_COMMENT("Entry:");
3295   __ enter(); // required for proper stackwalking of RuntimeStub frame
3296 
3297   setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
3298                      // zlen => rcx
3299                      // r9 and r10 may be used to save non-volatile registers
3300   __ movptr(r8, rdx);
3301   __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3302 
3303   restore_arg_regs();
3304 
3305   __ leave(); // required for proper stackwalking of RuntimeStub frame
3306   __ ret(0);
3307 
3308   AOTCodeCache::store_stub(this, vmIntrinsics::_squareToLen, "squareToLen", start);
3309   return start;
3310 }
3311 
3312 address StubGenerator::generate_method_entry_barrier() {
3313   __ align(CodeEntryAlignment);
3314   StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id;
3315   StubCodeMark mark(this, stub_id);
3316   address start = __ pc();
3317 
3318   Label deoptimize_label;
3319 
3320   __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
3321 
3322   BLOCK_COMMENT("Entry:");
3323   __ enter(); // save rbp
3324 
3325   // save c_rarg0, because we want to use that value.
3326   // We could do without it but then we depend on the number of slots used by pusha
3327   __ push(c_rarg0);
3328 

3388 
3389  /**
3390  *  Arguments:
3391  *
3392  *  Input:
3393  *    c_rarg0   - out address
3394  *    c_rarg1   - in address
3395  *    c_rarg2   - offset
3396  *    c_rarg3   - len
3397  * not Win64
3398  *    c_rarg4   - k
3399  * Win64
3400  *    rsp+40    - k
3401  */
3402 address StubGenerator::generate_mulAdd() {
3403   __ align(CodeEntryAlignment);
3404   StubGenStubId stub_id = StubGenStubId::mulAdd_id;
3405   StubCodeMark mark(this, stub_id);
3406   address start = __ pc();
3407 
3408   if (AOTCodeCache::load_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start)) {
3409     return start;
3410   }
3411 
3412   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3413   // Unix:  rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3414   const Register out     = rdi;
3415   const Register in      = rsi;
3416   const Register offset  = r11;
3417   const Register len     = rcx;
3418   const Register k       = r8;
3419 
3420   // Next registers will be saved on stack in mul_add().
3421   const Register tmp1  = r12;
3422   const Register tmp2  = r13;
3423   const Register tmp3  = r14;
3424   const Register tmp4  = r15;
3425   const Register tmp5  = rbx;
3426 
3427   BLOCK_COMMENT("Entry:");
3428   __ enter(); // required for proper stackwalking of RuntimeStub frame
3429 
3430   setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3431                      // len => rcx, k => r8
3432                      // r9 and r10 may be used to save non-volatile registers
3433 #ifdef _WIN64
3434   // last argument is on stack on Win64
3435   __ movl(k, Address(rsp, 6 * wordSize));
3436 #endif
3437   __ movptr(r11, rdx);  // move offset in rdx to offset(r11)
3438   __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3439 
3440   restore_arg_regs();
3441 
3442   __ leave(); // required for proper stackwalking of RuntimeStub frame
3443   __ ret(0);
3444 
3445   AOTCodeCache::store_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start);
3446   return start;
3447 }
3448 
3449 address StubGenerator::generate_bigIntegerRightShift() {
3450   __ align(CodeEntryAlignment);
3451   StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id;
3452   StubCodeMark mark(this, stub_id);
3453   address start = __ pc();
3454 
3455   Label Shift512Loop, ShiftTwo, ShiftTwoLoop, ShiftOne, Exit;
3456   // For Unix, the arguments are as follows: rdi, rsi, rdx, rcx, r8.
3457   const Register newArr = rdi;
3458   const Register oldArr = rsi;
3459   const Register newIdx = rdx;
3460   const Register shiftCount = rcx;  // It was intentional to have shiftCount in rcx since it is used implicitly for shift.
3461   const Register totalNumIter = r8;
3462 
3463   // For windows, we use r9 and r10 as temps to save rdi and rsi. Thus we cannot allocate them for our temps.
3464   // For everything else, we prefer using r9 and r10 since we do not have to save them before use.
3465   const Register tmp1 = r11;                    // Caller save.

4048                                              &L_success);
4049   // bind(L_failure);
4050   __ movl(result, 1);
4051   __ ret(0);
4052 
4053   __ bind(L_success);
4054   __ movl(result, 0);
4055   __ ret(0);
4056 
4057   return start;
4058 }
4059 
4060 void StubGenerator::create_control_words() {
4061   // Round to nearest, 64-bit mode, exceptions masked, flags specialized
4062   StubRoutines::x86::_mxcsr_std = EnableX86ECoreOpts ? 0x1FBF : 0x1F80;
4063   // Round to zero, 64-bit mode, exceptions masked, flags specialized
4064   StubRoutines::x86::_mxcsr_rz = EnableX86ECoreOpts ? 0x7FBF : 0x7F80;
4065 }
4066 
4067 // Initialization
4068 void StubGenerator::generate_preuniverse_stubs() {
4069   // atomic calls
4070   StubRoutines::_fence_entry                = generate_orderaccess_fence();
4071 }
4072 
4073 void StubGenerator::generate_initial_stubs() {
4074   // Generates all stubs and initializes the entry points
4075 
4076   // This platform-specific settings are needed by generate_call_stub()
4077   create_control_words();
4078 
4079   // Initialize table for unsafe copy memeory check.
4080   if (UnsafeMemoryAccess::_table == nullptr) {
4081     UnsafeMemoryAccess::create_table(16 + 4); // 16 for copyMemory; 4 for setMemory
4082   }
4083 
4084   // entry points that exist in all platforms Note: This is code
4085   // that could be shared among different platforms - however the
4086   // benefit seems to be smaller than the disadvantage of having a
4087   // much more complicated generator structure. See also comment in
4088   // stubRoutines.hpp.
4089 
4090   StubRoutines::_forward_exception_entry = generate_forward_exception();
4091 
4092   StubRoutines::_call_stub_entry =
4093     generate_call_stub(StubRoutines::_call_stub_return_address);
4094 
4095   // is referenced by megamorphic call
4096   StubRoutines::_catch_exception_entry = generate_catch_exception();
4097 



4098   // platform dependent
4099   StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();
4100 
4101   StubRoutines::x86::_verify_mxcsr_entry    = generate_verify_mxcsr();
4102 
4103   StubRoutines::x86::_f2i_fixup             = generate_f2i_fixup();
4104   StubRoutines::x86::_f2l_fixup             = generate_f2l_fixup();
4105   StubRoutines::x86::_d2i_fixup             = generate_d2i_fixup();
4106   StubRoutines::x86::_d2l_fixup             = generate_d2l_fixup();
4107 
4108   StubRoutines::x86::_float_sign_mask       = generate_fp_mask(StubGenStubId::float_sign_mask_id,  0x7FFFFFFF7FFFFFFF);
4109   StubRoutines::x86::_float_sign_flip       = generate_fp_mask(StubGenStubId::float_sign_flip_id,  0x8000000080000000);
4110   StubRoutines::x86::_double_sign_mask      = generate_fp_mask(StubGenStubId::double_sign_mask_id, 0x7FFFFFFFFFFFFFFF);
4111   StubRoutines::x86::_double_sign_flip      = generate_fp_mask(StubGenStubId::double_sign_flip_id, 0x8000000000000000);
4112 
4113   if (UseCRC32Intrinsics) {
4114     // set table address before stub generation which use it
4115     StubRoutines::_crc_table_adr = (address)StubRoutines::x86::_crc_table;
4116     StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32();
4117   }

4345       libsimdsort = os::dll_load(dll_name_simd_sort, ebuf_, sizeof ebuf_);
4346     }
4347     // Get addresses for SIMD sort and partition routines
4348     if (libsimdsort != nullptr) {
4349       log_info(library)("Loaded library %s, handle " INTPTR_FORMAT, JNI_LIB_PREFIX "simdsort" JNI_LIB_SUFFIX, p2i(libsimdsort));
4350 
4351       snprintf(ebuf_, sizeof(ebuf_), VM_Version::supports_avx512_simd_sort() ? "avx512_sort" : "avx2_sort");
4352       StubRoutines::_array_sort = (address)os::dll_lookup(libsimdsort, ebuf_);
4353 
4354       snprintf(ebuf_, sizeof(ebuf_), VM_Version::supports_avx512_simd_sort() ? "avx512_partition" : "avx2_partition");
4355       StubRoutines::_array_partition = (address)os::dll_lookup(libsimdsort, ebuf_);
4356     }
4357   }
4358 
4359 #endif // COMPILER2
4360 #endif // COMPILER2_OR_JVMCI
4361 }
4362 
4363 StubGenerator::StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) {
4364   switch(blob_id) {
4365   case preuniverse_id:
4366     generate_preuniverse_stubs();
4367     break;
4368   case initial_id:
4369     generate_initial_stubs();
4370     break;
4371   case continuation_id:
4372     generate_continuation_stubs();
4373     break;
4374   case compiler_id:
4375     generate_compiler_stubs();
4376     break;
4377   case final_id:
4378     generate_final_stubs();
4379     break;
4380   default:
4381     fatal("unexpected blob id: %d", blob_id);
4382     break;
4383   };
4384 }
4385 
4386 void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) {
4387   StubGenerator g(code, blob_id);
< prev index next >