< prev index next >

src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp

Print this page


   1 /*
   2  * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   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 #ifndef _WINDOWS
  27 #include "alloca.h"
  28 #endif
  29 #include "asm/macroAssembler.hpp"
  30 #include "asm/macroAssembler.inline.hpp"
  31 #include "code/debugInfoRec.hpp"
  32 #include "code/icBuffer.hpp"
  33 #include "code/nativeInst.hpp"
  34 #include "code/vtableStubs.hpp"
  35 #include "gc/shared/gcLocker.hpp"

  36 #include "interpreter/interpreter.hpp"
  37 #include "logging/log.hpp"
  38 #include "memory/resourceArea.hpp"
  39 #include "oops/compiledICHolder.hpp"
  40 #include "runtime/safepointMechanism.hpp"
  41 #include "runtime/sharedRuntime.hpp"
  42 #include "runtime/vframeArray.hpp"
  43 #include "utilities/align.hpp"
  44 #include "utilities/formatBuffer.hpp"
  45 #include "vm_version_x86.hpp"
  46 #include "vmreg_x86.inline.hpp"
  47 #ifdef COMPILER1
  48 #include "c1/c1_Runtime1.hpp"
  49 #endif
  50 #ifdef COMPILER2
  51 #include "opto/runtime.hpp"
  52 #endif
  53 #if INCLUDE_JVMCI
  54 #include "jvmci/jvmciJavaClasses.hpp"
  55 #endif


1417     } else if (in_regs[i].first()->is_XMMRegister()) {
1418       if (in_sig_bt[i] == T_FLOAT) {
1419         int offset = slot * VMRegImpl::stack_slot_size;
1420         slot++;
1421         assert(slot <= stack_slots, "overflow");
1422         if (map != NULL) {
1423           __ movflt(Address(rsp, offset), in_regs[i].first()->as_XMMRegister());
1424         } else {
1425           __ movflt(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset));
1426         }
1427       }
1428     } else if (in_regs[i].first()->is_stack()) {
1429       if (in_sig_bt[i] == T_ARRAY && map != NULL) {
1430         int offset_in_older_frame = in_regs[i].first()->reg2stack() + SharedRuntime::out_preserve_stack_slots();
1431         map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + stack_slots));
1432       }
1433     }
1434   }
1435 }
1436 






























































































1437 
1438 // Check GCLocker::needs_gc and enter the runtime if it's true.  This
1439 // keeps a new JNI critical region from starting until a GC has been
1440 // forced.  Save down any oops in registers and describe them in an
1441 // OopMap.
1442 static void check_needs_gc_for_critical_native(MacroAssembler* masm,
1443                                                int stack_slots,
1444                                                int total_c_args,
1445                                                int total_in_args,
1446                                                int arg_save_area,
1447                                                OopMapSet* oop_maps,
1448                                                VMRegPair* in_regs,
1449                                                BasicType* in_sig_bt) {
1450   __ block_comment("check GCLocker::needs_gc");
1451   Label cont;
1452   __ cmp8(ExternalAddress((address)GCLocker::needs_gc_address()), false);
1453   __ jcc(Assembler::equal, cont);
1454 
1455   // Save down any incoming oops and call into the runtime to halt for a GC
1456 


2112     }
2113 
2114 #ifdef ASSERT
2115     {
2116       Label L;
2117       __ mov(rax, rsp);
2118       __ andptr(rax, -16); // must be 16 byte boundary (see amd64 ABI)
2119       __ cmpptr(rax, rsp);
2120       __ jcc(Assembler::equal, L);
2121       __ stop("improperly aligned stack");
2122       __ bind(L);
2123     }
2124 #endif /* ASSERT */
2125 
2126 
2127   // We use r14 as the oop handle for the receiver/klass
2128   // It is callee save so it survives the call to native
2129 
2130   const Register oop_handle_reg = r14;
2131 
2132   if (is_critical_native) {
2133     check_needs_gc_for_critical_native(masm, stack_slots, total_c_args, total_in_args,
2134                                        oop_handle_offset, oop_maps, in_regs, in_sig_bt);
2135   }
2136 
2137   //
2138   // We immediately shuffle the arguments so that any vm call we have to
2139   // make from here on out (sync slow path, jvmti, etc.) we will have
2140   // captured the oops from our caller and have a valid oopMap for
2141   // them.
2142 
2143   // -----------------
2144   // The Grand Shuffle
2145 
2146   // The Java calling convention is either equal (linux) or denser (win64) than the
2147   // c calling convention. However the because of the jni_env argument the c calling
2148   // convention always has at least one more (and two for static) arguments than Java.
2149   // Therefore if we move the args from java -> c backwards then we will never have
2150   // a register->register conflict and we don't have to build a dependency graph
2151   // and figure out how to break any cycles.
2152   //


