< prev index next >

src/cpu/x86/vm/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 "precompiled.hpp"
  26 #include "asm/macroAssembler.hpp"
  27 #include "asm/macroAssembler.inline.hpp"



  28 #include "interpreter/interpreter.hpp"
  29 #include "nativeInst_x86.hpp"
  30 #include "oops/instanceOop.hpp"
  31 #include "oops/method.hpp"
  32 #include "oops/objArrayKlass.hpp"
  33 #include "oops/oop.inline.hpp"
  34 #include "prims/methodHandles.hpp"
  35 #include "runtime/frame.inline.hpp"
  36 #include "runtime/handles.inline.hpp"
  37 #include "runtime/sharedRuntime.hpp"
  38 #include "runtime/stubCodeGenerator.hpp"
  39 #include "runtime/stubRoutines.hpp"
  40 #include "runtime/thread.inline.hpp"
  41 #include "utilities/top.hpp"
  42 #ifdef COMPILER2
  43 #include "opto/runtime.hpp"
  44 #endif
  45 
  46 // Declaration and definition of StubGenerator (no .hpp file).
  47 // For a more detailed description of the stub routine structure


 787       __ stmxcsr(mxcsr_save);
 788       __ movl(rax, mxcsr_save);
 789       __ andl(rax, MXCSR_MASK);    // Only check control and mask bits
 790       __ cmp32(rax, mxcsr_std);
 791       __ jcc(Assembler::equal, ok_ret);
 792 
 793       __ warn("MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall");
 794 
 795       __ ldmxcsr(mxcsr_std);
 796 
 797       __ bind(ok_ret);
 798       __ addptr(rsp, wordSize);
 799       __ pop(rax);
 800     }
 801 
 802     __ ret(0);
 803 
 804     return start;
 805   }
 806 






















































































 807   address generate_f2i_fixup() {
 808     StubCodeMark mark(this, "StubRoutines", "f2i_fixup");
 809     Address inout(rsp, 5 * wordSize); // return address + 4 saves
 810 
 811     address start = __ pc();
 812 
 813     Label L;
 814 
 815     __ push(rax);
 816     __ push(c_rarg3);
 817     __ push(c_rarg2);
 818     __ push(c_rarg1);
 819 
 820     __ movl(rax, 0x7f800000);
 821     __ xorl(c_rarg3, c_rarg3);
 822     __ movl(c_rarg2, inout);
 823     __ movl(c_rarg1, c_rarg2);
 824     __ andl(c_rarg1, 0x7fffffff);
 825     __ cmpl(rax, c_rarg1); // NaN? -> 0
 826     __ jcc(Assembler::negative, L);


1217     const Register saved_rdi = r9;
1218     const Register saved_rsi = r10;
1219 #ifdef _WIN64
1220     __ movptr(rdi, saved_rdi);
1221     __ movptr(rsi, saved_rsi);
1222 #endif
1223   }
1224 
1225   // Generate code for an array write pre barrier
1226   //
1227   //     addr    -  starting address
1228   //     count   -  element count
1229   //     tmp     - scratch register
1230   //
1231   //     Destroy no registers!
1232   //
1233   void  gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
1234     BarrierSet* bs = Universe::heap()->barrier_set();
1235     switch (bs->kind()) {
1236       case BarrierSet::G1SATBCTLogging:

1237         // With G1, don't generate the call if we statically know that the target in uninitialized
1238         if (!dest_uninitialized) {
1239            __ pusha();                      // push registers
1240            if (count == c_rarg0) {
1241              if (addr == c_rarg1) {
1242                // exactly backwards!!
1243                __ xchgptr(c_rarg1, c_rarg0);
1244              } else {
1245                __ movptr(c_rarg1, count);
1246                __ movptr(c_rarg0, addr);
1247              }
1248            } else {
1249              __ movptr(c_rarg0, addr);
1250              __ movptr(c_rarg1, count);
1251            }
1252            __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2);
1253            __ popa();
1254         }
1255          break;
1256       case BarrierSet::CardTableForRS:


