1 /*
  2  * Copyright (c) 2020, 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 #include "precompiled.hpp"
 25 #include "asm/macroAssembler.hpp"
 26 #include "code/codeBlob.hpp"
 27 #include "logging/logStream.hpp"
 28 #include "memory/resourceArea.hpp"
 29 #include "prims/foreign_globals.inline.hpp"
 30 #include "prims/universalNativeInvoker.hpp"
 31 #include "runtime/sharedRuntime.hpp"
 32 #include "runtime/stubCodeGenerator.hpp"
 33 #include "utilities/formatBuffer.hpp"
 34 
 35 #define __ _masm->
 36 
 37 class NativeInvokerGenerator : public StubCodeGenerator {
 38   BasicType* _signature;
 39   int _num_args;
 40   BasicType _ret_bt;
 41 
 42   const ABIDescriptor& _abi;
 43   const GrowableArray<VMReg>& _input_registers;
 44   const GrowableArray<VMReg>& _output_registers;
 45 
 46   bool _needs_return_buffer;
 47 
 48   int _frame_complete;
 49   int _framesize;
 50   OopMapSet* _oop_maps;
 51 public:
 52   NativeInvokerGenerator(CodeBuffer* buffer,
 53                          BasicType* signature,
 54                          int num_args,
 55                          BasicType ret_bt,
 56                          const ABIDescriptor& abi,
 57                          const GrowableArray<VMReg>& input_registers,
 58                          const GrowableArray<VMReg>& output_registers,
 59                          bool needs_return_buffer)
 60    : StubCodeGenerator(buffer, PrintMethodHandleStubs),
 61      _signature(signature),
 62      _num_args(num_args),
 63      _ret_bt(ret_bt),
 64      _abi(abi),
 65      _input_registers(input_registers),
 66      _output_registers(output_registers),
 67      _needs_return_buffer(needs_return_buffer),
 68      _frame_complete(0),
 69      _framesize(0),
 70      _oop_maps(NULL) {
 71   }
 72 
 73   void generate();
 74 
 75   int frame_complete() const {
 76     return _frame_complete;
 77   }
 78 
 79   int framesize() const {
 80     return (_framesize >> (LogBytesPerWord - LogBytesPerInt));
 81   }
 82 
 83   OopMapSet* oop_maps() const {
 84     return _oop_maps;
 85   }
 86 };
 87 
 88 static const int native_invoker_code_size = 1024;
 89 
 90 RuntimeStub* ProgrammableInvoker::make_native_invoker(BasicType* signature,
 91                                                       int num_args,
 92                                                       BasicType ret_bt,
 93                                                       const ABIDescriptor& abi,
 94                                                       const GrowableArray<VMReg>& input_registers,
 95                                                       const GrowableArray<VMReg>& output_registers,
 96                                                       bool needs_return_buffer) {
 97   int locs_size  = 64;
 98   CodeBuffer code("nep_invoker_blob", native_invoker_code_size, locs_size);
 99   NativeInvokerGenerator g(&code, signature, num_args, ret_bt, abi, input_registers, output_registers, needs_return_buffer);
100   g.generate();
101   code.log_section_sizes("nep_invoker_blob");
102 
103   RuntimeStub* stub =
104     RuntimeStub::new_runtime_stub("nep_invoker_blob",
105                                   &code,
106                                   g.frame_complete(),
107                                   g.framesize(),
108                                   g.oop_maps(), false);
109 
110   if (TraceNativeInvokers) {
111     stub->print_on(tty);
112   }
113 
114   return stub;
115 }
116 
117 void NativeInvokerGenerator::generate() {
118   enum layout {
119     rbp_off,
120     rbp_off2,
121     return_off,
122     return_off2,
123     framesize_base // inclusive of return address
124     // The following are also computed dynamically:
125     // shadow space
126     // spill area
127     // out arg area (e.g. for stack args)
128   };
129 
130   Register shufffle_reg = rbx;
131   JavaCallConv in_conv;
132   NativeCallConv out_conv(_input_registers);
133   ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shufffle_reg->as_VMReg());
134 
135 #ifdef ASSERT
136   LogTarget(Trace, panama) lt;
137   if (lt.is_enabled()) {
138     ResourceMark rm;
139     LogStream ls(lt);
140     arg_shuffle.print_on(&ls);
141   }
142 #endif
143 
144   // in bytes
145   int allocated_frame_size = 0;
146   if (_needs_return_buffer) {
147     allocated_frame_size += 8; // store address
148   }
149   allocated_frame_size += arg_shuffle.out_arg_stack_slots() << LogBytesPerInt;
150   allocated_frame_size += _abi._shadow_space_bytes;
151 
152   int ret_buf_addr_rsp_offset = -1;
153   if (_needs_return_buffer) {
154     // the above
155     ret_buf_addr_rsp_offset = allocated_frame_size - 8;
156   }
157 
158   // when we don't use a return buffer we need to spill the return value around our slowpath calls
159   // when we use a return buffer case this SHOULD be unused.
160   RegSpiller out_reg_spiller(_output_registers);
161   int spill_rsp_offset = -1;
162 
163   if (!_needs_return_buffer) {
164     spill_rsp_offset = 0;
165     // spill area can be shared with the above, so we take the max of the 2
166     allocated_frame_size = out_reg_spiller.spill_size_bytes() > allocated_frame_size
167       ? out_reg_spiller.spill_size_bytes()
168       : allocated_frame_size;
169   }
170   allocated_frame_size = align_up(allocated_frame_size, 16);
171   // _framesize is in 32-bit stack slots:
172   _framesize += framesize_base + (allocated_frame_size >> LogBytesPerInt);
173   assert(is_even(_framesize/2), "sp not 16-byte aligned");
174 
175   _oop_maps  = new OopMapSet();
176   address start = __ pc();
177 
178   __ enter();
179 
180   // return address and rbp are already in place
181   __ subptr(rsp, allocated_frame_size); // prolog
182 
183   _frame_complete = __ pc() - start;
184 
185   address the_pc = __ pc();
186 
187   __ block_comment("{ thread java2native");
188   __ set_last_Java_frame(rsp, rbp, (address)the_pc);
189   OopMap* map = new OopMap(_framesize, 0);
190   _oop_maps->add_gc_map(the_pc - start, map);
191 
192   // State transition
193   __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native);
194   __ block_comment("} thread java2native");
195 
196   __ block_comment("{ argument shuffle");
197   arg_shuffle.generate(_masm, shufffle_reg->as_VMReg(), 0, _abi._shadow_space_bytes);
198   if (_needs_return_buffer) {
199     // spill our return buffer address
200     assert(ret_buf_addr_rsp_offset != -1, "no return buffer addr spill");
201     __ movptr(Address(rsp, ret_buf_addr_rsp_offset), _abi._ret_buf_addr_reg);
202   }
203   __ block_comment("} argument shuffle");
204 
205   __ call(_abi._target_addr_reg);
206   // this call is assumed not to have killed r15_thread
207 
208   if (!_needs_return_buffer) {
209     // FIXME: this assumes we return in rax/xmm0, which might not be the case
210     // Unpack native results.
211     switch (_ret_bt) {
212       case T_BOOLEAN: __ c2bool(rax);            break;
213       case T_CHAR   : __ movzwl(rax, rax);       break;
214       case T_BYTE   : __ sign_extend_byte (rax); break;
215       case T_SHORT  : __ sign_extend_short(rax); break;
216       case T_INT    : /* nothing to do */        break;
217       case T_DOUBLE :
218       case T_FLOAT  :
219         // Result is in xmm0 we'll save as needed
220         break;
221       case T_VOID: break;
222       case T_LONG: break;
223       default       : ShouldNotReachHere();
224     }
225   } else {
226     assert(ret_buf_addr_rsp_offset != -1, "no return buffer addr spill");
227     __ movptr(rscratch1, Address(rsp, ret_buf_addr_rsp_offset));
228     int offset = 0;
229     for (int i = 0; i < _output_registers.length(); i++) {
230       VMReg reg = _output_registers.at(i);
231       if (reg->is_Register()) {
232         __ movptr(Address(rscratch1, offset), reg->as_Register());
233         offset += 8;
234       } else if (reg->is_XMMRegister()) {
235         __ movdqu(Address(rscratch1, offset), reg->as_XMMRegister());
236         offset += 16;
237       } else {
238         ShouldNotReachHere();
239       }
240     }
241   }
242 
243   __ block_comment("{ thread native2java");
244   __ restore_cpu_control_state_after_jni();
245 
246   __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native_trans);
247 
248   // Force this write out before the read below
249   __ membar(Assembler::Membar_mask_bits(
250           Assembler::LoadLoad | Assembler::LoadStore |
251           Assembler::StoreLoad | Assembler::StoreStore));
252 
253   Label L_after_safepoint_poll;
254   Label L_safepoint_poll_slow_path;
255 
256   __ safepoint_poll(L_safepoint_poll_slow_path, r15_thread, true /* at_return */, false /* in_nmethod */);
257   __ cmpl(Address(r15_thread, JavaThread::suspend_flags_offset()), 0);
258   __ jcc(Assembler::notEqual, L_safepoint_poll_slow_path);
259 
260   __ bind(L_after_safepoint_poll);
261 
262   // change thread state
263   __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_Java);
264 
265   __ block_comment("reguard stack check");
266   Label L_reguard;
267   Label L_after_reguard;
268   __ cmpl(Address(r15_thread, JavaThread::stack_guard_state_offset()), StackOverflow::stack_guard_yellow_reserved_disabled);
269   __ jcc(Assembler::equal, L_reguard);
270   __ bind(L_after_reguard);
271 
272   __ reset_last_Java_frame(r15_thread, true);
273   __ block_comment("} thread native2java");
274 
275   __ leave(); // required for proper stackwalking of RuntimeStub frame
276   __ ret(0);
277 
278   //////////////////////////////////////////////////////////////////////////////
279 
280   __ block_comment("{ L_safepoint_poll_slow_path");
281   __ bind(L_safepoint_poll_slow_path);
282   __ vzeroupper();
283 
284   if(!_needs_return_buffer) {
285     out_reg_spiller.generate_spill(_masm, spill_rsp_offset);
286   }
287 
288   __ mov(c_rarg0, r15_thread);
289   __ mov(r12, rsp); // remember sp
290   __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows
291   __ andptr(rsp, -16); // align stack as required by ABI
292   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
293   __ mov(rsp, r12); // restore sp
294   __ reinit_heapbase();
295 
296   if(!_needs_return_buffer) {
297     out_reg_spiller.generate_fill(_masm, spill_rsp_offset);
298   }
299 
300   __ jmp(L_after_safepoint_poll);
301   __ block_comment("} L_safepoint_poll_slow_path");
302 
303   //////////////////////////////////////////////////////////////////////////////
304 
305   __ block_comment("{ L_reguard");
306   __ bind(L_reguard);
307   __ vzeroupper();
308 
309   if(!_needs_return_buffer) {
310     out_reg_spiller.generate_spill(_masm, spill_rsp_offset);
311   }
312 
313   __ mov(r12, rsp); // remember sp
314   __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows
315   __ andptr(rsp, -16); // align stack as required by ABI
316   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)));
317   __ mov(rsp, r12); // restore sp
318   __ reinit_heapbase();
319 
320   if(!_needs_return_buffer) {
321     out_reg_spiller.generate_fill(_masm, spill_rsp_offset);
322   }
323 
324   __ jmp(L_after_reguard);
325 
326   __ block_comment("} L_reguard");
327 
328   //////////////////////////////////////////////////////////////////////////////
329 
330   __ flush();
331 }