2169   // All inbound args are referenced based on rbp and all outbound args via rsp.
2170 
2171 
2172 #ifdef ASSERT
2173   bool reg_destroyed[RegisterImpl::number_of_registers];
2174   bool freg_destroyed[XMMRegisterImpl::number_of_registers];
2175   for ( int r = 0 ; r < RegisterImpl::number_of_registers ; r++ ) {
2176     reg_destroyed[r] = false;
2177   }
2178   for ( int f = 0 ; f < XMMRegisterImpl::number_of_registers ; f++ ) {
2179     freg_destroyed[f] = false;
2180   }
2181 
2182 #endif /* ASSERT */
2183 
2184   // This may iterate in two different directions depending on the
2185   // kind of native it is.  The reason is that for regular JNI natives
2186   // the incoming and outgoing registers are offset upwards and for
2187   // critical natives they are offset down.
2188   GrowableArray<int> arg_order(2 * total_in_args);





2189   VMRegPair tmp_vmreg;
2190   tmp_vmreg.set2(rbx->as_VMReg());
2191 
2192   if (!is_critical_native) {
2193     for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) {
2194       arg_order.push(i);
2195       arg_order.push(c_arg);
2196     }
2197   } else {
2198     // Compute a valid move order, using tmp_vmreg to break any cycles
2199     ComputeMoveOrder cmo(total_in_args, in_regs, total_c_args, out_regs, in_sig_bt, arg_order, tmp_vmreg);
2200   }
2201 
2202   int temploc = -1;
2203   for (int ai = 0; ai < arg_order.length(); ai += 2) {
2204     int i = arg_order.at(ai);
2205     int c_arg = arg_order.at(ai + 1);
2206     __ block_comment(err_msg("move %d -> %d", i, c_arg));
2207     if (c_arg == -1) {
2208       assert(is_critical_native, "should only be required for critical natives");


2216       // Read from the temporary location
2217       assert(temploc != -1, "must be valid");
2218       i = temploc;
2219       temploc = -1;
2220     }
2221 #ifdef ASSERT
2222     if (in_regs[i].first()->is_Register()) {
2223       assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "destroyed reg!");
2224     } else if (in_regs[i].first()->is_XMMRegister()) {
2225       assert(!freg_destroyed[in_regs[i].first()->as_XMMRegister()->encoding()], "destroyed reg!");
2226     }
2227     if (out_regs[c_arg].first()->is_Register()) {
2228       reg_destroyed[out_regs[c_arg].first()->as_Register()->encoding()] = true;
2229     } else if (out_regs[c_arg].first()->is_XMMRegister()) {
2230       freg_destroyed[out_regs[c_arg].first()->as_XMMRegister()->encoding()] = true;
2231     }
2232 #endif /* ASSERT */
2233     switch (in_sig_bt[i]) {
2234       case T_ARRAY:
2235         if (is_critical_native) {






2236           unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg + 1], out_regs[c_arg]);
2237           c_arg++;
2238 #ifdef ASSERT
2239           if (out_regs[c_arg].first()->is_Register()) {
2240             reg_destroyed[out_regs[c_arg].first()->as_Register()->encoding()] = true;
2241           } else if (out_regs[c_arg].first()->is_XMMRegister()) {
2242             freg_destroyed[out_regs[c_arg].first()->as_XMMRegister()->encoding()] = true;
2243           }
2244 #endif
2245           break;
2246         }
2247       case T_OBJECT:
2248         assert(!is_critical_native, "no oop arguments");
2249         object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg],
2250                     ((i == 0) && (!is_static)),
2251                     &receiver_offset);
2252         break;
2253       case T_VOID:
2254         break;
2255 


