169 Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler();
170 Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException");
171 Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException", "/ by zero");
172 Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler();
173 Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException", nullptr);
174 Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler();
175 }
176
177 { CodeletMark cm(_masm, "preemption resume adapter");
178 Interpreter::_cont_resume_interpreter_adapter = generate_cont_resume_interpreter_adapter();
179 }
180
181 #define method_entry(kind) \
182 { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \
183 Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind, false); \
184 }
185
186 // all non-native method kinds
187 method_entry(zerolocals)
188 method_entry(zerolocals_synchronized)
189 method_entry(empty)
190 method_entry(getter)
191 method_entry(setter)
192 method_entry(abstract)
193 method_entry(java_lang_math_sin )
194 method_entry(java_lang_math_cos )
195 method_entry(java_lang_math_tan )
196 method_entry(java_lang_math_tanh )
197 method_entry(java_lang_math_abs )
198 method_entry(java_lang_math_sqrt )
199 method_entry(java_lang_math_sqrt_strict)
200 method_entry(java_lang_math_log )
201 method_entry(java_lang_math_log10)
202 method_entry(java_lang_math_exp )
203 method_entry(java_lang_math_pow )
204 method_entry(java_lang_math_fmaF )
205 method_entry(java_lang_math_fmaD )
206 method_entry(java_lang_ref_reference_get)
207 AbstractInterpreter::initialize_method_handle_entries();
208
209 method_entry(java_util_zip_CRC32C_updateBytes)
210 method_entry(java_util_zip_CRC32C_updateDirectByteBuffer)
211
212 method_entry(java_lang_Float_float16ToFloat);
213 method_entry(java_lang_Float_floatToFloat16);
214
215 #undef method_entry
216
217 // all native method kinds
218 #define native_method_entry(kind) \
219 { CodeletMark cm(_masm, "native method entry point (kind = " #kind ")"); \
220 Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind, true); \
221 }
222
223 native_method_entry(native)
224 native_method_entry(native_synchronized)
225
226 // Entries to intrinsics for native methods should follow
227 // entries for `native` methods to use the same address in case
228 // intrinsic is disabled.
229 native_method_entry(java_lang_Thread_currentThread)
230
231 native_method_entry(java_util_zip_CRC32_update)
232 native_method_entry(java_util_zip_CRC32_updateBytes)
233 native_method_entry(java_util_zip_CRC32_updateByteBuffer)
234
235 native_method_entry(java_lang_Float_intBitsToFloat)
236 native_method_entry(java_lang_Float_floatToRawIntBits)
237 native_method_entry(java_lang_Double_longBitsToDouble)
238 native_method_entry(java_lang_Double_doubleToRawLongBits)
239
240 #undef native_method_entry
241
242 // Bytecodes
243 set_entry_points_for_all_bytes();
244
352 case btos:
353 case ztos:
354 case ctos:
355 case stos:
356 ShouldNotReachHere(); // btos/ctos/stos should use itos.
357 break;
358 case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break;
359 case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break;
360 case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break;
361 case ftos: vep = __ pc(); __ pop(ftos); fep = __ pc(); generate_and_dispatch(t); break;
362 case dtos: vep = __ pc(); __ pop(dtos); dep = __ pc(); generate_and_dispatch(t); break;
363 case vtos: set_vtos_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); break;
364 default : ShouldNotReachHere(); break;
365 }
366 }
367
368
369 //------------------------------------------------------------------------------------------------------------------------
370
371 void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) {
372 #ifndef PRODUCT
373 // debugging code
374 if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode();
375 if (PrintBytecodeHistogram) histogram_bytecode(t);
376 if (PrintBytecodePairHistogram) histogram_bytecode_pair(t);
377 if (TraceBytecodes) trace_bytecode(t);
378 if (StopInterpreterAt > 0) stop_interpreter_at();
379 __ verify_FPU(1, t->tos_in());
380 #endif // !PRODUCT
381 int step = 0;
382 if (!t->does_dispatch()) {
383 step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode());
384 if (tos_out == ilgl) tos_out = t->tos_out();
385 // compute bytecode size
386 assert(step > 0, "just checkin'");
387 // setup stuff for dispatching next bytecode
388 if (ProfileInterpreter && VerifyDataPointer
389 && MethodData::bytecode_has_profile(t->bytecode())) {
390 __ verify_method_data_pointer();
391 }
392 __ dispatch_prolog(tos_out, step);
393 }
394 // generate template
395 t->generate(_masm);
396 // advance
397 if (t->does_dispatch()) {
398 #ifdef ASSERT
399 // make sure execution doesn't go beyond this point if code is broken
400 __ should_not_reach_here();
401 #endif // ASSERT
402 } else {
403 // dispatch to next bytecode
404 __ dispatch_epilog(tos_out, step);
405 }
406 }
407
408 // Generate method entries
409 address TemplateInterpreterGenerator::generate_method_entry(
410 AbstractInterpreter::MethodKind kind, bool native) {
411 // determine code generation flags
412 bool synchronized = false;
413 address entry_point = nullptr;
414
415 switch (kind) {
416 case Interpreter::zerolocals : break;
417 case Interpreter::zerolocals_synchronized: synchronized = true; break;
418 case Interpreter::native : break;
419 case Interpreter::native_synchronized : synchronized = true; break;
420 case Interpreter::empty : break;
421 case Interpreter::getter : break;
422 case Interpreter::setter : break;
423 case Interpreter::abstract : entry_point = generate_abstract_entry(); break;
424 default:
425 entry_point = generate_intrinsic_entry(kind); // process the rest
426 break;
427 }
428
429 if (entry_point) {
430 return entry_point;
431 }
432
433 // We expect the normal and native entry points to be generated first so we can reuse them.
434 if (native) {
435 entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::native_synchronized : Interpreter::native);
436 if (entry_point == nullptr) {
437 entry_point = generate_native_entry(synchronized);
438 }
439 } else {
440 entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::zerolocals_synchronized : Interpreter::zerolocals);
441 if (entry_point == nullptr) {
442 entry_point = generate_normal_entry(synchronized);
443 }
444 }
445
446 return entry_point;
447 }
448
449 // Generate intrinsic method entries
450 address TemplateInterpreterGenerator::generate_intrinsic_entry(AbstractInterpreter::MethodKind kind) {
451 if (!InlineIntrinsics || !vmIntrinsics::is_intrinsic_available(AbstractInterpreter::method_intrinsic(kind))) {
452 return nullptr;
453 }
454
455 address entry_point = nullptr;
456
457 switch (kind) {
458 case Interpreter::java_lang_math_sin : // fall thru
459 case Interpreter::java_lang_math_cos : // fall thru
460 case Interpreter::java_lang_math_tan : // fall thru
461 case Interpreter::java_lang_math_tanh : // fall thru
462 case Interpreter::java_lang_math_abs : // fall thru
463 case Interpreter::java_lang_math_log : // fall thru
|
169 Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler();
170 Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException");
171 Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException", "/ by zero");
172 Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler();
173 Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException", nullptr);
174 Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler();
175 }
176
177 { CodeletMark cm(_masm, "preemption resume adapter");
178 Interpreter::_cont_resume_interpreter_adapter = generate_cont_resume_interpreter_adapter();
179 }
180
181 #define method_entry(kind) \
182 { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \
183 Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind, false); \
184 }
185
186 // all non-native method kinds
187 method_entry(zerolocals)
188 method_entry(zerolocals_synchronized)
189 method_entry(zerolocals_upcalls)
190 method_entry(zerolocals_synchronized_upcalls)
191 method_entry(empty)
192 method_entry(empty_upcalls)
193 method_entry(getter)
194 method_entry(setter)
195 method_entry(abstract)
196 method_entry(java_lang_math_sin )
197 method_entry(java_lang_math_cos )
198 method_entry(java_lang_math_tan )
199 method_entry(java_lang_math_tanh )
200 method_entry(java_lang_math_abs )
201 method_entry(java_lang_math_sqrt )
202 method_entry(java_lang_math_sqrt_strict)
203 method_entry(java_lang_math_log )
204 method_entry(java_lang_math_log10)
205 method_entry(java_lang_math_exp )
206 method_entry(java_lang_math_pow )
207 method_entry(java_lang_math_fmaF )
208 method_entry(java_lang_math_fmaD )
209 method_entry(java_lang_ref_reference_get)
210 AbstractInterpreter::initialize_method_handle_entries();
211
212 method_entry(java_util_zip_CRC32C_updateBytes)
213 method_entry(java_util_zip_CRC32C_updateDirectByteBuffer)
214
215 method_entry(java_lang_Float_float16ToFloat);
216 method_entry(java_lang_Float_floatToFloat16);
217
218 #undef method_entry
219
220 // all native method kinds
221 #define native_method_entry(kind) \
222 { CodeletMark cm(_masm, "native method entry point (kind = " #kind ")"); \
223 Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind, true); \
224 }
225
226 native_method_entry(native)
227 native_method_entry(native_synchronized)
228 native_method_entry(native_upcalls)
229 native_method_entry(native_synchronized_upcalls)
230
231 // Entries to intrinsics for native methods should follow
232 // entries for `native` methods to use the same address in case
233 // intrinsic is disabled.
234 native_method_entry(java_lang_Thread_currentThread)
235
236 native_method_entry(java_util_zip_CRC32_update)
237 native_method_entry(java_util_zip_CRC32_updateBytes)
238 native_method_entry(java_util_zip_CRC32_updateByteBuffer)
239
240 native_method_entry(java_lang_Float_intBitsToFloat)
241 native_method_entry(java_lang_Float_floatToRawIntBits)
242 native_method_entry(java_lang_Double_longBitsToDouble)
243 native_method_entry(java_lang_Double_doubleToRawLongBits)
244
245 #undef native_method_entry
246
247 // Bytecodes
248 set_entry_points_for_all_bytes();
249
357 case btos:
358 case ztos:
359 case ctos:
360 case stos:
361 ShouldNotReachHere(); // btos/ctos/stos should use itos.
362 break;
363 case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break;
364 case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break;
365 case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break;
366 case ftos: vep = __ pc(); __ pop(ftos); fep = __ pc(); generate_and_dispatch(t); break;
367 case dtos: vep = __ pc(); __ pop(dtos); dep = __ pc(); generate_and_dispatch(t); break;
368 case vtos: set_vtos_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); break;
369 default : ShouldNotReachHere(); break;
370 }
371 }
372
373
374 //------------------------------------------------------------------------------------------------------------------------
375
376 void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) {
377 if (CountBytecodes || CountBytecodesPerThread || TraceBytecodes || StopInterpreterAt > 0) {
378 count_bytecode();
379 }
380 if (PrintBytecodeHistogram) histogram_bytecode(t);
381 #ifndef PRODUCT
382 // debugging code
383 if (PrintBytecodePairHistogram) histogram_bytecode_pair(t);
384 if (TraceBytecodes) trace_bytecode(t);
385 if (StopInterpreterAt > 0) stop_interpreter_at();
386 __ verify_FPU(1, t->tos_in());
387 #endif // !PRODUCT
388 int step = 0;
389 if (!t->does_dispatch()) {
390 step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode());
391 if (tos_out == ilgl) tos_out = t->tos_out();
392 // compute bytecode size
393 assert(step > 0, "just checkin'");
394 // setup stuff for dispatching next bytecode
395 if (ProfileInterpreter && VerifyDataPointer
396 && MethodData::bytecode_has_profile(t->bytecode())) {
397 __ verify_method_data_pointer();
398 }
399 __ dispatch_prolog(tos_out, step);
400 }
401 // generate template
402 t->generate(_masm);
403 // advance
404 if (t->does_dispatch()) {
405 #ifdef ASSERT
406 // make sure execution doesn't go beyond this point if code is broken
407 __ should_not_reach_here();
408 #endif // ASSERT
409 } else {
410 // dispatch to next bytecode
411 __ dispatch_epilog(tos_out, step);
412 }
413 }
414
415 bool TemplateInterpreterGenerator::is_synchronized_method(AbstractInterpreter::MethodKind kind) {
416 switch (kind) {
417 case Interpreter::zerolocals_synchronized : // fall thru
418 case Interpreter::zerolocals_synchronized_upcalls: // fall thru
419 case Interpreter::native_synchronized : // fall thru
420 case Interpreter::native_synchronized_upcalls :
421 return true;
422 default:
423 return false;
424 }
425 }
426
427 bool TemplateInterpreterGenerator::is_runtime_upcalls_method(AbstractInterpreter::MethodKind kind) {
428 switch (kind) {
429 case Interpreter::zerolocals_upcalls : // fall thru
430 case Interpreter::zerolocals_synchronized_upcalls: // fall thru
431 case Interpreter::native_upcalls : // fall thru
432 case Interpreter::native_synchronized_upcalls : // fall thru
433 case Interpreter::empty_upcalls :
434 return true;
435 default:
436 return false;
437 }
438 }
439
440 bool TemplateInterpreterGenerator::is_intrinsic_method(AbstractInterpreter::MethodKind kind) {
441 switch (kind) {
442 case Interpreter::zerolocals : // fall thru
443 case Interpreter::zerolocals_synchronized : // fall thru
444 case Interpreter::zerolocals_upcalls : // fall thru
445 case Interpreter::zerolocals_synchronized_upcalls: // fall thru
446 case Interpreter::native : // fall thru
447 case Interpreter::native_synchronized : // fall thru
448 case Interpreter::native_upcalls : // fall thru
449 case Interpreter::native_synchronized_upcalls : // fall thru
450 case Interpreter::empty : // fall thru
451 case Interpreter::empty_upcalls : // fall thru
452 case Interpreter::getter : // fall thru
453 case Interpreter::setter : // fall thru
454 case Interpreter::abstract :
455 return false;
456 default:
457 return true;
458 }
459 }
460
461 bool TemplateInterpreterGenerator::is_abstract_method(AbstractInterpreter::MethodKind kind) {
462 switch (kind) {
463 case Interpreter::abstract:
464 return true;
465 default:
466 return false;
467 }
468 }
469
470 // Generate method entries
471 address TemplateInterpreterGenerator::generate_method_entry(
472 AbstractInterpreter::MethodKind kind, bool native) {
473 address entry_point = nullptr;
474
475 if (is_abstract_method(kind)) {
476 entry_point = generate_abstract_entry();
477 } else if (is_intrinsic_method(kind)) {
478 entry_point = generate_intrinsic_entry(kind);
479 }
480
481 if (entry_point) {
482 return entry_point;
483 }
484
485 bool synchronized = is_synchronized_method(kind);
486 bool upcalls = is_runtime_upcalls_method(kind);
487
488 // We expect the normal and native entry points to be generated first so we can reuse them.
489 if (!synchronized && !upcalls) {
490 entry_point = Interpreter::entry_for_kind(native ? Interpreter::native
491 : Interpreter::zerolocals);
492 } else if (synchronized && !upcalls) {
493 entry_point = Interpreter::entry_for_kind(native ? Interpreter::native_synchronized
494 : Interpreter::zerolocals_synchronized);
495 } else if (!synchronized && upcalls) {
496 entry_point = Interpreter::entry_for_kind(native ? Interpreter::native_upcalls
497 : Interpreter::zerolocals_upcalls);
498 } else if (synchronized && upcalls) {
499 entry_point = Interpreter::entry_for_kind(native ? Interpreter::native_synchronized_upcalls
500 : Interpreter::zerolocals_synchronized_upcalls);
501 }
502
503 if (entry_point == nullptr) {
504 entry_point = native ? generate_native_entry(synchronized, upcalls)
505 : generate_normal_entry(synchronized, upcalls);
506 }
507
508 return entry_point;
509 }
510
511 // Generate intrinsic method entries
512 address TemplateInterpreterGenerator::generate_intrinsic_entry(AbstractInterpreter::MethodKind kind) {
513 if (!InlineIntrinsics || !vmIntrinsics::is_intrinsic_available(AbstractInterpreter::method_intrinsic(kind))) {
514 return nullptr;
515 }
516
517 address entry_point = nullptr;
518
519 switch (kind) {
520 case Interpreter::java_lang_math_sin : // fall thru
521 case Interpreter::java_lang_math_cos : // fall thru
522 case Interpreter::java_lang_math_tan : // fall thru
523 case Interpreter::java_lang_math_tanh : // fall thru
524 case Interpreter::java_lang_math_abs : // fall thru
525 case Interpreter::java_lang_math_log : // fall thru
|