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