2352 
2353   Label slow_path_lock;
2354   Label lock_done;
2355 
2356   if (method->is_synchronized()) {
2357     assert(!is_critical_native, "unhandled");
2358 
2359 
2360     const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes();
2361 
2362     // Get the handle (the 2nd argument)
2363     __ mov(oop_handle_reg, c_rarg1);
2364 
2365     // Get address of the box
2366 
2367     __ lea(lock_reg, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size));
2368 
2369     // Load the oop from the handle
2370     __ movptr(obj_reg, Address(oop_handle_reg, 0));
2371 

2372     if (UseBiasedLocking) {
2373       __ biased_locking_enter(lock_reg, obj_reg, swap_reg, rscratch1, false, lock_done, &slow_path_lock);
2374     }
2375 
2376     // Load immediate 1 into swap_reg %rax
2377     __ movl(swap_reg, 1);
2378 
2379     // Load (object->mark() | 1) into swap_reg %rax
2380     __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
2381 
2382     // Save (object->mark() | 1) into BasicLock's displaced header
2383     __ movptr(Address(lock_reg, mark_word_offset), swap_reg);
2384 
2385     if (os::is_MP()) {
2386       __ lock();
2387     }
2388 
2389     // src -> dest iff dest == rax else rax <- dest
2390     __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
2391     __ jcc(Assembler::equal, lock_done);


2432 
2433   // Unpack native results.
2434   switch (ret_type) {
2435   case T_BOOLEAN: __ c2bool(rax);            break;
2436   case T_CHAR   : __ movzwl(rax, rax);      break;
2437   case T_BYTE   : __ sign_extend_byte (rax); break;
2438   case T_SHORT  : __ sign_extend_short(rax); break;
2439   case T_INT    : /* nothing to do */        break;
2440   case T_DOUBLE :
2441   case T_FLOAT  :
2442     // Result is in xmm0 we'll save as needed
2443     break;
2444   case T_ARRAY:                 // Really a handle
2445   case T_OBJECT:                // Really a handle
2446       break; // can't de-handlize until after safepoint check
2447   case T_VOID: break;
2448   case T_LONG: break;
2449   default       : ShouldNotReachHere();
2450   }
2451 













