< 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"

3126 
3127 /**
3128  *  Arguments:
3129  *
3130  *  Input:
3131  *    c_rarg0   - x address
3132  *    c_rarg1   - x length
3133  *    c_rarg2   - y address
3134  *    c_rarg3   - y length
3135  * not Win64
3136  *    c_rarg4   - z address
3137  * Win64
3138  *    rsp+40    - z address
3139  */
3140 address StubGenerator::generate_multiplyToLen() {
3141   __ align(CodeEntryAlignment);
3142   StubId stub_id = StubId::stubgen_multiplyToLen_id;
3143   StubCodeMark mark(this, stub_id);
3144   address start = __ pc();
3145 




3146   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3147   // Unix:  rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3148   const Register x     = rdi;
3149   const Register xlen  = rax;
3150   const Register y     = rsi;
3151   const Register ylen  = rcx;
3152   const Register z     = r8;
3153 
3154   // Next registers will be saved on stack in multiply_to_len().
3155   const Register tmp0  = r11;
3156   const Register tmp1  = r12;
3157   const Register tmp2  = r13;
3158   const Register tmp3  = r14;
3159   const Register tmp4  = r15;
3160   const Register tmp5  = rbx;
3161 
3162   BLOCK_COMMENT("Entry:");
3163   __ enter(); // required for proper stackwalking of RuntimeStub frame
3164 
3165   setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
3166                      // ylen => rcx, z => r8
3167                      // r9 and r10 may be used to save non-volatile registers
3168 #ifdef _WIN64
3169   // last argument (#4) is on stack on Win64
3170   __ movptr(z, Address(rsp, 6 * wordSize));
3171 #endif
3172 
3173   __ movptr(xlen, rsi);
3174   __ movptr(y,    rdx);
3175   __ multiply_to_len(x, xlen, y, ylen, z, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
3176 
3177   restore_arg_regs();
3178 
3179   __ leave(); // required for proper stackwalking of RuntimeStub frame
3180   __ ret(0);
3181 

3182   return start;
3183 }
3184 
3185 /**
3186 *  Arguments:
3187 *
3188 *  Input:
3189 *    c_rarg0   - obja     address
3190 *    c_rarg1   - objb     address
3191 *    c_rarg3   - length   length
3192 *    c_rarg4   - scale    log2_array_indxscale
3193 *
3194 *  Output:
3195 *        rax   - int >= mismatched index, < 0 bitwise complement of tail
3196 */
3197 address StubGenerator::generate_vectorizedMismatch() {
3198   __ align(CodeEntryAlignment);
3199   StubId stub_id = StubId::stubgen_vectorizedMismatch_id;
3200   StubCodeMark mark(this, stub_id);
3201   address start = __ pc();

3235   return start;
3236 }
3237 
3238 /**
3239  *  Arguments:
3240  *
3241 //  Input:
3242 //    c_rarg0   - x address
3243 //    c_rarg1   - x length
3244 //    c_rarg2   - z address
3245 //    c_rarg3   - z length
3246  *
3247  */
3248 address StubGenerator::generate_squareToLen() {
3249 
3250   __ align(CodeEntryAlignment);
3251   StubId stub_id = StubId::stubgen_squareToLen_id;
3252   StubCodeMark mark(this, stub_id);
3253   address start = __ pc();
3254 




3255   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3256   // Unix:  rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
3257   const Register x      = rdi;
3258   const Register len    = rsi;
3259   const Register z      = r8;
3260   const Register zlen   = rcx;
3261 
3262  const Register tmp1      = r12;
3263  const Register tmp2      = r13;
3264  const Register tmp3      = r14;
3265  const Register tmp4      = r15;
3266  const Register tmp5      = rbx;
3267 
3268   BLOCK_COMMENT("Entry:");
3269   __ enter(); // required for proper stackwalking of RuntimeStub frame
3270 
3271   setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
3272                      // zlen => rcx
3273                      // r9 and r10 may be used to save non-volatile registers
3274   __ movptr(r8, rdx);
3275   __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3276 
3277   restore_arg_regs();
3278 
3279   __ leave(); // required for proper stackwalking of RuntimeStub frame
3280   __ ret(0);
3281 

3282   return start;
3283 }
3284 
3285 address StubGenerator::generate_method_entry_barrier() {
3286   __ align(CodeEntryAlignment);
3287   StubId stub_id = StubId::stubgen_method_entry_barrier_id;
3288   StubCodeMark mark(this, stub_id);
3289   address start = __ pc();
3290 
3291   Label deoptimize_label;
3292 
3293   __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
3294 
3295   BLOCK_COMMENT("Entry:");
3296   __ enter(); // save rbp
3297 
3298   // save c_rarg0, because we want to use that value.
3299   // We could do without it but then we depend on the number of slots used by pusha
3300   __ push_ppx(c_rarg0);
3301 

3361 
3362  /**
3363  *  Arguments:
3364  *
3365  *  Input:
3366  *    c_rarg0   - out address
3367  *    c_rarg1   - in address
3368  *    c_rarg2   - offset
3369  *    c_rarg3   - len
3370  * not Win64
3371  *    c_rarg4   - k
3372  * Win64
3373  *    rsp+40    - k
3374  */
3375 address StubGenerator::generate_mulAdd() {
3376   __ align(CodeEntryAlignment);
3377   StubId stub_id = StubId::stubgen_mulAdd_id;
3378   StubCodeMark mark(this, stub_id);
3379   address start = __ pc();
3380 




3381   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3382   // Unix:  rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3383   const Register out     = rdi;
3384   const Register in      = rsi;
3385   const Register offset  = r11;
3386   const Register len     = rcx;
3387   const Register k       = r8;
3388 
3389   // Next registers will be saved on stack in mul_add().
3390   const Register tmp1  = r12;
3391   const Register tmp2  = r13;
3392   const Register tmp3  = r14;
3393   const Register tmp4  = r15;
3394   const Register tmp5  = rbx;
3395 
3396   BLOCK_COMMENT("Entry:");
3397   __ enter(); // required for proper stackwalking of RuntimeStub frame
3398 
3399   setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3400                      // len => rcx, k => r8
3401                      // r9 and r10 may be used to save non-volatile registers
3402 #ifdef _WIN64
3403   // last argument is on stack on Win64
3404   __ movl(k, Address(rsp, 6 * wordSize));
3405 #endif
3406   __ movptr(r11, rdx);  // move offset in rdx to offset(r11)
3407   __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3408 
3409   restore_arg_regs();
3410 
3411   __ leave(); // required for proper stackwalking of RuntimeStub frame
3412   __ ret(0);
3413 

3414   return start;
3415 }
3416 
3417 address StubGenerator::generate_bigIntegerRightShift() {
3418   __ align(CodeEntryAlignment);
3419   StubId stub_id = StubId::stubgen_bigIntegerRightShiftWorker_id;
3420   StubCodeMark mark(this, stub_id);
3421   address start = __ pc();
3422 
3423   Label Shift512Loop, ShiftTwo, ShiftTwoLoop, ShiftOne, Exit;
3424   // For Unix, the arguments are as follows: rdi, rsi, rdx, rcx, r8.
3425   const Register newArr = rdi;
3426   const Register oldArr = rsi;
3427   const Register newIdx = rdx;
3428   const Register shiftCount = rcx;  // It was intentional to have shiftCount in rcx since it is used implicitly for shift.
3429   const Register totalNumIter = r8;
3430 
3431   // For windows, we use r9 and r10 as temps to save rdi and rsi. Thus we cannot allocate them for our temps.
3432   // For everything else, we prefer using r9 and r10 since we do not have to save them before use.
3433   const Register tmp1 = r11;                    // Caller save.

   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"

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

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

3372 
3373  /**
3374  *  Arguments:
3375  *
3376  *  Input:
3377  *    c_rarg0   - out address
3378  *    c_rarg1   - in address
3379  *    c_rarg2   - offset
3380  *    c_rarg3   - len
3381  * not Win64
3382  *    c_rarg4   - k
3383  * Win64
3384  *    rsp+40    - k
3385  */
3386 address StubGenerator::generate_mulAdd() {
3387   __ align(CodeEntryAlignment);
3388   StubId stub_id = StubId::stubgen_mulAdd_id;
3389   StubCodeMark mark(this, stub_id);
3390   address start = __ pc();
3391 
3392   if (AOTCodeCache::load_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start)) {
3393     return start;
3394   }
3395 
3396   // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
3397   // Unix:  rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
3398   const Register out     = rdi;
3399   const Register in      = rsi;
3400   const Register offset  = r11;
3401   const Register len     = rcx;
3402   const Register k       = r8;
3403 
3404   // Next registers will be saved on stack in mul_add().
3405   const Register tmp1  = r12;
3406   const Register tmp2  = r13;
3407   const Register tmp3  = r14;
3408   const Register tmp4  = r15;
3409   const Register tmp5  = rbx;
3410 
3411   BLOCK_COMMENT("Entry:");
3412   __ enter(); // required for proper stackwalking of RuntimeStub frame
3413 
3414   setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
3415                      // len => rcx, k => r8
3416                      // r9 and r10 may be used to save non-volatile registers
3417 #ifdef _WIN64
3418   // last argument is on stack on Win64
3419   __ movl(k, Address(rsp, 6 * wordSize));
3420 #endif
3421   __ movptr(r11, rdx);  // move offset in rdx to offset(r11)
3422   __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
3423 
3424   restore_arg_regs();
3425 
3426   __ leave(); // required for proper stackwalking of RuntimeStub frame
3427   __ ret(0);
3428 
3429   AOTCodeCache::store_stub(this, vmIntrinsics::_mulAdd, "mulAdd", start);
3430   return start;
3431 }
3432 
3433 address StubGenerator::generate_bigIntegerRightShift() {
3434   __ align(CodeEntryAlignment);
3435   StubId stub_id = StubId::stubgen_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.
< prev index next >