@@ -1586,39 +1586,6 @@ void ConnectionGraph::add_objload_to_connection_graph(Node *n, Unique_Node_List
15861586 }
15871587}
15881588
1589- void ConnectionGraph::add_proj (Node* n, Unique_Node_List* delayed_worklist) {
1590- if (n->as_Proj ()->_con == TypeFunc::Parms && n->in (0 )->is_Call () && n->in (0 )->as_Call ()->returns_pointer ()) {
1591- add_local_var_and_edge (n, PointsToNode::NoEscape, n->in (0 ), delayed_worklist);
1592- } else if (n->in (0 )->is_LoadFlat ()) {
1593- // Treat LoadFlat outputs similar to a call return value
1594- add_local_var_and_edge (n, PointsToNode::NoEscape, n->in (0 ), delayed_worklist);
1595- } else if (n->as_Proj ()->_con >= TypeFunc::Parms && n->in (0 )->is_Call () && n->bottom_type ()->isa_ptr ()) {
1596- CallNode* call = n->in (0 )->as_Call ();
1597- assert (call->tf ()->returns_inline_type_as_fields (), " " );
1598- ciMethod* meth = n->in (0 )->as_CallJava ()->method ();
1599- BCEscapeAnalyzer* call_analyzer = (meth != nullptr ) ? meth->get_bcea () : nullptr ;
1600- const TypeTuple* d = call->tf ()->domain_sig ();
1601- uint i = d->cnt ();
1602- if (call_analyzer != nullptr ) {
1603- for (i = TypeFunc::Parms; i < d->cnt (); i++) {
1604- if (d->field_at (i)->isa_ptr () != nullptr &&
1605- call_analyzer->is_arg_returned (i - TypeFunc::Parms)) {
1606- break ;
1607- }
1608- }
1609- }
1610- if (n->as_Proj ()->_con == TypeFunc::Parms || i >= d->cnt () || !scalarized_arg_with_compatible_return (call->as_CallJava (), i)) {
1611- // either:
1612- // - not an argument returned
1613- // - the returned buffer for a returned scalarized argument
1614- // - an incompatible returned scalarized argument
1615- add_local_var_and_edge (n, PointsToNode::NoEscape, n->in (0 ), delayed_worklist);
1616- } else {
1617- add_local_var (n, PointsToNode::NoEscape);
1618- }
1619- }
1620- }
1621-
16221589// Populate Connection Graph with PointsTo nodes and create simple
16231590// connection graph edges.
16241591void ConnectionGraph::add_node_to_connection_graph (Node *n, Unique_Node_List *delayed_worklist) {
@@ -1782,7 +1749,15 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de
17821749 break ;
17831750 case Op_Proj: {
17841751 // we are only interested in the oop result projection from a call
1785- add_proj (n, delayed_worklist);
1752+ if (n->as_Proj ()->_con >= TypeFunc::Parms && n->in (0 )->is_Call () &&
1753+ (n->in (0 )->as_Call ()->returns_pointer () || n->bottom_type ()->isa_ptr ())) {
1754+ assert ((n->as_Proj ()->_con == TypeFunc::Parms && n->in (0 )->as_Call ()->returns_pointer ()) ||
1755+ n->in (0 )->as_Call ()->tf ()->returns_inline_type_as_fields (), " what kind of oop return is it?" );
1756+ add_local_var_and_edge (n, PointsToNode::NoEscape, n->in (0 ), delayed_worklist);
1757+ } else if (n->as_Proj ()->_con >= TypeFunc::Parms && n->in (0 )->is_LoadFlat () && igvn->type (n)->isa_ptr ()) {
1758+ // Treat LoadFlat outputs similar to a call return value
1759+ add_local_var_and_edge (n, PointsToNode::NoEscape, n->in (0 ), delayed_worklist);
1760+ }
17861761 break ;
17871762 }
17881763 case Op_Rethrow: // Exception object escapes
@@ -1952,7 +1927,15 @@ void ConnectionGraph::add_final_edges(Node *n) {
19521927 break ;
19531928 }
19541929 case Op_Proj: {
1955- add_proj (n, nullptr );
1930+ if (n->in (0 )->is_Call ()) {
1931+ // we are only interested in the oop result projection from a call
1932+ assert ((n->as_Proj ()->_con == TypeFunc::Parms && n->in (0 )->as_Call ()->returns_pointer ()) ||
1933+ n->in (0 )->as_Call ()->tf ()->returns_inline_type_as_fields (), " what kind of oop return is it?" );
1934+ add_local_var_and_edge (n, PointsToNode::NoEscape, n->in (0 ), nullptr );
1935+ } else if (n->in (0 )->is_LoadFlat ()) {
1936+ // Treat LoadFlat outputs similar to a call return value
1937+ add_local_var_and_edge (n, PointsToNode::NoEscape, n->in (0 ), nullptr );
1938+ }
19561939 break ;
19571940 }
19581941 case Op_Rethrow: // Exception object escapes
@@ -2146,8 +2129,6 @@ class DomainIterator : public StackObj {
21462129 uint _i_domain_cc;
21472130 int _i_sig_cc;
21482131 uint _depth;
2149- uint _first_field_pos;
2150- const bool _is_static;
21512132
21522133 void next_helper () {
21532134 if (_sig_cc == nullptr ) {
@@ -2156,22 +2137,14 @@ class DomainIterator : public StackObj {
21562137 BasicType prev_bt = _i_sig_cc > 0 ? _sig_cc->at (_i_sig_cc-1 )._bt : T_ILLEGAL;
21572138 while (_i_sig_cc < _sig_cc->length ()) {
21582139 BasicType bt = _sig_cc->at (_i_sig_cc)._bt ;
2159- assert (bt != T_VOID || _sig_cc->at (_i_sig_cc-1 )._bt == prev_bt, " incorrect prev bt " );
2140+ assert (bt != T_VOID || _sig_cc->at (_i_sig_cc-1 )._bt == prev_bt, " " );
21602141 if (bt == T_METADATA) {
2161- if (_depth == 0 ) {
2162- _first_field_pos = _i_domain_cc;
2163- }
21642142 _depth++;
21652143 } else if (bt == T_VOID && (prev_bt != T_LONG && prev_bt != T_DOUBLE)) {
21662144 _depth--;
21672145 if (_depth == 0 ) {
21682146 _i_domain++;
21692147 }
2170- } else if (bt == T_BOOLEAN && prev_bt == T_METADATA && (_is_static || _i_domain > 0 ) && _sig_cc->at (_i_sig_cc)._offset == -1 ) {
2171- assert (_sig_cc->at (_i_sig_cc)._null_marker , " null marker expected right after T_METADATA" );
2172- assert (_depth == 1 , " only root value null marker" );
2173- _i_domain_cc++;
2174- _first_field_pos = _i_domain_cc;
21752148 } else {
21762149 return ;
21772150 }
@@ -2189,9 +2162,7 @@ class DomainIterator : public StackObj {
21892162 _i_domain(TypeFunc::Parms),
21902163 _i_domain_cc(TypeFunc::Parms),
21912164 _i_sig_cc(0 ),
2192- _depth(0 ),
2193- _first_field_pos(0 ),
2194- _is_static(call->method ()->is_static()) {
2165+ _depth(0 ) {
21952166 next_helper ();
21962167 }
21972168
@@ -2226,11 +2197,6 @@ class DomainIterator : public StackObj {
22262197 const Type* current_domain_cc () const {
22272198 return _domain_cc->field_at (_i_domain_cc);
22282199 }
2229-
2230- uint first_field_pos () const {
2231- assert (_first_field_pos >= TypeFunc::Parms, " not yet updated?" );
2232- return _first_field_pos;
2233- }
22342200};
22352201
22362202void ConnectionGraph::add_call_node (CallNode* call) {
@@ -2342,25 +2308,21 @@ void ConnectionGraph::add_call_node(CallNode* call) {
23422308 add_java_object (call, PointsToNode::NoEscape);
23432309 set_not_scalar_replaceable (ptnode_adr (call_idx) NOT_PRODUCT (COMMA " is result of call" ));
23442310 } else {
2311+ bool ret_arg = false ;
23452312 // Determine whether any arguments are returned.
2346- const TypeTuple* d = call->tf ()->domain_sig ();
2347- uint i = TypeFunc::Parms;
2348- for (; i < d->cnt (); i++) {
2349- if (d->field_at (i)->isa_ptr () != nullptr &&
2350- call_analyzer->is_arg_returned (i - TypeFunc::Parms)) {
2313+ for (DomainIterator di (call->as_CallJava ()); di.has_next (); di.next ()) {
2314+ uint arg = di.i_domain () - TypeFunc::Parms;
2315+ if (di.current_domain_cc ()->isa_ptr () != nullptr &&
2316+ call_analyzer->is_arg_returned (arg) &&
2317+ !meth->is_scalarized_arg (arg)) {
2318+ ret_arg = true ;
23512319 break ;
23522320 }
23532321 }
2354- // For non scalarized argument/return: add_proj() adds an edge between the return projection and the call,
2355- // process_call_arguments() adds an edge between the call and the argument
2356- // For scalarized argument/return: process_call_arguments() adds an edge between a call projection for a field
2357- // and the argument input to the call for that field. An edge is added between the projection for the returned
2358- // buffer and the call.
2359- if (i < d->cnt () && !scalarized_arg_with_compatible_return (call->as_CallJava (), i)) {
2360- // returns non scalarized argument or incompatible return
2322+ if (ret_arg) {
23612323 add_local_var (call, PointsToNode::ArgEscape);
23622324 } else {
2363- // Returns unknown object or scalarized argument being returned
2325+ // Returns unknown object.
23642326 map_ideal_node (call, phantom_obj);
23652327 }
23662328 }
@@ -2373,16 +2335,6 @@ void ConnectionGraph::add_call_node(CallNode* call) {
23732335 }
23742336}
23752337
2376- // Check that the return type is compatible with the type of the argument being returned i.e. that there's no cast that
2377- // fails in the method
2378- bool ConnectionGraph::scalarized_arg_with_compatible_return (CallJavaNode* call, uint k) {
2379- ciMethod* meth = call->method ();
2380- BCEscapeAnalyzer* call_analyzer = meth->get_bcea ();
2381- assert (call_analyzer->is_arg_returned (k - TypeFunc::Parms), " only for returned arg" );
2382- return meth->is_scalarized_arg (k - TypeFunc::Parms) &&
2383- call->tf ()->domain_sig ()->field_at (k)->meet (TypePtr::NULL_PTR)->higher_equal (call->tf ()->range_sig ()->field_at (TypeFunc::Parms));
2384- }
2385-
23862338void ConnectionGraph::process_call_arguments (CallNode *call) {
23872339 bool is_arraycopy = false ;
23882340 switch (call->Opcode ()) {
@@ -2575,27 +2527,11 @@ void ConnectionGraph::process_call_arguments(CallNode *call) {
25752527 const Type* at = di.current_domain_cc ();
25762528 Node* arg = call->in (di.i_domain_cc ());
25772529 PointsToNode* arg_ptn = ptnode_adr (arg->_idx );
2578- assert (!call_analyzer->is_arg_returned (k) || !scalarized_arg_with_compatible_return (call->as_CallJava (), di.i_domain ()) ||
2579- call->proj_out_or_null (di.i_domain_cc () - di.first_field_pos () + TypeFunc::Parms + 1 ) == nullptr ||
2580- _igvn->type (call->proj_out_or_null (di.i_domain_cc () - di.first_field_pos () + TypeFunc::Parms + 1 )) == at,
2581- " scalarized return and scalarized argument should match" );
25822530 if (at->isa_ptr () != nullptr &&
2583- call_analyzer->is_arg_returned (k)) {
2531+ call_analyzer->is_arg_returned (k) &&
2532+ !meth->is_scalarized_arg (k)) {
25842533 // The call returns arguments.
2585- if (scalarized_arg_with_compatible_return (call->as_CallJava (), di.i_domain ())) {
2586- ProjNode* res_proj = call->proj_out_or_null (di.i_domain_cc () - di.first_field_pos () + TypeFunc::Parms + 1 );
2587- if (res_proj != nullptr ) {
2588- assert (_igvn->type (res_proj)->isa_ptr (), " scalarized return and scalarized argument should match" );
2589- if (res_proj->_con != TypeFunc::Parms) {
2590- // add an edge between the result projection for a field and the argument projection for the same argument field
2591- PointsToNode* proj_ptn = ptnode_adr (res_proj->_idx );
2592- add_edge (proj_ptn, arg_ptn);
2593- if (!call_analyzer->is_return_local ()) {
2594- add_edge (proj_ptn, phantom_obj);
2595- }
2596- }
2597- }
2598- } else if (call_ptn != nullptr ) { // Is call's result used?
2534+ if (call_ptn != nullptr ) { // Is call's result used?
25992535 assert (call_ptn->is_LocalVar (), " node should be registered" );
26002536 assert (arg_ptn != nullptr , " node should be registered" );
26012537 add_edge (call_ptn, arg_ptn);
0 commit comments