2452   // Switch thread to "native transition" state before reading the synchronization state.
2453   // This additional state is necessary because reading and testing the synchronization
2454   // state is not atomic w.r.t. GC, as this scenario demonstrates:
2455   //     Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted.
2456   //     VM thread changes sync state to synchronizing and suspends threads for GC.
2457   //     Thread A is resumed to finish this native method, but doesn't block here since it
2458   //     didn't see any synchronization is progress, and escapes.
2459   __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native_trans);
2460 
2461   if(os::is_MP()) {
2462     if (UseMembar) {
2463       // Force this write out before the read below
2464       __ membar(Assembler::Membar_mask_bits(
2465            Assembler::LoadLoad | Assembler::LoadStore |
2466            Assembler::StoreLoad | Assembler::StoreStore));
2467     } else {
2468       // Write serialization page so VM thread can do a pseudo remote membar.
2469       // We use the current thread pointer to calculate a thread specific
2470       // offset to write to within the page. This minimizes bus traffic
2471       // due to cache line collision.


2519 
2520   // change thread state
2521   __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_Java);
2522   __ bind(after_transition);
2523 
2524   Label reguard;
2525   Label reguard_done;
2526   __ cmpl(Address(r15_thread, JavaThread::stack_guard_state_offset()), JavaThread::stack_guard_yellow_reserved_disabled);
2527   __ jcc(Assembler::equal, reguard);
2528   __ bind(reguard_done);
2529 
2530   // native result if any is live
2531 
2532   // Unlock
2533   Label unlock_done;
2534   Label slow_path_unlock;
2535   if (method->is_synchronized()) {
2536 
2537     // Get locked oop from the handle we passed to jni
2538     __ movptr(obj_reg, Address(oop_handle_reg, 0));

2539 
2540     Label done;
2541 
2542     if (UseBiasedLocking) {
2543       __ biased_locking_exit(obj_reg, old_hdr, done);
2544     }
2545 
2546     // Simple recursive lock?
2547 
2548     __ cmpptr(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), (int32_t)NULL_WORD);
2549     __ jcc(Assembler::equal, done);
2550 
2551     // Must save rax if if it is live now because cmpxchg must use it
2552     if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) {
2553       save_native_result(masm, ret_type, stack_slots);
2554     }
2555 
2556 
2557     // get address of the stack lock
2558     __ lea(rax, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size));


   1 /*
   2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   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 #ifndef _WINDOWS
  27 #include "alloca.h"
  28 #endif
  29 #include "asm/macroAssembler.hpp"
  30 #include "asm/macroAssembler.inline.hpp"
  31 #include "code/debugInfoRec.hpp"
  32 #include "code/icBuffer.hpp"
  33 #include "code/nativeInst.hpp"
  34 #include "code/vtableStubs.hpp"
  35 #include "gc/shared/gcLocker.hpp"
  36 #include "gc/shared/collectedHeap.hpp"
  37 #include "interpreter/interpreter.hpp"
  38 #include "logging/log.hpp"
  39 #include "memory/resourceArea.hpp"
  40 #include "oops/compiledICHolder.hpp"
  41 #include "runtime/safepointMechanism.hpp"
  42 #include "runtime/sharedRuntime.hpp"
  43 #include "runtime/vframeArray.hpp"
  44 #include "utilities/align.hpp"
  45 #include "utilities/formatBuffer.hpp"
  46 #include "vm_version_x86.hpp"
  47 #include "vmreg_x86.inline.hpp"
  48 #ifdef COMPILER1
  49 #include "c1/c1_Runtime1.hpp"
  50 #endif
  51 #ifdef COMPILER2
  52 #include "opto/runtime.hpp"
  53 #endif
  54 #if INCLUDE_JVMCI
  55 #include "jvmci/jvmciJavaClasses.hpp"
  56 #endif


1418     } else if (in_regs[i].first()->is_XMMRegister()) {
1419       if (in_sig_bt[i] == T_FLOAT) {
1420         int offset = slot * VMRegImpl::stack_slot_size;
1421         slot++;
1422         assert(slot <= stack_slots, "overflow");
1423         if (map != NULL) {
1424           __ movflt(Address(rsp, offset), in_regs[i].first()->as_XMMRegister());
1425         } else {
1426           __ movflt(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset));
1427         }
1428       }
1429     } else if (in_regs[i].first()->is_stack()) {
1430       if (in_sig_bt[i] == T_ARRAY && map != NULL) {
1431         int offset_in_older_frame = in_regs[i].first()->reg2stack() + SharedRuntime::out_preserve_stack_slots();
1432         map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + stack_slots));
1433       }
1434     }
1435   }
1436 }
1437 
1438 // Pin incoming array argument of java critical method
1439 static void pin_critical_native_array(MacroAssembler* masm,
1440                                       VMRegPair reg,
1441                                       int& pinned_slot) {
1442   __ block_comment("pin_critical_native_array {");
1443   Register tmp_reg = rax;
1444 
1445   Label is_null;
1446   VMRegPair tmp;
1447   VMRegPair in_reg = reg;
1448   bool on_stack = false;
1449 
1450   tmp.set_ptr(tmp_reg->as_VMReg());
1451   if (reg.first()->is_stack()) {
1452     // Load the arg up from the stack
1453     move_ptr(masm, reg, tmp);
1454     reg = tmp;
1455     on_stack = true;
1456   } else {
1457     __ movptr(rax, reg.first()->as_Register());
1458   }
1459   __ testptr(reg.first()->as_Register(), reg.first()->as_Register());
1460   __ jccb(Assembler::equal, is_null);
1461 
1462   __ push(c_rarg0);
1463   __ push(c_rarg1);
1464   __ push(c_rarg2);
1465   __ push(c_rarg3);
1466 #ifdef _WIN64
1467   // caller-saved registers on Windows
1468   __ push(r10);
1469   __ push(r11);
1470 #else
1471   __ push(c_rarg4);
1472   __ push(c_rarg5);
1473 #endif
1474 
1475   if (reg.first()->as_Register() != c_rarg1) {
1476     __ movptr(c_rarg1, reg.first()->as_Register());
1477   }
1478   __ movptr(c_rarg0, r15_thread);
1479   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::pin_object)));
1480 
1481 #ifdef _WIN64
1482   __ pop(r11);
1483   __ pop(r10);
1484 #else
1485   __ pop(c_rarg5);
1486   __ pop(c_rarg4);
1487 #endif
1488   __ pop(c_rarg3);
1489   __ pop(c_rarg2);
1490   __ pop(c_rarg1);
1491   __ pop(c_rarg0);
1492 
1493   if (on_stack) {
1494     __ movptr(Address(rbp, reg2offset_in(in_reg.first())), rax);
1495     __ bind(is_null);
1496   } else {
1497     __ movptr(reg.first()->as_Register(), rax);
1498 
1499     // save on stack for unpinning later
1500     __ bind(is_null);
1501     assert(reg.first()->is_Register(), "Must be a register");
1502     int offset = pinned_slot * VMRegImpl::stack_slot_size;
1503     pinned_slot += VMRegImpl::slots_per_word;
1504     __ movq(Address(rsp, offset), rax);
1505   }
1506   __ block_comment("} pin_critical_native_array");
1507 }
1508 
1509 // Unpin array argument of java critical method
1510 static void unpin_critical_native_array(MacroAssembler* masm,
1511                                         VMRegPair reg,
1512                                         int& pinned_slot) {
1513   __ block_comment("unpin_critical_native_array {");
1514   Label is_null;
1515 
1516   if (reg.first()->is_stack()) {
1517     __ movptr(c_rarg1, Address(rbp, reg2offset_in(reg.first())));
1518   } else {
1519     int offset = pinned_slot * VMRegImpl::stack_slot_size;
1520     pinned_slot += VMRegImpl::slots_per_word;
1521     __ movq(c_rarg1, Address(rsp, offset));
1522   }
1523   __ testptr(c_rarg1, c_rarg1);
1524   __ jccb(Assembler::equal, is_null);
1525 
1526   __ movptr(c_rarg0, r15_thread);
1527   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::unpin_object)));
1528 
1529   __ bind(is_null);
1530   __ block_comment("} unpin_critical_native_array");
1531 }
1532 
1533 // Check GCLocker::needs_gc and enter the runtime if it's true.  This
1534 // keeps a new JNI critical region from starting until a GC has been
1535 // forced.  Save down any oops in registers and describe them in an
1536 // OopMap.
1537 static void check_needs_gc_for_critical_native(MacroAssembler* masm,
1538                                                int stack_slots,
1539                                                int total_c_args,
1540                                                int total_in_args,
1541                                                int arg_save_area,
1542                                                OopMapSet* oop_maps,
1543                                                VMRegPair* in_regs,
1544                                                BasicType* in_sig_bt) {
1545   __ block_comment("check GCLocker::needs_gc");
1546   Label cont;
1547   __ cmp8(ExternalAddress((address)GCLocker::needs_gc_address()), false);
1548   __ jcc(Assembler::equal, cont);
1549 
1550   // Save down any incoming oops and call into the runtime to halt for a GC
1551 


2207     }
2208 
2209 #ifdef ASSERT
2210     {
2211       Label L;
2212       __ mov(rax, rsp);
2213       __ andptr(rax, -16); // must be 16 byte boundary (see amd64 ABI)
2214       __ cmpptr(rax, rsp);
2215       __ jcc(Assembler::equal, L);
2216       __ stop("improperly aligned stack");
2217       __ bind(L);
2218     }
2219 #endif /* ASSERT */
2220 
2221 
2222   // We use r14 as the oop handle for the receiver/klass
2223   // It is callee save so it survives the call to native
2224 
2225   const Register oop_handle_reg = r14;
2226 
2227   if (is_critical_native && !Universe::heap()->supports_object_pinning()) {
2228     check_needs_gc_for_critical_native(masm, stack_slots, total_c_args, total_in_args,
2229                                        oop_handle_offset, oop_maps, in_regs, in_sig_bt);
2230   }
2231 
2232   //
2233   // We immediately shuffle the arguments so that any vm call we have to
2234   // make from here on out (sync slow path, jvmti, etc.) we will have
2235   // captured the oops from our caller and have a valid oopMap for
2236   // them.
2237 
2238   // -----------------
2239   // The Grand Shuffle
2240 
2241   // The Java calling convention is either equal (linux) or denser (win64) than the
2242   // c calling convention. However the because of the jni_env argument the c calling
2243   // convention always has at least one more (and two for static) arguments than Java.
2244   // Therefore if we move the args from java -> c backwards then we will never have
2245   // a register->register conflict and we don't have to build a dependency graph
2246   // and figure out how to break any cycles.
2247   //


