< prev index next >

src/hotspot/cpu/aarch64/universalNativeInvoker_aarch64.cpp

Print this page

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




 28 #include "memory/resourceArea.hpp"
 29 #include "prims/universalNativeInvoker.hpp"

 30 
 31 #define __ _masm->
 32 
 33 void ProgrammableInvoker::Generator::generate() {
 34   __ enter();



 35 
 36   // Name registers used in the stub code. These are all caller-save so
 37   // may be clobbered by the call to the native function. Avoid using
 38   // rscratch1 here as it's r8 which is the indirect result register in
 39   // the standard ABI.
 40   Register Rctx = r10, Rstack_size = r11;
 41   Register Rwords = r12, Rtmp = r13;
 42   Register Rsrc_ptr = r14, Rdst_ptr = r15;
 43 
 44   assert_different_registers(Rctx, Rstack_size, rscratch1, rscratch2);
 45 
 46   // TODO: if the callee is not using the standard C ABI then we need to
 47   //       preserve more registers here.






















 48 
 49   __ block_comment("init_and_alloc_stack");
 50 
 51   __ mov(Rctx, c_rarg0);
 52   __ str(Rctx, Address(__ pre(sp, -2 * wordSize)));

 53 
 54   assert(_abi->_stack_alignment_bytes % 16 == 0, "stack must be 16 byte aligned");


 55 
 56   __ block_comment("allocate_stack");
 57   __ ldr(Rstack_size, Address(Rctx, (int) _layout->stack_args_bytes));
 58   __ add(rscratch2, Rstack_size, _abi->_stack_alignment_bytes - 1);
 59   __ andr(rscratch2, rscratch2, -_abi->_stack_alignment_bytes);
 60   __ sub(sp, sp, rscratch2);
 61 
 62   __ block_comment("load_arguments");
 63 
 64   __ ldr(Rsrc_ptr, Address(Rctx, (int) _layout->stack_args));
 65   __ lsr(Rwords, Rstack_size, LogBytesPerWord);
 66   __ mov(Rdst_ptr, sp);









 67 
 68   Label Ldone, Lnext;
 69   __ bind(Lnext);
 70   __ cbz(Rwords, Ldone);
 71   __ ldr(Rtmp, __ post(Rsrc_ptr, wordSize));
 72   __ str(Rtmp, __ post(Rdst_ptr, wordSize));
 73   __ sub(Rwords, Rwords, 1);
 74   __ b(Lnext);
 75   __ bind(Ldone);
 76 
 77   for (int i = 0; i < _abi->_vector_argument_registers.length(); i++) {
 78     ssize_t offs = _layout->arguments_vector + i * float_reg_size;
 79     __ ldrq(_abi->_vector_argument_registers.at(i), Address(Rctx, offs));
 80   }
 81 
 82   for (int i = 0; i < _abi->_integer_argument_registers.length(); i++) {
 83     ssize_t offs = _layout->arguments_integer + i * sizeof(uintptr_t);
 84     __ ldr(_abi->_integer_argument_registers.at(i), Address(Rctx, offs));



























 85   }

 86 
 87   assert(_abi->_shadow_space_bytes == 0, "shadow space not supported on AArch64");





 88 
 89   // call target function
 90   __ block_comment("call target function");
 91   __ ldr(rscratch2, Address(Rctx, (int) _layout->arguments_next_pc));
 92   __ blr(rscratch2);

 93 
 94   __ ldr(Rctx, Address(rfp, -2 * wordSize));   // Might have clobbered Rctx

 95 
 96   __ block_comment("store_registers");






 97 
 98   for (int i = 0; i < _abi->_integer_return_registers.length(); i++) {
 99     ssize_t offs = _layout->returns_integer + i * sizeof(uintptr_t);
100     __ str(_abi->_integer_return_registers.at(i), Address(Rctx, offs));


























101   }




102 
103   for (int i = 0; i < _abi->_vector_return_registers.length(); i++) {
104     ssize_t offs = _layout->returns_vector + i * float_reg_size;
105     __ strq(_abi->_vector_return_registers.at(i), Address(Rctx, offs));





























106   }
107 
108   __ leave();


































109   __ ret(lr);
110 
111   __ flush();
112 }