1261         ShouldNotReachHere();
1262 
1263     }
1264   }
1265 
1266   //
1267   // Generate code for an array write post barrier
1268   //
1269   //  Input:
1270   //     start    - register containing starting address of destination array
1271   //     count    - elements count
1272   //     scratch  - scratch register
1273   //
1274   //  The input registers are overwritten.
1275   //
1276   void  gen_write_ref_array_post_barrier(Register start, Register count, Register scratch) {
1277     assert_different_registers(start, count, scratch);
1278     BarrierSet* bs = Universe::heap()->barrier_set();
1279     switch (bs->kind()) {
1280       case BarrierSet::G1SATBCTLogging:

1281         {
1282           __ pusha();             // push registers (overkill)
1283           if (c_rarg0 == count) { // On win64 c_rarg0 == rcx
1284             assert_different_registers(c_rarg1, start);
1285             __ mov(c_rarg1, count);
1286             __ mov(c_rarg0, start);
1287           } else {
1288             assert_different_registers(c_rarg0, count);
1289             __ mov(c_rarg0, start);
1290             __ mov(c_rarg1, count);
1291           }
1292           __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2);
1293           __ popa();
1294         }
1295         break;
1296       case BarrierSet::CardTableForRS:
1297       case BarrierSet::CardTableExtension:
1298         {
1299           CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
1300           assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");


4258     // fabricate a RuntimeStub internally.
4259     StubRoutines::_throw_AbstractMethodError_entry =
4260       generate_throw_exception("AbstractMethodError throw_exception",
4261                                CAST_FROM_FN_PTR(address,
4262                                                 SharedRuntime::
4263                                                 throw_AbstractMethodError));
4264 
4265     StubRoutines::_throw_IncompatibleClassChangeError_entry =
4266       generate_throw_exception("IncompatibleClassChangeError throw_exception",
4267                                CAST_FROM_FN_PTR(address,
4268                                                 SharedRuntime::
4269                                                 throw_IncompatibleClassChangeError));
4270 
4271     StubRoutines::_throw_NullPointerException_at_call_entry =
4272       generate_throw_exception("NullPointerException at call throw_exception",
4273                                CAST_FROM_FN_PTR(address,
4274                                                 SharedRuntime::
4275                                                 throw_NullPointerException_at_call));
4276 
4277     // entry points that are platform specific



4278     StubRoutines::x86::_f2i_fixup = generate_f2i_fixup();
4279     StubRoutines::x86::_f2l_fixup = generate_f2l_fixup();
4280     StubRoutines::x86::_d2i_fixup = generate_d2i_fixup();
4281     StubRoutines::x86::_d2l_fixup = generate_d2l_fixup();
4282 
4283     StubRoutines::x86::_float_sign_mask  = generate_fp_mask("float_sign_mask",  0x7FFFFFFF7FFFFFFF);
4284     StubRoutines::x86::_float_sign_flip  = generate_fp_mask("float_sign_flip",  0x8000000080000000);
4285     StubRoutines::x86::_double_sign_mask = generate_fp_mask("double_sign_mask", 0x7FFFFFFFFFFFFFFF);
4286     StubRoutines::x86::_double_sign_flip = generate_fp_mask("double_sign_flip", 0x8000000000000000);
4287 
4288     // support for verify_oop (must happen after universe_init)
4289     StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop();
4290 
4291     // arraycopy stubs used by compilers
4292     generate_arraycopy_stubs();
4293 
4294     generate_math_stubs();
4295 
4296     // don't bother generating these AES intrinsic stubs unless global flag is set
4297     if (UseAESIntrinsics) {




   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 "precompiled.hpp"
  26 #include "asm/macroAssembler.hpp"
  27 #include "asm/macroAssembler.inline.hpp"
  28 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  29 #include "gc/shenandoah/shenandoahHeap.hpp"
  30 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  31 #include "interpreter/interpreter.hpp"
  32 #include "nativeInst_x86.hpp"
  33 #include "oops/instanceOop.hpp"
  34 #include "oops/method.hpp"
  35 #include "oops/objArrayKlass.hpp"
  36 #include "oops/oop.inline.hpp"
  37 #include "prims/methodHandles.hpp"
  38 #include "runtime/frame.inline.hpp"
  39 #include "runtime/handles.inline.hpp"
  40 #include "runtime/sharedRuntime.hpp"
  41 #include "runtime/stubCodeGenerator.hpp"
  42 #include "runtime/stubRoutines.hpp"
  43 #include "runtime/thread.inline.hpp"
  44 #include "utilities/top.hpp"
  45 #ifdef COMPILER2
  46 #include "opto/runtime.hpp"
  47 #endif
  48 
  49 // Declaration and definition of StubGenerator (no .hpp file).
  50 // For a more detailed description of the stub routine structure


 790       __ stmxcsr(mxcsr_save);
 791       __ movl(rax, mxcsr_save);
 792       __ andl(rax, MXCSR_MASK);    // Only check control and mask bits
 793       __ cmp32(rax, mxcsr_std);
 794       __ jcc(Assembler::equal, ok_ret);
 795 
 796       __ warn("MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall");
 797 
 798       __ ldmxcsr(mxcsr_std);
 799 
 800       __ bind(ok_ret);
 801       __ addptr(rsp, wordSize);
 802       __ pop(rax);
 803     }
 804 
 805     __ ret(0);
 806 
 807     return start;
 808   }
 809 
 810   address generate_shenandoah_wb() {
 811     StubCodeMark mark(this, "StubRoutines", "shenandoah_wb");
 812     address start = __ pc();
 813 
 814     Label done;
 815 
 816     __ push(rbx);
 817     // Check for object beeing in the collection set.
 818     // TODO: Can we use only 1 register here?
 819     __ movptr(rdi, rax);
 820     __ shrptr(rdi, ShenandoahHeapRegion::RegionSizeShift);
 821     __ movptr(rbx, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr());
 822     __ movbool(rbx, Address(rbx, rdi, Address::times_1));
 823     __ testbool(rbx);
 824     __ jcc(Assembler::zero, done);
 825 
 826     __ push(rcx);
 827     __ push(rdx);
 828     __ push(rdi);
 829     __ push(rsi);
 830     __ push(r8);
 831     __ push(r9);
 832     __ push(r10);
 833     __ push(r11);
 834     __ push(r12);
 835     __ push(r13);
 836     __ push(r14);
 837     __ push(r15);
 838     __ subptr(rsp, 128);
 839     __ movdbl(Address(rsp, 0), xmm0);
 840     __ movdbl(Address(rsp, 8), xmm1);
 841     __ movdbl(Address(rsp, 16), xmm2);
 842     __ movdbl(Address(rsp, 24), xmm3);
 843     __ movdbl(Address(rsp, 32), xmm4);
 844     __ movdbl(Address(rsp, 40), xmm5);
 845     __ movdbl(Address(rsp, 48), xmm6);
 846     __ movdbl(Address(rsp, 56), xmm7);
 847     __ movdbl(Address(rsp, 64), xmm8);
 848     __ movdbl(Address(rsp, 72), xmm9);
 849     __ movdbl(Address(rsp, 80), xmm10);
 850     __ movdbl(Address(rsp, 88), xmm11);
 851     __ movdbl(Address(rsp, 96), xmm12);
 852     __ movdbl(Address(rsp, 104), xmm13);
 853     __ movdbl(Address(rsp, 112), xmm14);
 854     __ movdbl(Address(rsp, 120), xmm15);
 855     __ movptr(rdi, rax);
 856     __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahBarrierSet::write_barrier_c2), rdi);
 857     __ movdbl(xmm0, Address(rsp, 0));
 858     __ movdbl(xmm1, Address(rsp, 8));
 859     __ movdbl(xmm2, Address(rsp, 16));
 860     __ movdbl(xmm3, Address(rsp, 24));
 861     __ movdbl(xmm4, Address(rsp, 32));
 862     __ movdbl(xmm5, Address(rsp, 40));
 863     __ movdbl(xmm6, Address(rsp, 48));
 864     __ movdbl(xmm7, Address(rsp, 56));
 865     __ movdbl(xmm8, Address(rsp, 64));
 866     __ movdbl(xmm9, Address(rsp, 72));
 867     __ movdbl(xmm10, Address(rsp, 80));
 868     __ movdbl(xmm11, Address(rsp, 88));
 869     __ movdbl(xmm12, Address(rsp, 96));
 870     __ movdbl(xmm13, Address(rsp, 104));
 871     __ movdbl(xmm14, Address(rsp, 112));
 872     __ movdbl(xmm15, Address(rsp, 120));
 873     __ addptr(rsp, 128);
 874     __ pop(r15);
 875     __ pop(r14);
 876     __ pop(r13);
 877     __ pop(r12);
 878     __ pop(r11);
 879     __ pop(r10);
 880     __ pop(r9);
 881     __ pop(r8);
 882     __ pop(rsi);
 883     __ pop(rdi);
 884     __ pop(rdx);
 885     __ pop(rcx);
 886 
 887     __ bind(done);
 888 
 889     __ pop(rbx);
 890 
 891     __ ret(0);
 892 
 893     return start;
 894   }
 895 
 896   address generate_f2i_fixup() {
 897     StubCodeMark mark(this, "StubRoutines", "f2i_fixup");
 898     Address inout(rsp, 5 * wordSize); // return address + 4 saves
 899 
 900     address start = __ pc();
 901 
 902     Label L;
 903 
 904     __ push(rax);
 905     __ push(c_rarg3);
 906     __ push(c_rarg2);
 907     __ push(c_rarg1);
 908 
 909     __ movl(rax, 0x7f800000);
 910     __ xorl(c_rarg3, c_rarg3);
 911     __ movl(c_rarg2, inout);
 912     __ movl(c_rarg1, c_rarg2);
 913     __ andl(c_rarg1, 0x7fffffff);
 914     __ cmpl(rax, c_rarg1); // NaN? -> 0
 915     __ jcc(Assembler::negative, L);


1306     const Register saved_rdi = r9;
1307     const Register saved_rsi = r10;
1308 #ifdef _WIN64
1309     __ movptr(rdi, saved_rdi);
1310     __ movptr(rsi, saved_rsi);
1311 #endif
1312   }
1313 
1314   // Generate code for an array write pre barrier
1315   //
1316   //     addr    -  starting address
1317   //     count   -  element count
1318   //     tmp     - scratch register
1319   //
1320   //     Destroy no registers!
1321   //
1322   void  gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
1323     BarrierSet* bs = Universe::heap()->barrier_set();
1324     switch (bs->kind()) {
1325       case BarrierSet::G1SATBCTLogging:
1326       case BarrierSet::ShenandoahBarrierSet:
1327         // With G1, don't generate the call if we statically know that the target in uninitialized
1328         if (!dest_uninitialized) {
1329            __ pusha();                      // push registers
1330            if (count == c_rarg0) {
1331              if (addr == c_rarg1) {
1332                // exactly backwards!!
1333                __ xchgptr(c_rarg1, c_rarg0);
1334              } else {
1335                __ movptr(c_rarg1, count);
1336                __ movptr(c_rarg0, addr);
1337              }
1338            } else {
1339              __ movptr(c_rarg0, addr);
1340              __ movptr(c_rarg1, count);
1341            }
1342            __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2);
1343            __ popa();
1344         }
1345          break;
1346       case BarrierSet::CardTableForRS:


