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