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