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


  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




  56 
  57 #define __ masm->
  58 
  59 const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size;
  60 
  61 class SimpleRuntimeFrame {
  62 
  63   public:
  64 
  65   // Most of the runtime stubs have this simple frame layout.
  66   // This class exists to make the layout shared in one place.
  67   // Offsets are for compiler stack slots, which are jints.
  68   enum layout {
  69     // The frame sender code expects that rbp will be in the "natural" place and
  70     // will override any oopMap setting for it. We must therefore force the layout
  71     // so that it agrees with the frame sender code.
  72     rbp_off = frame::arg_reg_save_area_bytes/BytesPerInt,
  73     rbp_off2,
  74     return_off, return_off2,
  75     framesize


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


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






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


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








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


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
















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


   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  *


  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 "utilities/macros.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
  57 #if INCLUDE_SHENANDOAHGC
  58 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  59 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  60 #endif
  61 
  62 #define __ masm->
  63 
  64 const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size;
  65 
  66 class SimpleRuntimeFrame {
  67 
  68   public:
  69 
  70   // Most of the runtime stubs have this simple frame layout.
  71   // This class exists to make the layout shared in one place.
  72   // Offsets are for compiler stack slots, which are jints.
  73   enum layout {
  74     // The frame sender code expects that rbp will be in the "natural" place and
  75     // will override any oopMap setting for it. We must therefore force the layout
  76     // so that it agrees with the frame sender code.
  77     rbp_off = frame::arg_reg_save_area_bytes/BytesPerInt,
  78     rbp_off2,
  79     return_off, return_off2,
  80     framesize


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


2175   // All inbound args are referenced based on rbp and all outbound args via rsp.
2176 
2177 
2178 #ifdef ASSERT
2179   bool reg_destroyed[RegisterImpl::number_of_registers];
2180   bool freg_destroyed[XMMRegisterImpl::number_of_registers];
2181   for ( int r = 0 ; r < RegisterImpl::number_of_registers ; r++ ) {
2182     reg_destroyed[r] = false;
2183   }
2184   for ( int f = 0 ; f < XMMRegisterImpl::number_of_registers ; f++ ) {
2185     freg_destroyed[f] = false;
2186   }
2187 
2188 #endif /* ASSERT */
2189 
2190   // This may iterate in two different directions depending on the
2191   // kind of native it is.  The reason is that for regular JNI natives
2192   // the incoming and outgoing registers are offset upwards and for
2193   // critical natives they are offset down.
2194   GrowableArray<int> arg_order(2 * total_in_args);
2195 #if INCLUDE_SHENANDOAHGC
2196   // Inbound arguments that need to be pinned for critical natives
2197   GrowableArray<int> pinned_args(total_in_args);
2198   // Current stack slot for storing register based array argument
2199   int pinned_slot = oop_handle_offset;
2200 #endif
2201   VMRegPair tmp_vmreg;
2202   tmp_vmreg.set2(rbx->as_VMReg());
2203 
2204   if (!is_critical_native) {
2205     for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) {
2206       arg_order.push(i);
2207       arg_order.push(c_arg);
2208     }
2209   } else {
2210     // Compute a valid move order, using tmp_vmreg to break any cycles
2211     ComputeMoveOrder cmo(total_in_args, in_regs, total_c_args, out_regs, in_sig_bt, arg_order, tmp_vmreg);
2212   }
2213 
2214   int temploc = -1;
2215   for (int ai = 0; ai < arg_order.length(); ai += 2) {
2216     int i = arg_order.at(ai);
2217     int c_arg = arg_order.at(ai + 1);
2218     __ block_comment(err_msg("move %d -> %d", i, c_arg));
2219     if (c_arg == -1) {
2220       assert(is_critical_native, "should only be required for critical natives");


2228       // Read from the temporary location
2229       assert(temploc != -1, "must be valid");
2230       i = temploc;
2231       temploc = -1;
2232     }
2233 #ifdef ASSERT
2234     if (in_regs[i].first()->is_Register()) {
2235       assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "destroyed reg!");
2236     } else if (in_regs[i].first()->is_XMMRegister()) {
2237       assert(!freg_destroyed[in_regs[i].first()->as_XMMRegister()->encoding()], "destroyed reg!");
2238     }
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 /* ASSERT */
2245     switch (in_sig_bt[i]) {
2246       case T_ARRAY:
2247         if (is_critical_native) {
2248 #if INCLUDE_SHENANDOAHGC
2249           // pin before unpack
2250           if (UseShenandoahGC) {
2251             assert(pinned_slot <= stack_slots, "overflow");
2252             ShenandoahBarrierSet::assembler()->pin_critical_native_array(masm, in_regs[i], pinned_slot);
2253             pinned_args.append(i);
2254           }
2255 #endif
2256           unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg + 1], out_regs[c_arg]);
2257           c_arg++;
2258 #ifdef ASSERT
2259           if (out_regs[c_arg].first()->is_Register()) {
2260             reg_destroyed[out_regs[c_arg].first()->as_Register()->encoding()] = true;
2261           } else if (out_regs[c_arg].first()->is_XMMRegister()) {
2262             freg_destroyed[out_regs[c_arg].first()->as_XMMRegister()->encoding()] = true;
2263           }
2264 #endif
2265           break;
2266         }
2267       case T_OBJECT:
2268         assert(!is_critical_native, "no oop arguments");
2269         object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg],
2270                     ((i == 0) && (!is_static)),
2271                     &receiver_offset);
2272         break;
2273       case T_VOID:
2274         break;
2275 