113 
114 address ProgrammableInvoker::generate_adapter(jobject jabi, jobject jlayout) {
115   ResourceMark rm;
116   const ABIDescriptor abi = ForeignGlobals::parse_abi_descriptor(jabi);
117   const BufferLayout layout = ForeignGlobals::parse_buffer_layout(jlayout);
118 
119   BufferBlob* _invoke_native_blob = BufferBlob::create("invoke_native_blob", native_invoker_size);














120 
121   CodeBuffer code2(_invoke_native_blob);
122   ProgrammableInvoker::Generator g2(&code2, &abi, &layout);
123   g2.generate();
124   code2.log_section_sizes("InvokeNativeBlob");
125 
126   return _invoke_native_blob->code_begin();










127 }

  8  * published by the Free Software Foundation.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  */
 24 
 25 #include "precompiled.hpp"
 26 #include "asm/macroAssembler.hpp"
 27 #include "code/codeBlob.hpp"
 28 #include "code/codeCache.hpp"
 29 #include "code/vmreg.inline.hpp"
 30 #include "compiler/oopMap.hpp"
 31 #include "logging/logStream.hpp"
 32 #include "memory/resourceArea.hpp"
 33 #include "prims/universalNativeInvoker.hpp"
 34 #include "runtime/stubCodeGenerator.hpp"
 35 
 36 #define __ _masm->
 37 
 38 class NativeInvokerGenerator : public StubCodeGenerator {
 39   BasicType* _signature;
 40   int _num_args;
 41   BasicType _ret_bt;
 42   const ABIDescriptor& _abi;
 43 
 44   const GrowableArray<VMReg>& _input_registers;
 45   const GrowableArray<VMReg>& _output_registers;





 46 
 47   bool _needs_return_buffer;
 48 
 49   int _frame_complete;
 50   int _framesize;
 51   OopMapSet* _oop_maps;
 52 public:
 53   NativeInvokerGenerator(CodeBuffer* buffer,
 54                          BasicType* signature,
 55                          int num_args,
 56                          BasicType ret_bt,
 57                          const ABIDescriptor& abi,
 58                          const GrowableArray<VMReg>& input_registers,
 59                          const GrowableArray<VMReg>& output_registers,
 60                          bool needs_return_buffer)
 61    : StubCodeGenerator(buffer, PrintMethodHandleStubs),
 62      _signature(signature),
 63      _num_args(num_args),
 64      _ret_bt(ret_bt),
 65      _abi(abi),
 66      _input_registers(input_registers),
 67      _output_registers(output_registers),
 68      _needs_return_buffer(needs_return_buffer),
 69      _frame_complete(0),
 70      _framesize(0),
 71      _oop_maps(NULL) {
 72   }
 73 
 74   void generate();
 75 
 76   int frame_complete() const {
 77     return _frame_complete;
 78   }
 79 
 80   int framesize() const {
 81     return (_framesize >> (LogBytesPerWord - LogBytesPerInt));
 82   }
 83 
 84   OopMapSet* oop_maps() const {
 85     return _oop_maps;
 86   }
 87 };

 88 
 89 static const int native_invoker_code_size = 1024;
 90 
 91 RuntimeStub* ProgrammableInvoker::make_native_invoker(BasicType* signature,
 92                                                       int num_args,
 93                                                       BasicType ret_bt,
 94                                                       const ABIDescriptor& abi,
 95                                                       const GrowableArray<VMReg>& input_registers,
 96                                                       const GrowableArray<VMReg>& output_registers,
 97                                                       bool needs_return_buffer) {
 98   int locs_size  = 64;
 99   CodeBuffer code("nep_invoker_blob", native_invoker_code_size, locs_size);
100   NativeInvokerGenerator g(&code, signature, num_args, ret_bt, abi, input_registers, output_registers, needs_return_buffer);
101   g.generate();
102   code.log_section_sizes("nep_invoker_blob");
103 
104   RuntimeStub* stub =
105     RuntimeStub::new_runtime_stub("nep_invoker_blob",
106                                   &code,
107                                   g.frame_complete(),
108                                   g.framesize(),
109                                   g.oop_maps(), false);


110 
111   if (TraceNativeInvokers) {
112     stub->print_on(tty);

113   }
114 
115   return stub;
116 }
117 
118 void NativeInvokerGenerator::generate() {
119   enum layout {
120     rfp_off,
121     rfp_off2,
122     lr_off,
123     lr_off2,
124     framesize // inclusive of return address
125     // The following are also computed dynamically:
126     // spill area for return value
127     // out arg area (e.g. for stack args)
128   };
129 
130   // we can't use rscratch1 because it is r8, and used by the ABI
131   Register tmp1 = r9;
132   Register tmp2 = r10;
133 
134   Register shuffle_reg = r19;
135   JavaCallConv in_conv;
136   NativeCallConv out_conv(_input_registers);
137   ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg->as_VMReg());
138 
139 #ifdef ASSERT
140   LogTarget(Trace, panama) lt;
141   if (lt.is_enabled()) {
142     ResourceMark rm;
143     LogStream ls(lt);
144     arg_shuffle.print_on(&ls);
145   }
146 #endif
147 
148   int allocated_frame_size = 0;
149   if (_needs_return_buffer) {
150     allocated_frame_size += 8; // for address spill
151   }
152   allocated_frame_size += arg_shuffle.out_arg_stack_slots() <<LogBytesPerInt;
153   assert(_abi._shadow_space_bytes == 0, "not expecting shadow space on AArch64");
154 
155   int ret_buf_addr_sp_offset = -1;
156   if (_needs_return_buffer) {
157      // in sync with the above
158      ret_buf_addr_sp_offset = allocated_frame_size - 8;
159   }
160 
161   RegSpiller out_reg_spiller(_output_registers);
162   int spill_offset = -1;
163 
164   if (!_needs_return_buffer) {
165     spill_offset = 0;
166     // spill area can be shared with the above, so we take the max of the 2
167     allocated_frame_size = out_reg_spiller.spill_size_bytes() > allocated_frame_size
168       ? out_reg_spiller.spill_size_bytes()
169       : allocated_frame_size;
170   }
171 
172   _framesize = align_up(framesize
173     + (allocated_frame_size >> LogBytesPerInt), 4);
174   assert(is_even(_framesize/2), "sp not 16-byte aligned");
175 
176   _oop_maps  = new OopMapSet();
177   address start = __ pc();
178 
179   __ enter();
180 
181   // lr and fp are already in place
182   __ sub(sp, rfp, ((unsigned)_framesize-4) << LogBytesPerInt); // prolog
183 
184   _frame_complete = __ pc() - start;
185 
186   address the_pc = __ pc();
187   __ set_last_Java_frame(sp, rfp, the_pc, tmp1);
188   OopMap* map = new OopMap(_framesize, 0);
189   _oop_maps->add_gc_map(the_pc - start, map);
190 
191   // State transition
192   __ mov(tmp1, _thread_in_native);
193   __ lea(tmp2, Address(rthread, JavaThread::thread_state_offset()));
194   __ stlrw(tmp1, tmp2);
195 
196   __ block_comment("{ argument shuffle");
197   arg_shuffle.generate(_masm, shuffle_reg->as_VMReg(), 0, _abi._shadow_space_bytes);
198   if (_needs_return_buffer) {
199     assert(ret_buf_addr_sp_offset != -1, "no return buffer addr spill");
200     __ str(_abi._ret_buf_addr_reg, Address(sp, ret_buf_addr_sp_offset));
201   }
202   __ block_comment("} argument shuffle");
203 
204   __ blr(_abi._target_addr_reg);
205   // this call is assumed not to have killed rthread
206 
207   if (!_needs_return_buffer) {
208     // Unpack native results.
209     switch (_ret_bt) {
210       case T_BOOLEAN: __ c2bool(r0);                     break;
211       case T_CHAR   : __ ubfx(r0, r0, 0, 16);            break;
212       case T_BYTE   : __ sbfx(r0, r0, 0, 8);             break;
213       case T_SHORT  : __ sbfx(r0, r0, 0, 16);            break;
214       case T_INT    : __ sbfx(r0, r0, 0, 32);            break;
215       case T_DOUBLE :
216       case T_FLOAT  :
217         // Result is in v0 we'll save as needed
218         break;
219       case T_VOID: break;
220       case T_LONG: break;
221       default       : ShouldNotReachHere();
222     }
223   } else {
224     assert(ret_buf_addr_sp_offset != -1, "no return buffer addr spill");
225     __ ldr(tmp1, Address(sp, ret_buf_addr_sp_offset));
226     int offset = 0;
227     for (int i = 0; i < _output_registers.length(); i++) {
228       VMReg reg = _output_registers.at(i);
229       if (reg->is_Register()) {
230         __ str(reg->as_Register(), Address(tmp1, offset));
231         offset += 8;
232       } else if(reg->is_FloatRegister()) {
233         __ strd(reg->as_FloatRegister(), Address(tmp1, offset));
234         offset += 16;
235       } else {
236         ShouldNotReachHere();
237       }
238     }
239   }
240 
241   __ mov(tmp1, _thread_in_native_trans);
242   __ strw(tmp1, Address(rthread, JavaThread::thread_state_offset()));
243 
244   // Force this write out before the read below
245   __ membar(Assembler::LoadLoad | Assembler::LoadStore |
246             Assembler::StoreLoad | Assembler::StoreStore);
247 
248   __ verify_sve_vector_length(tmp1);
249 
250   Label L_after_safepoint_poll;
251   Label L_safepoint_poll_slow_path;
252 
253   __ safepoint_poll(L_safepoint_poll_slow_path, true /* at_return */, true /* acquire */, false /* in_nmethod */, tmp1);
254 
255   __ ldrw(tmp1, Address(rthread, JavaThread::suspend_flags_offset()));
256   __ cbnzw(tmp1, L_safepoint_poll_slow_path);
257 
258   __ bind(L_after_safepoint_poll);
259 
260   // change thread state
261   __ mov(tmp1, _thread_in_Java);
262   __ lea(tmp2, Address(rthread, JavaThread::thread_state_offset()));
263   __ stlrw(tmp1, tmp2);
264 
265   __ block_comment("reguard stack check");
266   Label L_reguard;
267   Label L_after_reguard;
268   __ ldrb(tmp1, Address(rthread, JavaThread::stack_guard_state_offset()));
269   __ cmpw(tmp1, StackOverflow::stack_guard_yellow_reserved_disabled);
270   __ br(Assembler::EQ, L_reguard);
271   __ bind(L_after_reguard);
272 
273   __ reset_last_Java_frame(true);
274 
275   __ leave(); // required for proper stackwalking of RuntimeStub frame
276   __ ret(lr);
277 
278   //////////////////////////////////////////////////////////////////////////////
279 
280   __ block_comment("{ L_safepoint_poll_slow_path");
281   __ bind(L_safepoint_poll_slow_path);
282 
283   if (!_needs_return_buffer) {
284     // Need to save the native result registers around any runtime calls.
285     out_reg_spiller.generate_spill(_masm, spill_offset);
286   }
287 
288   __ mov(c_rarg0, rthread);
289   assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area");
290   __ lea(tmp1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
291   __ blr(tmp1);
292 
293   if (!_needs_return_buffer) {
294     out_reg_spiller.generate_fill(_masm, spill_offset);
295   }
296 
297   __ b(L_after_safepoint_poll);
298   __ block_comment("} L_safepoint_poll_slow_path");
299 
300   //////////////////////////////////////////////////////////////////////////////
301 
302   __ block_comment("{ L_reguard");
303   __ bind(L_reguard);
304 
305   if (!_needs_return_buffer) {
306     out_reg_spiller.generate_spill(_masm, spill_offset);
307   }
308 
309   __ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), tmp1);



310 
311   if (!_needs_return_buffer) {
312     out_reg_spiller.generate_fill(_masm, spill_offset);
313   }
314 
315   __ b(L_after_reguard);
316 
317   __ block_comment("} L_reguard");
318 
319   //////////////////////////////////////////////////////////////////////////////
320 
321   __ flush();
322 }
< prev index next >