2264   // All inbound args are referenced based on rbp and all outbound args via rsp.
2265 
2266 
2267 #ifdef ASSERT
2268   bool reg_destroyed[RegisterImpl::number_of_registers];
2269   bool freg_destroyed[XMMRegisterImpl::number_of_registers];
2270   for ( int r = 0 ; r < RegisterImpl::number_of_registers ; r++ ) {
2271     reg_destroyed[r] = false;
2272   }
2273   for ( int f = 0 ; f < XMMRegisterImpl::number_of_registers ; f++ ) {
2274     freg_destroyed[f] = false;
2275   }
2276 
2277 #endif /* ASSERT */
2278 
2279   // This may iterate in two different directions depending on the
2280   // kind of native it is.  The reason is that for regular JNI natives
2281   // the incoming and outgoing registers are offset upwards and for
2282   // critical natives they are offset down.
2283   GrowableArray<int> arg_order(2 * total_in_args);
2284   // Inbound arguments that need to be pinned for critical natives
2285   GrowableArray<int> pinned_args(total_in_args);
2286   // Current stack slot for storing register based array argument
2287   int pinned_slot = oop_handle_offset;
2288 
2289   VMRegPair tmp_vmreg;
2290   tmp_vmreg.set2(rbx->as_VMReg());
2291 
2292   if (!is_critical_native) {
2293     for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) {
2294       arg_order.push(i);
2295       arg_order.push(c_arg);
2296     }
2297   } else {
2298     // Compute a valid move order, using tmp_vmreg to break any cycles
2299     ComputeMoveOrder cmo(total_in_args, in_regs, total_c_args, out_regs, in_sig_bt, arg_order, tmp_vmreg);
2300   }
2301 
2302   int temploc = -1;
2303   for (int ai = 0; ai < arg_order.length(); ai += 2) {
2304     int i = arg_order.at(ai);
2305     int c_arg = arg_order.at(ai + 1);
2306     __ block_comment(err_msg("move %d -> %d", i, c_arg));
2307     if (c_arg == -1) {
2308       assert(is_critical_native, "should only be required for critical natives");


2316       // Read from the temporary location
2317       assert(temploc != -1, "must be valid");
2318       i = temploc;
2319       temploc = -1;
2320     }
2321 #ifdef ASSERT
2322     if (in_regs[i].first()->is_Register()) {
2323       assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "destroyed reg!");
2324     } else if (in_regs[i].first()->is_XMMRegister()) {
2325       assert(!freg_destroyed[in_regs[i].first()->as_XMMRegister()->encoding()], "destroyed reg!");
2326     }
2327     if (out_regs[c_arg].first()->is_Register()) {
2328       reg_destroyed[out_regs[c_arg].first()->as_Register()->encoding()] = true;
2329     } else if (out_regs[c_arg].first()->is_XMMRegister()) {
2330       freg_destroyed[out_regs[c_arg].first()->as_XMMRegister()->encoding()] = true;
2331     }
2332 #endif /* ASSERT */
2333     switch (in_sig_bt[i]) {
2334       case T_ARRAY:
2335         if (is_critical_native) {
2336           // pin before unpack
2337           if (Universe::heap()->supports_object_pinning()) {
2338             assert(pinned_slot <= stack_slots, "overflow");
2339             pin_critical_native_array(masm, in_regs[i], pinned_slot);
2340             pinned_args.append(i);
2341           }
2342           unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg + 1], out_regs[c_arg]);
2343           c_arg++;
2344 #ifdef ASSERT
2345           if (out_regs[c_arg].first()->is_Register()) {
2346             reg_destroyed[out_regs[c_arg].first()->as_Register()->encoding()] = true;
2347           } else if (out_regs[c_arg].first()->is_XMMRegister()) {
2348             freg_destroyed[out_regs[c_arg].first()->as_XMMRegister()->encoding()] = true;
2349           }
2350 #endif
2351           break;
2352         }
2353       case T_OBJECT:
2354         assert(!is_critical_native, "no oop arguments");
2355         object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg],
2356                     ((i == 0) && (!is_static)),
2357                     &receiver_offset);
2358         break;
2359       case T_VOID:
2360         break;
2361 