1351         ShouldNotReachHere();
1352 
1353     }
1354   }
1355 
1356   //
1357   // Generate code for an array write post barrier
1358   //
1359   //  Input:
1360   //     start    - register containing starting address of destination array
1361   //     count    - elements count
1362   //     scratch  - scratch register
1363   //
1364   //  The input registers are overwritten.
1365   //
1366   void  gen_write_ref_array_post_barrier(Register start, Register count, Register scratch) {
1367     assert_different_registers(start, count, scratch);
1368     BarrierSet* bs = Universe::heap()->barrier_set();
1369     switch (bs->kind()) {
1370       case BarrierSet::G1SATBCTLogging:
1371       case BarrierSet::ShenandoahBarrierSet:
1372         {
1373           __ pusha();             // push registers (overkill)
1374           if (c_rarg0 == count) { // On win64 c_rarg0 == rcx
1375             assert_different_registers(c_rarg1, start);
1376             __ mov(c_rarg1, count);
1377             __ mov(c_rarg0, start);
1378           } else {
1379             assert_different_registers(c_rarg0, count);
1380             __ mov(c_rarg0, start);
1381             __ mov(c_rarg1, count);
1382           }
1383           __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2);
1384           __ popa();
1385         }
1386         break;
1387       case BarrierSet::CardTableForRS:
1388       case BarrierSet::CardTableExtension:
1389         {
1390           CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
1391           assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");


4349     // fabricate a RuntimeStub internally.
4350     StubRoutines::_throw_AbstractMethodError_entry =
4351       generate_throw_exception("AbstractMethodError throw_exception",
4352                                CAST_FROM_FN_PTR(address,
4353                                                 SharedRuntime::
4354                                                 throw_AbstractMethodError));
4355 
4356     StubRoutines::_throw_IncompatibleClassChangeError_entry =
4357       generate_throw_exception("IncompatibleClassChangeError throw_exception",
4358                                CAST_FROM_FN_PTR(address,
4359                                                 SharedRuntime::
4360                                                 throw_IncompatibleClassChangeError));
4361 
4362     StubRoutines::_throw_NullPointerException_at_call_entry =
4363       generate_throw_exception("NullPointerException at call throw_exception",
4364                                CAST_FROM_FN_PTR(address,
4365                                                 SharedRuntime::
4366                                                 throw_NullPointerException_at_call));
4367 
4368     // entry points that are platform specific
4369     if (UseShenandoahGC) {
4370       StubRoutines::x86::_shenandoah_wb = generate_shenandoah_wb();
4371     }
4372     StubRoutines::x86::_f2i_fixup = generate_f2i_fixup();
4373     StubRoutines::x86::_f2l_fixup = generate_f2l_fixup();
4374     StubRoutines::x86::_d2i_fixup = generate_d2i_fixup();
4375     StubRoutines::x86::_d2l_fixup = generate_d2l_fixup();
4376 
4377     StubRoutines::x86::_float_sign_mask  = generate_fp_mask("float_sign_mask",  0x7FFFFFFF7FFFFFFF);
4378     StubRoutines::x86::_float_sign_flip  = generate_fp_mask("float_sign_flip",  0x8000000080000000);
4379     StubRoutines::x86::_double_sign_mask = generate_fp_mask("double_sign_mask", 0x7FFFFFFFFFFFFFFF);
4380     StubRoutines::x86::_double_sign_flip = generate_fp_mask("double_sign_flip", 0x8000000000000000);
4381 
4382     // support for verify_oop (must happen after universe_init)
4383     StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop();
4384 
4385     // arraycopy stubs used by compilers
4386     generate_arraycopy_stubs();
4387 
4388     generate_math_stubs();
4389 
4390     // don't bother generating these AES intrinsic stubs unless global flag is set
4391     if (UseAESIntrinsics) {


< prev index next >