2452 
2453   // Unpack native results.
2454   switch (ret_type) {
2455   case T_BOOLEAN: __ c2bool(rax);            break;
2456   case T_CHAR   : __ movzwl(rax, rax);      break;
2457   case T_BYTE   : __ sign_extend_byte (rax); break;
2458   case T_SHORT  : __ sign_extend_short(rax); break;
2459   case T_INT    : /* nothing to do */        break;
2460   case T_DOUBLE :
2461   case T_FLOAT  :
2462     // Result is in xmm0 we'll save as needed
2463     break;
2464   case T_ARRAY:                 // Really a handle
2465   case T_OBJECT:                // Really a handle
2466       break; // can't de-handlize until after safepoint check
2467   case T_VOID: break;
2468   case T_LONG: break;
2469   default       : ShouldNotReachHere();
2470   }
2471 
2472 #if INCLUDE_SHENANDOAHGC
2473   if (UseShenandoahGC) {
2474     // unpin pinned arguments
2475     pinned_slot = oop_handle_offset;
2476     if (pinned_args.length() > 0) {
2477       // save return value that may be overwritten otherwise.
2478       save_native_result(masm, ret_type, stack_slots);
2479       for (int index = 0; index < pinned_args.length(); index ++) {
2480         int i = pinned_args.at(index);
2481         assert(pinned_slot <= stack_slots, "overflow");
2482         ShenandoahBarrierSet::assembler()->unpin_critical_native_array(masm, in_regs[i], pinned_slot);
2483       }
2484       restore_native_result(masm, ret_type, stack_slots);
2485     }
2486   }
2487 #endif
2488   // Switch thread to "native transition" state before reading the synchronization state.
2489   // This additional state is necessary because reading and testing the synchronization
2490   // state is not atomic w.r.t. GC, as this scenario demonstrates:
2491   //     Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted.
2492   //     VM thread changes sync state to synchronizing and suspends threads for GC.
2493   //     Thread A is resumed to finish this native method, but doesn't block here since it
2494   //     didn't see any synchronization is progress, and escapes.
2495   __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native_trans);
2496 
2497   if(os::is_MP()) {
2498     if (UseMembar) {
2499       // Force this write out before the read below
2500       __ membar(Assembler::Membar_mask_bits(
2501            Assembler::LoadLoad | Assembler::LoadStore |
2502            Assembler::StoreLoad | Assembler::StoreStore));
2503     } else {
2504       // Write serialization page so VM thread can do a pseudo remote membar.
2505       // We use the current thread pointer to calculate a thread specific
2506       // offset to write to within the page. This minimizes bus traffic
2507       // due to cache line collision.


< prev index next >