2458 
2459   Label slow_path_lock;
2460   Label lock_done;
2461 
2462   if (method->is_synchronized()) {
2463     assert(!is_critical_native, "unhandled");
2464 
2465 
2466     const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes();
2467 
2468     // Get the handle (the 2nd argument)
2469     __ mov(oop_handle_reg, c_rarg1);
2470 
2471     // Get address of the box
2472 
2473     __ lea(lock_reg, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size));
2474 
2475     // Load the oop from the handle
2476     __ movptr(obj_reg, Address(oop_handle_reg, 0));
2477 
2478     __ resolve_for_write(IS_NOT_NULL, obj_reg);
2479     if (UseBiasedLocking) {
2480       __ biased_locking_enter(lock_reg, obj_reg, swap_reg, rscratch1, false, lock_done, &slow_path_lock);
2481     }
2482 
2483     // Load immediate 1 into swap_reg %rax
2484     __ movl(swap_reg, 1);
2485 
2486     // Load (object->mark() | 1) into swap_reg %rax
2487     __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
2488 
2489     // Save (object->mark() | 1) into BasicLock's displaced header
2490     __ movptr(Address(lock_reg, mark_word_offset), swap_reg);
2491 
2492     if (os::is_MP()) {
2493       __ lock();
2494     }
2495 
2496     // src -> dest iff dest == rax else rax <- dest
2497     __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
2498     __ jcc(Assembler::equal, lock_done);


