Adding the following assert triggers when running TestDeoptimizationWhenBuffering.java and suggests that an inline type allocation is kept alive by the return:
--- a/src/hotspot/share/opto/compile.cpp
+++ b/src/hotspot/share/opto/compile.cpp
@@ -1933,12 +1933,14 @@ static bool return_val_keeps_allocations_alive(Node* ret_val) {
Unique_Node_List wq;
wq.push(ret_val);
bool some_allocations = false;
+ bool fail = false;
+ Unique_Node_List allocs;
for (uint i = 0; i < wq.size(); i++) {
Node* n = wq.at(i);
assert(!n->is_InlineType(), "chain of inline type nodes");
if (n->outcnt() > 1) {
// Some other use for the allocation
- return false;
+ fail = true;
} else if (n->is_InlineTypePtr()) {
wq.push(n->in(1));
} else if (n->is_Phi()) {
@@ -1949,8 +1951,24 @@ static bool return_val_keeps_allocations_alive(Node* ret_val) {
n->in(1)->is_Proj() &&
n->in(1)->in(0)->is_Allocate()) {
some_allocations = true;
+ allocs.push(n);
}
}
+ if (fail && some_allocations) {
+ while (allocs.size() > 0) {
+ Node* alloc = allocs.pop();
+ while (alloc->outcnt() == 1) {
+ alloc = alloc->unique_out();
+ if (alloc == ret_val) {
+ ret_val->dump(5);
+ assert(false, "FAIL");
+ }
+ }
+ }
+ }
+ if (fail) {
+ return false;
+ }
return some_allocations;
}
On the other hand, code in Compile::return_values is too conservative and replaces the oop by the tagged klass if the inline type is not always allocated. We should still return the oop, even if the inline type is only allocated in some return paths (of course, without keeping that allocation alive just for the return).
--- a/src/hotspot/share/opto/compile.cpp
+++ b/src/hotspot/share/opto/compile.cpp
@@ -1933,12 +1933,14 @@ static bool return_val_keeps_allocations_alive(Node* ret_val) {
Unique_Node_List wq;
wq.push(ret_val);
bool some_allocations = false;
+ bool fail = false;
+ Unique_Node_List allocs;
for (uint i = 0; i < wq.size(); i++) {
Node* n = wq.at(i);
assert(!n->is_InlineType(), "chain of inline type nodes");
if (n->outcnt() > 1) {
// Some other use for the allocation
- return false;
+ fail = true;
} else if (n->is_InlineTypePtr()) {
wq.push(n->in(1));
} else if (n->is_Phi()) {
@@ -1949,8 +1951,24 @@ static bool return_val_keeps_allocations_alive(Node* ret_val) {
n->in(1)->is_Proj() &&
n->in(1)->in(0)->is_Allocate()) {
some_allocations = true;
+ allocs.push(n);
}
}
+ if (fail && some_allocations) {
+ while (allocs.size() > 0) {
+ Node* alloc = allocs.pop();
+ while (alloc->outcnt() == 1) {
+ alloc = alloc->unique_out();
+ if (alloc == ret_val) {
+ ret_val->dump(5);
+ assert(false, "FAIL");
+ }
+ }
+ }
+ }
+ if (fail) {
+ return false;
+ }
return some_allocations;
}
On the other hand, code in Compile::return_values is too conservative and replaces the oop by the tagged klass if the inline type is not always allocated. We should still return the oop, even if the inline type is only allocated in some return paths (of course, without keeping that allocation alive just for the return).
- relates to
-
JDK-8215560 [lworld] Investigate if method handle calls can be further optimized
-
- Resolved
-