1 /*
2 * Copyright (c) 1997, 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 #include "asm/macroAssembler.hpp"
27 #include "interpreter/interp_masm.hpp"
28 #include "interpreter/interpreter.hpp"
29 #include "interpreter/interpreterRuntime.hpp"
30 #include "interpreter/templateInterpreterGenerator.hpp"
31 #include "runtime/arguments.hpp"
32 #include "runtime/sharedRuntime.hpp"
33
34 #define __ _masm->
35
36
generate_slow_signature_handler()37 address TemplateInterpreterGenerator::generate_slow_signature_handler() {
38 address entry = __ pc();
39 // rbx,: method
40 // rcx: temporary
41 // rdi: pointer to locals
42 // rsp: end of copied parameters area
43 __ mov(rcx, rsp);
44 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::slow_signature_handler), rbx, rdi, rcx);
45 __ ret(0);
46 return entry;
47 }
48
49 /**
50 * Method entry for static native methods:
51 * int java.util.zip.CRC32.update(int crc, int b)
52 */
generate_CRC32_update_entry()53 address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
54 if (UseCRC32Intrinsics) {
55 address entry = __ pc();
56
57 // rbx: Method*
58 // rsi: senderSP must preserved for slow path, set SP to it on fast path
59 // rdx: scratch
60 // rdi: scratch
61
62 Label slow_path;
63 // If we need a safepoint check, generate full interpreter entry.
64 __ safepoint_poll(slow_path, noreg, rdi);
65
66 // We don't generate local frame and don't align stack because
67 // we call stub code and there is no safepoint on this path.
68
69 // Load parameters
70 const Register crc = rax; // crc
71 const Register val = rdx; // source java byte value
72 const Register tbl = rdi; // scratch
73
74 // Arguments are reversed on java expression stack
75 __ movl(val, Address(rsp, wordSize)); // byte value
76 __ movl(crc, Address(rsp, 2*wordSize)); // Initial CRC
77
78 __ lea(tbl, ExternalAddress(StubRoutines::crc_table_addr()));
79 __ notl(crc); // ~crc
80 __ update_byte_crc32(crc, val, tbl);
81 __ notl(crc); // ~crc
82 // result in rax
83
84 // _areturn
85 __ pop(rdi); // get return address
86 __ mov(rsp, rsi); // set sp to sender sp
87 __ jmp(rdi);
88
89 // generate a vanilla native entry as the slow path
90 __ bind(slow_path);
91 __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
92 return entry;
93 }
94 return NULL;
95 }
96
97 /**
98 * Method entry for static native methods:
99 * int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len)
100 * int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len)
101 */
generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind)102 address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
103 if (UseCRC32Intrinsics) {
104 address entry = __ pc();
105
106 // rbx,: Method*
107 // rsi: senderSP must preserved for slow path, set SP to it on fast path
108 // rdx: scratch
109 // rdi: scratch
110
111 Label slow_path;
112 // If we need a safepoint check, generate full interpreter entry.
113 __ safepoint_poll(slow_path, noreg, rdi);
114
115 // We don't generate local frame and don't align stack because
116 // we call stub code and there is no safepoint on this path.
117
118 // Load parameters
119 const Register crc = rax; // crc
120 const Register buf = rdx; // source java byte array address
121 const Register len = rdi; // length
122
123 // value x86_32
124 // interp. arg ptr ESP + 4
125 // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len)
126 // 3 2 1 0
127 // int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len)
128 // 4 2,3 1 0
129
130 // Arguments are reversed on java expression stack
131 __ movl(len, Address(rsp, 4 + 0)); // Length
132 // Calculate address of start element
133 if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) {
134 __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long buf
135 __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
136 __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC
137 } else {
138 __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array
139 __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
140 __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
141 __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC
142 }
143
144 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()), crc, buf, len);
145 // result in rax
146
147 // _areturn
148 __ pop(rdi); // get return address
149 __ mov(rsp, rsi); // set sp to sender sp
150 __ jmp(rdi);
151
152 // generate a vanilla native entry as the slow path
153 __ bind(slow_path);
154 __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
155 return entry;
156 }
157 return NULL;
158 }
159
160 /**
161 * Method entry for static native methods:
162 * int java.util.zip.CRC32C.updateBytes(int crc, byte[] b, int off, int end)
163 * int java.util.zip.CRC32C.updateByteBuffer(int crc, long address, int off, int end)
164 */
generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind)165 address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
166 if (UseCRC32CIntrinsics) {
167 address entry = __ pc();
168 // Load parameters
169 const Register crc = rax; // crc
170 const Register buf = rcx; // source java byte array address
171 const Register len = rdx; // length
172 const Register end = len;
173
174 // value x86_32
175 // interp. arg ptr ESP + 4
176 // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int end)
177 // 3 2 1 0
178 // int java.util.zip.CRC32.updateByteBuffer(int crc, long address, int off, int end)
179 // 4 2,3 1 0
180
181 // Arguments are reversed on java expression stack
182 __ movl(end, Address(rsp, 4 + 0)); // end
183 __ subl(len, Address(rsp, 4 + 1 * wordSize)); // end - offset == length
184 // Calculate address of start element
185 if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) {
186 __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long address
187 __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
188 __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC
189 } else {
190 __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array
191 __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
192 __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
193 __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC
194 }
195 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()), crc, buf, len);
196 // result in rax
197 // _areturn
198 __ pop(rdi); // get return address
199 __ mov(rsp, rsi); // set sp to sender sp
200 __ jmp(rdi);
201
202 return entry;
203 }
204 return NULL;
205 }
206
207 /**
208 * Method entry for static native method:
209 * java.lang.Float.intBitsToFloat(int bits)
210 */
generate_Float_intBitsToFloat_entry()211 address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() {
212 if (UseSSE >= 1) {
213 address entry = __ pc();
214
215 // rsi: the sender's SP
216
217 // Skip safepoint check (compiler intrinsic versions of this method
218 // do not perform safepoint checks either).
219
220 // Load 'bits' into xmm0 (interpreter returns results in xmm0)
221 __ movflt(xmm0, Address(rsp, wordSize));
222
223 // Return
224 __ pop(rdi); // get return address
225 __ mov(rsp, rsi); // set rsp to the sender's SP
226 __ jmp(rdi);
227 return entry;
228 }
229
230 return NULL;
231 }
232
233 /**
234 * Method entry for static native method:
235 * java.lang.Float.floatToRawIntBits(float value)
236 */
generate_Float_floatToRawIntBits_entry()237 address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() {
238 if (UseSSE >= 1) {
239 address entry = __ pc();
240
241 // rsi: the sender's SP
242
243 // Skip safepoint check (compiler intrinsic versions of this method
244 // do not perform safepoint checks either).
245
246 // Load the parameter (a floating-point value) into rax.
247 __ movl(rax, Address(rsp, wordSize));
248
249 // Return
250 __ pop(rdi); // get return address
251 __ mov(rsp, rsi); // set rsp to the sender's SP
252 __ jmp(rdi);
253 return entry;
254 }
255
256 return NULL;
257 }
258
259
260 /**
261 * Method entry for static native method:
262 * java.lang.Double.longBitsToDouble(long bits)
263 */
generate_Double_longBitsToDouble_entry()264 address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() {
265 if (UseSSE >= 2) {
266 address entry = __ pc();
267
268 // rsi: the sender's SP
269
270 // Skip safepoint check (compiler intrinsic versions of this method
271 // do not perform safepoint checks either).
272
273 // Load 'bits' into xmm0 (interpreter returns results in xmm0)
274 __ movdbl(xmm0, Address(rsp, wordSize));
275
276 // Return
277 __ pop(rdi); // get return address
278 __ mov(rsp, rsi); // set rsp to the sender's SP
279 __ jmp(rdi);
280 return entry;
281 }
282
283 return NULL;
284 }
285
286 /**
287 * Method entry for static native method:
288 * java.lang.Double.doubleToRawLongBits(double value)
289 */
generate_Double_doubleToRawLongBits_entry()290 address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry() {
291 if (UseSSE >= 2) {
292 address entry = __ pc();
293
294 // rsi: the sender's SP
295
296 // Skip safepoint check (compiler intrinsic versions of this method
297 // do not perform safepoint checks either).
298
299 // Load the parameter (a floating-point value) into rax.
300 __ movl(rdx, Address(rsp, 2*wordSize));
301 __ movl(rax, Address(rsp, wordSize));
302
303 // Return
304 __ pop(rdi); // get return address
305 __ mov(rsp, rsi); // set rsp to the sender's SP
306 __ jmp(rdi);
307 return entry;
308 }
309
310 return NULL;
311 }
312
generate_math_entry(AbstractInterpreter::MethodKind kind)313 address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
314
315 // rbx,: Method*
316 // rcx: scratrch
317 // rsi: sender sp
318
319 if (!InlineIntrinsics) return NULL; // Generate a vanilla entry
320
321 address entry_point = __ pc();
322
323 // These don't need a safepoint check because they aren't virtually
324 // callable. We won't enter these intrinsics from compiled code.
325 // If in the future we added an intrinsic which was virtually callable
326 // we'd have to worry about how to safepoint so that this code is used.
327
328 // mathematical functions inlined by compiler
329 // (interpreter must provide identical implementation
330 // in order to avoid monotonicity bugs when switching
331 // from interpreter to compiler in the middle of some
332 // computation)
333 //
334 // stack: [ ret adr ] <-- rsp
335 // [ lo(arg) ]
336 // [ hi(arg) ]
337 //
338 if (kind == Interpreter::java_lang_math_fmaD) {
339 if (!UseFMA) {
340 return NULL; // Generate a vanilla entry
341 }
342 __ movdbl(xmm2, Address(rsp, 5 * wordSize));
343 __ movdbl(xmm1, Address(rsp, 3 * wordSize));
344 __ movdbl(xmm0, Address(rsp, 1 * wordSize));
345 __ fmad(xmm0, xmm1, xmm2, xmm0);
346 __ pop(rdi); // get return address
347 __ mov(rsp, rsi); // set sp to sender sp
348 __ jmp(rdi);
349
350 return entry_point;
351 } else if (kind == Interpreter::java_lang_math_fmaF) {
352 if (!UseFMA) {
353 return NULL; // Generate a vanilla entry
354 }
355 __ movflt(xmm2, Address(rsp, 3 * wordSize));
356 __ movflt(xmm1, Address(rsp, 2 * wordSize));
357 __ movflt(xmm0, Address(rsp, 1 * wordSize));
358 __ fmaf(xmm0, xmm1, xmm2, xmm0);
359 __ pop(rdi); // get return address
360 __ mov(rsp, rsi); // set sp to sender sp
361 __ jmp(rdi);
362
363 return entry_point;
364 }
365
366 __ fld_d(Address(rsp, 1*wordSize));
367 switch (kind) {
368 case Interpreter::java_lang_math_sin :
369 __ subptr(rsp, 2 * wordSize);
370 __ fstp_d(Address(rsp, 0));
371 if (VM_Version::supports_sse2() && StubRoutines::dsin() != NULL) {
372 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dsin())));
373 } else {
374 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
375 }
376 __ addptr(rsp, 2 * wordSize);
377 break;
378 case Interpreter::java_lang_math_cos :
379 __ subptr(rsp, 2 * wordSize);
380 __ fstp_d(Address(rsp, 0));
381 if (VM_Version::supports_sse2() && StubRoutines::dcos() != NULL) {
382 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dcos())));
383 } else {
384 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dcos));
385 }
386 __ addptr(rsp, 2 * wordSize);
387 break;
388 case Interpreter::java_lang_math_tan :
389 __ subptr(rsp, 2 * wordSize);
390 __ fstp_d(Address(rsp, 0));
391 if (StubRoutines::dtan() != NULL) {
392 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dtan())));
393 } else {
394 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
395 }
396 __ addptr(rsp, 2 * wordSize);
397 break;
398 case Interpreter::java_lang_math_sqrt:
399 __ fsqrt();
400 break;
401 case Interpreter::java_lang_math_abs:
402 __ fabs();
403 break;
404 case Interpreter::java_lang_math_log:
405 __ subptr(rsp, 2 * wordSize);
406 __ fstp_d(Address(rsp, 0));
407 if (StubRoutines::dlog() != NULL) {
408 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
409 } else {
410 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dlog));
411 }
412 __ addptr(rsp, 2 * wordSize);
413 break;
414 case Interpreter::java_lang_math_log10:
415 __ subptr(rsp, 2 * wordSize);
416 __ fstp_d(Address(rsp, 0));
417 if (StubRoutines::dlog10() != NULL) {
418 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog10())));
419 } else {
420 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dlog10));
421 }
422 __ addptr(rsp, 2 * wordSize);
423 break;
424 case Interpreter::java_lang_math_pow:
425 __ fld_d(Address(rsp, 3*wordSize)); // second argument
426 __ subptr(rsp, 4 * wordSize);
427 __ fstp_d(Address(rsp, 0));
428 __ fstp_d(Address(rsp, 2 * wordSize));
429 if (StubRoutines::dpow() != NULL) {
430 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dpow())));
431 } else {
432 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dpow));
433 }
434 __ addptr(rsp, 4 * wordSize);
435 break;
436 case Interpreter::java_lang_math_exp:
437 __ subptr(rsp, 2*wordSize);
438 __ fstp_d(Address(rsp, 0));
439 if (StubRoutines::dexp() != NULL) {
440 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
441 } else {
442 __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dexp));
443 }
444 __ addptr(rsp, 2*wordSize);
445 break;
446 default :
447 ShouldNotReachHere();
448 }
449
450 // return double result in xmm0 for interpreter and compilers.
451 if (UseSSE >= 2) {
452 __ subptr(rsp, 2*wordSize);
453 __ fstp_d(Address(rsp, 0));
454 __ movdbl(xmm0, Address(rsp, 0));
455 __ addptr(rsp, 2*wordSize);
456 }
457
458 // done, result in FPU ST(0) or XMM0
459 __ pop(rdi); // get return address
460 __ mov(rsp, rsi); // set sp to sender sp
461 __ jmp(rdi);
462
463 return entry_point;
464 }
465