2539 
2540   // Unpack native results.
2541   switch (ret_type) {
2542   case T_BOOLEAN: __ c2bool(rax);            break;
2543   case T_CHAR   : __ movzwl(rax, rax);      break;
2544   case T_BYTE   : __ sign_extend_byte (rax); break;
2545   case T_SHORT  : __ sign_extend_short(rax); break;
2546   case T_INT    : /* nothing to do */        break;
2547   case T_DOUBLE :
2548   case T_FLOAT  :
2549     // Result is in xmm0 we'll save as needed
2550     break;
2551   case T_ARRAY:                 // Really a handle
2552   case T_OBJECT:                // Really a handle
2553       break; // can't de-handlize until after safepoint check
2554   case T_VOID: break;
2555   case T_LONG: break;
2556   default       : ShouldNotReachHere();
2557   }
2558 
2559   // unpin pinned arguments
2560   pinned_slot = oop_handle_offset;
2561   if (pinned_args.length() > 0) {
2562     // save return value that may be overwritten otherwise.
2563     save_native_result(masm, ret_type, stack_slots);
2564     for (int index = 0; index < pinned_args.length(); index ++) {
2565       int i = pinned_args.at(index);
2566       assert(pinned_slot <= stack_slots, "overflow");
2567       unpin_critical_native_array(masm, in_regs[i], pinned_slot);
2568     }
2569     restore_native_result(masm, ret_type, stack_slots);
2570   }
2571 
2572   // Switch thread to "native transition" state before reading the synchronization state.
2573   // This additional state is necessary because reading and testing the synchronization
2574   // state is not atomic w.r.t. GC, as this scenario demonstrates:
2575   //     Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted.
2576   //     VM thread changes sync state to synchronizing and suspends threads for GC.
2577   //     Thread A is resumed to finish this native method, but doesn't block here since it
2578   //     didn't see any synchronization is progress, and escapes.
2579   __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native_trans);
2580 
2581   if(os::is_MP()) {
2582     if (UseMembar) {
2583       // Force this write out before the read below
2584       __ membar(Assembler::Membar_mask_bits(
2585            Assembler::LoadLoad | Assembler::LoadStore |
2586            Assembler::StoreLoad | Assembler::StoreStore));
2587     } else {
2588       // Write serialization page so VM thread can do a pseudo remote membar.
2589       // We use the current thread pointer to calculate a thread specific
2590       // offset to write to within the page. This minimizes bus traffic
2591       // due to cache line collision.


2639 
2640   // change thread state
2641   __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_Java);
2642   __ bind(after_transition);
2643 
2644   Label reguard;
2645   Label reguard_done;
2646   __ cmpl(Address(r15_thread, JavaThread::stack_guard_state_offset()), JavaThread::stack_guard_yellow_reserved_disabled);
2647   __ jcc(Assembler::equal, reguard);
2648   __ bind(reguard_done);
2649 
2650   // native result if any is live
2651 
2652   // Unlock
2653   Label unlock_done;
2654   Label slow_path_unlock;
2655   if (method->is_synchronized()) {
2656 
2657     // Get locked oop from the handle we passed to jni
2658     __ movptr(obj_reg, Address(oop_handle_reg, 0));
2659     __ resolve_for_write(IS_NOT_NULL, obj_reg);
2660 
2661     Label done;
2662 
2663     if (UseBiasedLocking) {
2664       __ biased_locking_exit(obj_reg, old_hdr, done);
2665     }
2666 
2667     // Simple recursive lock?
2668 
2669     __ cmpptr(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), (int32_t)NULL_WORD);
2670     __ jcc(Assembler::equal, done);
2671 
2672     // Must save rax if if it is live now because cmpxchg must use it
2673     if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) {
2674       save_native_result(masm, ret_type, stack_slots);
2675     }
2676 
2677 
2678     // get address of the stack lock
2679     __ lea(rax, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size));


< prev index next >