Skip to content

Commit 9372228

Browse files
Use builtin_throw
1 parent 40474d3 commit 9372228

File tree

6 files changed

+332
-36
lines changed

6 files changed

+332
-36
lines changed

Diff for: src/hotspot/share/opto/graphKit.cpp

+34-28
Original file line numberDiff line numberDiff line change
@@ -525,17 +525,13 @@ void GraphKit::uncommon_trap_if_should_post_on_exceptions(Deoptimization::DeoptR
525525

526526
}
527527

528-
//------------------------------builtin_throw----------------------------------
529-
void GraphKit::builtin_throw(Deoptimization::DeoptReason reason) {
530-
bool must_throw = true;
531-
528+
Pair<bool, bool> GraphKit::builtin_throw_applies(Deoptimization::DeoptReason reason) {
532529
// If this particular condition has not yet happened at this
533530
// bytecode, then use the uncommon trap mechanism, and allow for
534531
// a future recompilation if several traps occur here.
535532
// If the throw is hot, try to use a more complicated inline mechanism
536533
// which keeps execution inside the compiled code.
537534
bool treat_throw_as_hot = false;
538-
ciMethodData* md = method()->method_data();
539535

540536
if (ProfileTraps) {
541537
if (too_many_traps(reason)) {
@@ -547,45 +543,55 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason) {
547543

548544
// Also, if there is a local exception handler, treat all throws
549545
// as hot if there has been at least one in this method.
550-
if (C->trap_count(reason) != 0
551-
&& method()->method_data()->trap_count(reason) != 0
552-
&& has_exception_handler()) {
553-
treat_throw_as_hot = true;
546+
if (C->trap_count(reason) != 0 && method()->method_data()->trap_count(reason) != 0 && has_exception_handler()) {
547+
treat_throw_as_hot = true;
554548
}
555549
}
550+
return {treat_throw_as_hot && method()->can_omit_stack_trace(), treat_throw_as_hot};
551+
}
552+
553+
//------------------------------builtin_throw----------------------------------
554+
void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, ciInstance* exception_object) {
555+
bool must_throw = true;
556+
Pair<bool, bool> applies_and_treat_throw_as_hot = builtin_throw_applies(reason);
557+
bool treat_throw_as_hot = applies_and_treat_throw_as_hot.second;
556558

557559
// If this throw happens frequently, an uncommon trap might cause
558560
// a performance pothole. If there is a local exception handler,
559561
// and if this particular bytecode appears to be deoptimizing often,
560562
// let us handle the throw inline, with a preconstructed instance.
561563
// Note: If the deopt count has blown up, the uncommon trap
562564
// runtime is going to flush this nmethod, not matter what.
563-
if (treat_throw_as_hot && method()->can_omit_stack_trace()) {
565+
if (applies_and_treat_throw_as_hot.first) {
564566
// If the throw is local, we use a pre-existing instance and
565567
// punt on the backtrace. This would lead to a missing backtrace
566568
// (a repeat of 4292742) if the backtrace object is ever asked
567569
// for its backtrace.
568570
// Fixing this remaining case of 4292742 requires some flavor of
569571
// escape analysis. Leave that for the future.
570572
ciInstance* ex_obj = nullptr;
571-
switch (reason) {
572-
case Deoptimization::Reason_null_check:
573-
ex_obj = env()->NullPointerException_instance();
574-
break;
575-
case Deoptimization::Reason_div0_check:
576-
ex_obj = env()->ArithmeticException_instance();
577-
break;
578-
case Deoptimization::Reason_range_check:
579-
ex_obj = env()->ArrayIndexOutOfBoundsException_instance();
580-
break;
581-
case Deoptimization::Reason_class_check:
582-
ex_obj = env()->ClassCastException_instance();
583-
break;
584-
case Deoptimization::Reason_array_check:
585-
ex_obj = env()->ArrayStoreException_instance();
586-
break;
587-
default:
588-
break;
573+
if (exception_object != nullptr) {
574+
ex_obj = exception_object;
575+
} else {
576+
switch (reason) {
577+
case Deoptimization::Reason_null_check:
578+
ex_obj = env()->NullPointerException_instance();
579+
break;
580+
case Deoptimization::Reason_div0_check:
581+
ex_obj = env()->ArithmeticException_instance();
582+
break;
583+
case Deoptimization::Reason_range_check:
584+
ex_obj = env()->ArrayIndexOutOfBoundsException_instance();
585+
break;
586+
case Deoptimization::Reason_class_check:
587+
ex_obj = env()->ClassCastException_instance();
588+
break;
589+
case Deoptimization::Reason_array_check:
590+
ex_obj = env()->ArrayStoreException_instance();
591+
break;
592+
default:
593+
break;
594+
}
589595
}
590596
if (failing()) { stop(); return; } // exception allocation might fail
591597
if (ex_obj != nullptr) {

Diff for: src/hotspot/share/opto/graphKit.hpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,10 @@ class GraphKit : public Phase {
275275

276276
// Helper to throw a built-in exception.
277277
// The JVMS must allow the bytecode to be re-executed via an uncommon trap.
278-
void builtin_throw(Deoptimization::DeoptReason reason);
278+
// If `exception_object` is nullptr, the exception to throw will be guessed based on `reason`
279+
void builtin_throw(Deoptimization::DeoptReason reason, ciInstance* exception_object = nullptr);
280+
// Returns the pair (builtin_throw_applies, throw_is_hot) for builtin_throw usage.
281+
Pair<bool, bool> builtin_throw_applies(Deoptimization::DeoptReason reason);
279282

280283
// Helper to check the JavaThread::_should_post_on_exceptions flag
281284
// and branch to an uncommon_trap if it is true (with the specified reason and must_throw)

Diff for: src/hotspot/share/opto/library_call.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -2017,7 +2017,7 @@ bool LibraryCallKit::inline_min_max(vmIntrinsics::ID id) {
20172017
return true;
20182018
}
20192019

2020-
void LibraryCallKit::inline_math_mathExact(Node* math, Node *test) {
2020+
void LibraryCallKit::inline_math_mathExact(Node* math, Node* test, bool use_builtin_throw) {
20212021
Node* bol = _gvn.transform( new BoolNode(test, BoolTest::overflow) );
20222022
IfNode* check = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN);
20232023
Node* fast_path = _gvn.transform( new IfFalseNode(check));
@@ -2031,8 +2031,12 @@ void LibraryCallKit::inline_math_mathExact(Node* math, Node *test) {
20312031
set_control(slow_path);
20322032
set_i_o(i_o());
20332033

2034-
uncommon_trap(Deoptimization::Reason_intrinsic,
2035-
Deoptimization::Action_maybe_recompile);
2034+
if (use_builtin_throw) {
2035+
builtin_throw(Deoptimization::Reason_intrinsic, env()->ArithmeticException_instance());
2036+
} else {
2037+
uncommon_trap(Deoptimization::Reason_intrinsic,
2038+
Deoptimization::Action_maybe_recompile);
2039+
}
20362040
}
20372041

20382042
set_control(fast_path);
@@ -2042,14 +2046,21 @@ void LibraryCallKit::inline_math_mathExact(Node* math, Node *test) {
20422046
template <typename OverflowOp>
20432047
bool LibraryCallKit::inline_math_overflow(Node* arg1, Node* arg2) {
20442048
typedef typename OverflowOp::MathOp MathOp;
2045-
if (too_many_traps(Deoptimization::Reason_intrinsic)) {
2049+
bool use_builtin_throw = false;
2050+
if (builtin_throw_applies(Deoptimization::Reason_intrinsic).first) {
2051+
// If builtin_throw would work (notably, the throw is hot and we don't care about backtraces),
2052+
// instead of bailing out on intrinsic or potentially deopting, let's do that!
2053+
use_builtin_throw = true;
2054+
} else if (too_many_traps(Deoptimization::Reason_intrinsic)) {
2055+
// It has been already too many times, but we cannot use builtin_throw care (e.g. we care about backtraces),
2056+
// so let's bail out intrinsic rather than risking deopting again.
20462057
return false;
20472058
}
20482059

20492060
MathOp* mathOp = new MathOp(arg1, arg2);
20502061
Node* operation = _gvn.transform( mathOp );
20512062
Node* ofcheck = _gvn.transform( new OverflowOp(arg1, arg2) );
2052-
inline_math_mathExact(operation, ofcheck);
2063+
inline_math_mathExact(operation, ofcheck, use_builtin_throw);
20532064
return true;
20542065
}
20552066

Diff for: src/hotspot/share/opto/library_call.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class LibraryCallKit : public GraphKit {
210210
bool inline_math_pow();
211211
template <typename OverflowOp>
212212
bool inline_math_overflow(Node* arg1, Node* arg2);
213-
void inline_math_mathExact(Node* math, Node* test);
213+
void inline_math_mathExact(Node* math, Node* test, bool use_builtin_throw);
214214
bool inline_math_addExactI(bool is_increment);
215215
bool inline_math_addExactL(bool is_increment);
216216
bool inline_math_multiplyExactI();

0 commit comments

Comments
 (0)