New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8261137: Optimization of Box nodes in uncommon_trap #2401
Changes from 5 commits
73be94c
4dfee52
4c62ec8
e80e495
84290ae
2032493
a82410c
3934fd9
4c1b503
2f0276c
fee961b
9fe85cf
31f215b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. | ||
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. | ||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
* | ||
* This code is free software; you can redistribute it and/or modify it | ||
|
@@ -554,6 +554,56 @@ void LateInlineVirtualCallGenerator::do_late_inline() { | |
CallGenerator::do_late_inline_helper(); | ||
} | ||
|
||
// replace box node to scalar node only in case it is directly referenced by debug info | ||
static void replace_box_to_scalar(CallNode* call, Node* resproj) { | ||
if (resproj != nullptr && call->is_CallStaticJava() && | ||
call->as_CallStaticJava()->is_boxing_method()) { | ||
Unique_Node_List debuginfo_node_list; | ||
for (DUIterator_Fast imax, i = resproj->fast_outs(imax); i < imax; i++) { | ||
Node* m = resproj->fast_out(i); | ||
if (m->is_SafePoint()) { | ||
SafePointNode* sfpt = m->as_SafePoint(); | ||
uint dbg_start = sfpt->is_Call() ? sfpt->as_Call()->tf()->domain()->cnt() : (uint)TypeFunc::Parms+1; | ||
for (uint i = 0; i < dbg_start; i++) { | ||
if (sfpt->in(i) == resproj) { | ||
return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this code can be replaced by:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I will do that. |
||
} | ||
} | ||
debuginfo_node_list.push(m); | ||
} else { | ||
return; | ||
} | ||
} | ||
|
||
GraphKit kit(call->jvms()); | ||
PhaseGVN& gvn = kit.gvn(); | ||
// delay box in runtime, treat box as a scalarized object | ||
while (debuginfo_node_list.size() > 0) { | ||
ProjNode* res = resproj->as_Proj(); | ||
Node* debuginfo_node = debuginfo_node_list.pop(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. |
||
|
||
ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); | ||
int n_fields = klass->nof_nonstatic_fields(); | ||
assert(n_fields == 1, "the klass must be an auto-boxing klass"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code can be put in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These codes are similar to #853 (comment) , so I put |
||
|
||
uint first_ind = (debuginfo_node->req() - debuginfo_node->jvms()->scloff()); | ||
Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), | ||
#ifdef ASSERT | ||
call->isa_Allocate(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is always There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was my suggestion to pass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for your review. I will change the SafePointScalarObject constructor in next push. |
||
#endif // ASSERT | ||
first_ind, n_fields, true); | ||
sobj->init_req(0, kit.root()); | ||
debuginfo_node->add_req(call->in(res->_con)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand why you are selecting the input based on the result projection field There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for your review. I use |
||
sobj = gvn.transform(sobj); | ||
JVMState* jvms = debuginfo_node->jvms(); | ||
jvms->set_endoff(debuginfo_node->req()); | ||
int start = jvms->debug_start(); | ||
int end = jvms->debug_end(); | ||
debuginfo_node->replace_edges_in_range(res, sobj, start, end); | ||
} | ||
} | ||
} | ||
|
||
void CallGenerator::do_late_inline_helper() { | ||
assert(is_late_inline(), "only late inline allowed"); | ||
|
||
|
@@ -603,6 +653,8 @@ void CallGenerator::do_late_inline_helper() { | |
C->remove_macro_node(call); | ||
} | ||
|
||
replace_box_to_scalar(call, callprojs.resproj); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be guarded by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly. I will change that. |
||
|
||
bool result_not_used = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0); | ||
if (is_pure_call() && result_not_used) { | ||
// The call is marked as pure (no important side effects), but result isn't used. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -500,6 +500,7 @@ class SafePointScalarObjectNode: public TypeNode { | |
// states of the scalarized object fields are collected. | ||
// It is relative to the last (youngest) jvms->_scloff. | ||
uint _n_fields; // Number of non-static fields of the scalarized object. | ||
bool _is_auto_box; // is the scalarized object is auto box. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo in comment. Should be something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for your review. I'll add this in my next patch. |
||
DEBUG_ONLY(AllocateNode* _alloc;) | ||
|
||
virtual uint hash() const ; // { return NO_HASH; } | ||
|
@@ -512,7 +513,7 @@ class SafePointScalarObjectNode: public TypeNode { | |
#ifdef ASSERT | ||
AllocateNode* alloc, | ||
#endif | ||
uint first_index, uint n_fields); | ||
uint first_index, uint n_fields, bool is_auto_box = false); | ||
virtual int Opcode() const; | ||
virtual uint ideal_reg() const; | ||
virtual const RegMask &in_RegMask(uint) const; | ||
|
@@ -525,6 +526,7 @@ class SafePointScalarObjectNode: public TypeNode { | |
} | ||
uint n_fields() const { return _n_fields; } | ||
|
||
bool is_auto_box() const { return _is_auto_box; } | ||
#ifdef ASSERT | ||
AllocateNode* alloc() const { return _alloc; } | ||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename this to
safepoints
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.