Mercurial > hg > truffle
annotate src/share/vm/opto/escape.cpp @ 4710:41406797186b
7113012: G1: rename not-fully-young GCs as "mixed"
Summary: Renamed partially-young GCs as mixed and fully-young GCs as young. Change all external output that includes those terms (GC log and GC ergo log) as well as any comments, fields, methods, etc. The changeset also includes very minor code tidying up (added some curly brackets).
Reviewed-by: johnc, brutisso
author | tonyp |
---|---|
date | Fri, 16 Dec 2011 02:14:27 -0500 |
parents | cc81b9c09bbb |
children | 1dc233a8c7fe |
rev | line source |
---|---|
0 | 1 /* |
2249 | 2 * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1539
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1539
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1539
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "ci/bcEscapeAnalyzer.hpp" | |
27 #include "libadt/vectset.hpp" | |
28 #include "memory/allocation.hpp" | |
29 #include "opto/c2compiler.hpp" | |
30 #include "opto/callnode.hpp" | |
31 #include "opto/cfgnode.hpp" | |
32 #include "opto/compile.hpp" | |
33 #include "opto/escape.hpp" | |
34 #include "opto/phaseX.hpp" | |
35 #include "opto/rootnode.hpp" | |
0 | 36 |
37 void PointsToNode::add_edge(uint targIdx, PointsToNode::EdgeType et) { | |
38 uint v = (targIdx << EdgeShift) + ((uint) et); | |
39 if (_edges == NULL) { | |
40 Arena *a = Compile::current()->comp_arena(); | |
41 _edges = new(a) GrowableArray<uint>(a, INITIAL_EDGE_COUNT, 0, 0); | |
42 } | |
43 _edges->append_if_missing(v); | |
44 } | |
45 | |
46 void PointsToNode::remove_edge(uint targIdx, PointsToNode::EdgeType et) { | |
47 uint v = (targIdx << EdgeShift) + ((uint) et); | |
48 | |
49 _edges->remove(v); | |
50 } | |
51 | |
52 #ifndef PRODUCT | |
77 | 53 static const char *node_type_names[] = { |
0 | 54 "UnknownType", |
55 "JavaObject", | |
56 "LocalVar", | |
57 "Field" | |
58 }; | |
59 | |
77 | 60 static const char *esc_names[] = { |
0 | 61 "UnknownEscape", |
65 | 62 "NoEscape", |
63 "ArgEscape", | |
64 "GlobalEscape" | |
0 | 65 }; |
66 | |
77 | 67 static const char *edge_type_suffix[] = { |
0 | 68 "?", // UnknownEdge |
69 "P", // PointsToEdge | |
70 "D", // DeferredEdge | |
71 "F" // FieldEdge | |
72 }; | |
73 | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
74 void PointsToNode::dump(bool print_state) const { |
0 | 75 NodeType nt = node_type(); |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
76 tty->print("%s ", node_type_names[(int) nt]); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
77 if (print_state) { |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
78 EscapeState es = escape_state(); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
79 tty->print("%s %s ", esc_names[(int) es], _scalar_replaceable ? "":"NSR"); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
80 } |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
81 tty->print("[["); |
0 | 82 for (uint i = 0; i < edge_count(); i++) { |
83 tty->print(" %d%s", edge_target(i), edge_type_suffix[(int) edge_type(i)]); | |
84 } | |
85 tty->print("]] "); | |
86 if (_node == NULL) | |
87 tty->print_cr("<null>"); | |
88 else | |
89 _node->dump(); | |
90 } | |
91 #endif | |
92 | |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
93 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
94 _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
95 _processed(C->comp_arena()), |
2249 | 96 pt_ptset(C->comp_arena()), |
97 pt_visited(C->comp_arena()), | |
98 pt_worklist(C->comp_arena(), 4, 0, 0), | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
99 _collecting(true), |
1921 | 100 _progress(false), |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
101 _compile(C), |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
102 _igvn(igvn), |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
103 _node_map(C->comp_arena()) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
104 |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
105 _phantom_object = C->top()->_idx, |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
106 add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
107 |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
108 // Add ConP(#NULL) and ConN(#NULL) nodes. |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
109 Node* oop_null = igvn->zerocon(T_OBJECT); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
110 _oop_null = oop_null->_idx; |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
111 assert(_oop_null < nodes_size(), "should be created already"); |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
112 add_node(oop_null, PointsToNode::JavaObject, PointsToNode::NoEscape, true); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
113 |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
114 if (UseCompressedOops) { |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
115 Node* noop_null = igvn->zerocon(T_NARROWOOP); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
116 _noop_null = noop_null->_idx; |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
117 assert(_noop_null < nodes_size(), "should be created already"); |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
118 add_node(noop_null, PointsToNode::JavaObject, PointsToNode::NoEscape, true); |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
119 } else { |
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
120 _noop_null = _oop_null; // Should be initialized |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
121 } |
4113 | 122 _pcmp_neq = NULL; // Should be initialized |
123 _pcmp_eq = NULL; | |
0 | 124 } |
125 | |
126 void ConnectionGraph::add_pointsto_edge(uint from_i, uint to_i) { | |
127 PointsToNode *f = ptnode_adr(from_i); | |
128 PointsToNode *t = ptnode_adr(to_i); | |
129 | |
130 assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set"); | |
131 assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of PointsTo edge"); | |
132 assert(t->node_type() == PointsToNode::JavaObject, "invalid destination of PointsTo edge"); | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
133 if (to_i == _phantom_object) { // Quick test for most common object |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
134 if (f->has_unknown_ptr()) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
135 return; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
136 } else { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
137 f->set_has_unknown_ptr(); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
138 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
139 } |
1921 | 140 add_edge(f, to_i, PointsToNode::PointsToEdge); |
0 | 141 } |
142 | |
143 void ConnectionGraph::add_deferred_edge(uint from_i, uint to_i) { | |
144 PointsToNode *f = ptnode_adr(from_i); | |
145 PointsToNode *t = ptnode_adr(to_i); | |
146 | |
147 assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set"); | |
148 assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of Deferred edge"); | |
149 assert(t->node_type() == PointsToNode::LocalVar || t->node_type() == PointsToNode::Field, "invalid destination of Deferred edge"); | |
150 // don't add a self-referential edge, this can occur during removal of | |
151 // deferred edges | |
152 if (from_i != to_i) | |
1921 | 153 add_edge(f, to_i, PointsToNode::DeferredEdge); |
0 | 154 } |
155 | |
65 | 156 int ConnectionGraph::address_offset(Node* adr, PhaseTransform *phase) { |
157 const Type *adr_type = phase->type(adr); | |
158 if (adr->is_AddP() && adr_type->isa_oopptr() == NULL && | |
159 adr->in(AddPNode::Address)->is_Proj() && | |
160 adr->in(AddPNode::Address)->in(0)->is_Allocate()) { | |
161 // We are computing a raw address for a store captured by an Initialize | |
162 // compute an appropriate address type. AddP cases #3 and #5 (see below). | |
163 int offs = (int)phase->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot); | |
164 assert(offs != Type::OffsetBot || | |
165 adr->in(AddPNode::Address)->in(0)->is_AllocateArray(), | |
166 "offset must be a constant or it is initialization of array"); | |
167 return offs; | |
168 } | |
169 const TypePtr *t_ptr = adr_type->isa_ptr(); | |
0 | 170 assert(t_ptr != NULL, "must be a pointer type"); |
171 return t_ptr->offset(); | |
172 } | |
173 | |
174 void ConnectionGraph::add_field_edge(uint from_i, uint to_i, int offset) { | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
175 // Don't add fields to NULL pointer. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
176 if (is_null_ptr(from_i)) |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
177 return; |
0 | 178 PointsToNode *f = ptnode_adr(from_i); |
179 PointsToNode *t = ptnode_adr(to_i); | |
180 | |
181 assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set"); | |
182 assert(f->node_type() == PointsToNode::JavaObject, "invalid destination of Field edge"); | |
183 assert(t->node_type() == PointsToNode::Field, "invalid destination of Field edge"); | |
184 assert (t->offset() == -1 || t->offset() == offset, "conflicting field offsets"); | |
185 t->set_offset(offset); | |
186 | |
1921 | 187 add_edge(f, to_i, PointsToNode::FieldEdge); |
0 | 188 } |
189 | |
190 void ConnectionGraph::set_escape_state(uint ni, PointsToNode::EscapeState es) { | |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
191 // Don't change non-escaping state of NULL pointer. |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
192 if (is_null_ptr(ni)) |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
193 return; |
0 | 194 PointsToNode *npt = ptnode_adr(ni); |
195 PointsToNode::EscapeState old_es = npt->escape_state(); | |
196 if (es > old_es) | |
197 npt->set_escape_state(es); | |
198 } | |
199 | |
65 | 200 void ConnectionGraph::add_node(Node *n, PointsToNode::NodeType nt, |
201 PointsToNode::EscapeState es, bool done) { | |
202 PointsToNode* ptadr = ptnode_adr(n->_idx); | |
203 ptadr->_node = n; | |
204 ptadr->set_node_type(nt); | |
205 | |
206 // inline set_escape_state(idx, es); | |
207 PointsToNode::EscapeState old_es = ptadr->escape_state(); | |
208 if (es > old_es) | |
209 ptadr->set_escape_state(es); | |
210 | |
211 if (done) | |
212 _processed.set(n->_idx); | |
213 } | |
214 | |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
215 PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) { |
0 | 216 uint idx = n->_idx; |
217 PointsToNode::EscapeState es; | |
218 | |
65 | 219 // If we are still collecting or there were no non-escaping allocations |
220 // we don't know the answer yet | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
221 if (_collecting) |
0 | 222 return PointsToNode::UnknownEscape; |
223 | |
224 // if the node was created after the escape computation, return | |
225 // UnknownEscape | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
226 if (idx >= nodes_size()) |
0 | 227 return PointsToNode::UnknownEscape; |
228 | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
229 es = ptnode_adr(idx)->escape_state(); |
0 | 230 |
231 // if we have already computed a value, return it | |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
307
diff
changeset
|
232 if (es != PointsToNode::UnknownEscape && |
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
307
diff
changeset
|
233 ptnode_adr(idx)->node_type() == PointsToNode::JavaObject) |
0 | 234 return es; |
235 | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
236 // PointsTo() calls n->uncast() which can return a new ideal node. |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
237 if (n->uncast()->_idx >= nodes_size()) |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
238 return PointsToNode::UnknownEscape; |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
239 |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
240 PointsToNode::EscapeState orig_es = es; |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
241 |
0 | 242 // compute max escape state of anything this node could point to |
2249 | 243 for(VectorSetI i(PointsTo(n)); i.test() && es != PointsToNode::GlobalEscape; ++i) { |
0 | 244 uint pt = i.elem; |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
245 PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); |
0 | 246 if (pes > es) |
247 es = pes; | |
248 } | |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
249 if (orig_es != es) { |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
250 // cache the computed escape state |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
251 assert(es > orig_es, "should have computed an escape state"); |
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
252 set_escape_state(idx, es); |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
253 } // orig_es could be PointsToNode::UnknownEscape |
0 | 254 return es; |
255 } | |
256 | |
2249 | 257 VectorSet* ConnectionGraph::PointsTo(Node * n) { |
258 pt_ptset.Reset(); | |
259 pt_visited.Reset(); | |
260 pt_worklist.clear(); | |
0 | 261 |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
262 #ifdef ASSERT |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
263 Node *orig_n = n; |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
264 #endif |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
265 |
65 | 266 n = n->uncast(); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
267 PointsToNode* npt = ptnode_adr(n->_idx); |
0 | 268 |
269 // If we have a JavaObject, return just that object | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
270 if (npt->node_type() == PointsToNode::JavaObject) { |
2249 | 271 pt_ptset.set(n->_idx); |
272 return &pt_ptset; | |
0 | 273 } |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
274 #ifdef ASSERT |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
275 if (npt->_node == NULL) { |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
276 if (orig_n != n) |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
277 orig_n->dump(); |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
278 n->dump(); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
279 assert(npt->_node != NULL, "unregistered node"); |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
280 } |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
281 #endif |
2249 | 282 pt_worklist.push(n->_idx); |
283 while(pt_worklist.length() > 0) { | |
284 int ni = pt_worklist.pop(); | |
285 if (pt_visited.test_set(ni)) | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
286 continue; |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
287 |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
288 PointsToNode* pn = ptnode_adr(ni); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
289 // ensure that all inputs of a Phi have been processed |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
290 assert(!_collecting || !pn->_node->is_Phi() || _processed.test(ni),""); |
0 | 291 |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
292 int edges_processed = 0; |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
293 uint e_cnt = pn->edge_count(); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
294 for (uint e = 0; e < e_cnt; e++) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
295 uint etgt = pn->edge_target(e); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
296 PointsToNode::EdgeType et = pn->edge_type(e); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
297 if (et == PointsToNode::PointsToEdge) { |
2249 | 298 pt_ptset.set(etgt); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
299 edges_processed++; |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
300 } else if (et == PointsToNode::DeferredEdge) { |
2249 | 301 pt_worklist.push(etgt); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
302 edges_processed++; |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
303 } else { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
304 assert(false,"neither PointsToEdge or DeferredEdge"); |
0 | 305 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
306 } |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
307 if (edges_processed == 0) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
308 // no deferred or pointsto edges found. Assume the value was set |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
309 // outside this method. Add the phantom object to the pointsto set. |
2249 | 310 pt_ptset.set(_phantom_object); |
0 | 311 } |
312 } | |
2249 | 313 return &pt_ptset; |
0 | 314 } |
315 | |
101
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
316 void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) { |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
317 // This method is most expensive during ConnectionGraph construction. |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
318 // Reuse vectorSet and an additional growable array for deferred edges. |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
319 deferred_edges->clear(); |
2249 | 320 visited->Reset(); |
0 | 321 |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
322 visited->set(ni); |
0 | 323 PointsToNode *ptn = ptnode_adr(ni); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
324 assert(ptn->node_type() == PointsToNode::LocalVar || |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
325 ptn->node_type() == PointsToNode::Field, "sanity"); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
326 assert(ptn->edge_count() != 0, "should have at least phantom_object"); |
0 | 327 |
101
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
328 // Mark current edges as visited and move deferred edges to separate array. |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
329 for (uint i = 0; i < ptn->edge_count(); ) { |
65 | 330 uint t = ptn->edge_target(i); |
101
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
331 #ifdef ASSERT |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
332 assert(!visited->test_set(t), "expecting no duplications"); |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
333 #else |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
334 visited->set(t); |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
335 #endif |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
336 if (ptn->edge_type(i) == PointsToNode::DeferredEdge) { |
0 | 337 ptn->remove_edge(t, PointsToNode::DeferredEdge); |
101
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
338 deferred_edges->append(t); |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
339 } else { |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
340 i++; |
101
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
341 } |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
342 } |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
343 for (int next = 0; next < deferred_edges->length(); ++next) { |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
344 uint t = deferred_edges->at(next); |
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
345 PointsToNode *ptt = ptnode_adr(t); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
346 uint e_cnt = ptt->edge_count(); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
347 assert(e_cnt != 0, "should have at least phantom_object"); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
348 for (uint e = 0; e < e_cnt; e++) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
349 uint etgt = ptt->edge_target(e); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
350 if (visited->test_set(etgt)) |
101
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
351 continue; |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
352 |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
353 PointsToNode::EdgeType et = ptt->edge_type(e); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
354 if (et == PointsToNode::PointsToEdge) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
355 add_pointsto_edge(ni, etgt); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
356 } else if (et == PointsToNode::DeferredEdge) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
357 deferred_edges->append(etgt); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
358 } else { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
359 assert(false,"invalid connection graph"); |
0 | 360 } |
361 } | |
362 } | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
363 if (ptn->edge_count() == 0) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
364 // No pointsto edges found after deferred edges are removed. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
365 // For example, in the next case where call is replaced |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
366 // with uncommon trap and as result array's load references |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
367 // itself through deferred edges: |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
368 // |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
369 // A a = b[i]; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
370 // if (c!=null) a = c.foo(); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
371 // b[i] = a; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
372 // |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
373 // Assume the value was set outside this method and |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
374 // add edge to phantom object. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
375 add_pointsto_edge(ni, _phantom_object); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
376 } |
0 | 377 } |
378 | |
379 | |
380 // Add an edge to node given by "to_i" from any field of adr_i whose offset | |
381 // matches "offset" A deferred edge is added if to_i is a LocalVar, and | |
382 // a pointsto edge is added if it is a JavaObject | |
383 | |
384 void ConnectionGraph::add_edge_from_fields(uint adr_i, uint to_i, int offs) { | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
385 // No fields for NULL pointer. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
386 if (is_null_ptr(adr_i)) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
387 return; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
388 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
389 PointsToNode* an = ptnode_adr(adr_i); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
390 PointsToNode* to = ptnode_adr(to_i); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
391 bool deferred = (to->node_type() == PointsToNode::LocalVar); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
392 bool escaped = (to_i == _phantom_object) && (offs == Type::OffsetTop); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
393 if (escaped) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
394 // Values in fields escaped during call. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
395 assert(an->escape_state() >= PointsToNode::ArgEscape, "sanity"); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
396 offs = Type::OffsetBot; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
397 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
398 for (uint fe = 0; fe < an->edge_count(); fe++) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
399 assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
400 int fi = an->edge_target(fe); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
401 if (escaped) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
402 set_escape_state(fi, PointsToNode::GlobalEscape); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
403 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
404 PointsToNode* pf = ptnode_adr(fi); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
405 int po = pf->offset(); |
0 | 406 if (po == offs || po == Type::OffsetBot || offs == Type::OffsetBot) { |
407 if (deferred) | |
408 add_deferred_edge(fi, to_i); | |
409 else | |
410 add_pointsto_edge(fi, to_i); | |
411 } | |
412 } | |
413 } | |
414 | |
65 | 415 // Add a deferred edge from node given by "from_i" to any field of adr_i |
416 // whose offset matches "offset". | |
0 | 417 void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) { |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
418 // No fields for NULL pointer. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
419 if (is_null_ptr(adr_i)) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
420 return; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
421 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
422 if (adr_i == _phantom_object) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
423 // Add only one edge for unknown object. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
424 add_pointsto_edge(from_i, _phantom_object); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
425 return; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
426 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
427 PointsToNode* an = ptnode_adr(adr_i); |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
428 bool is_alloc = an->_node->is_Allocate(); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
429 for (uint fe = 0; fe < an->edge_count(); fe++) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
430 assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
431 int fi = an->edge_target(fe); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
432 PointsToNode* pf = ptnode_adr(fi); |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
433 int offset = pf->offset(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
434 if (!is_alloc) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
435 // Assume the field was set outside this method if it is not Allocation |
0 | 436 add_pointsto_edge(fi, _phantom_object); |
437 } | |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
438 if (offset == offs || offset == Type::OffsetBot || offs == Type::OffsetBot) { |
0 | 439 add_deferred_edge(from_i, fi); |
440 } | |
441 } | |
4113 | 442 // Some fields references (AddP) may still be missing |
443 // until Connection Graph construction is complete. | |
444 // For example, loads from RAW pointers with offset 0 | |
445 // which don't have AddP. | |
446 // A reference to phantom_object will be added if | |
447 // a field reference is still missing after completing | |
448 // Connection Graph (see remove_deferred()). | |
0 | 449 } |
450 | |
65 | 451 // Helper functions |
452 | |
453 static Node* get_addp_base(Node *addp) { | |
454 assert(addp->is_AddP(), "must be AddP"); | |
455 // | |
456 // AddP cases for Base and Address inputs: | |
457 // case #1. Direct object's field reference: | |
458 // Allocate | |
459 // | | |
460 // Proj #5 ( oop result ) | |
461 // | | |
462 // CheckCastPP (cast to instance type) | |
463 // | | | |
464 // AddP ( base == address ) | |
465 // | |
466 // case #2. Indirect object's field reference: | |
467 // Phi | |
468 // | | |
469 // CastPP (cast to instance type) | |
470 // | | | |
471 // AddP ( base == address ) | |
472 // | |
473 // case #3. Raw object's field reference for Initialize node: | |
474 // Allocate | |
475 // | | |
476 // Proj #5 ( oop result ) | |
477 // top | | |
478 // \ | | |
479 // AddP ( base == top ) | |
480 // | |
481 // case #4. Array's element reference: | |
482 // {CheckCastPP | CastPP} | |
483 // | | | | |
484 // | AddP ( array's element offset ) | |
485 // | | | |
486 // AddP ( array's offset ) | |
487 // | |
488 // case #5. Raw object's field reference for arraycopy stub call: | |
489 // The inline_native_clone() case when the arraycopy stub is called | |
490 // after the allocation before Initialize and CheckCastPP nodes. | |
491 // Allocate | |
492 // | | |
493 // Proj #5 ( oop result ) | |
494 // | | | |
495 // AddP ( base == address ) | |
496 // | |
77 | 497 // case #6. Constant Pool, ThreadLocal, CastX2P or |
498 // Raw object's field reference: | |
499 // {ConP, ThreadLocal, CastX2P, raw Load} | |
65 | 500 // top | |
501 // \ | | |
502 // AddP ( base == top ) | |
503 // | |
77 | 504 // case #7. Klass's field reference. |
505 // LoadKlass | |
506 // | | | |
507 // AddP ( base == address ) | |
508 // | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
509 // case #8. narrow Klass's field reference. |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
510 // LoadNKlass |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
511 // | |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
512 // DecodeN |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
513 // | | |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
514 // AddP ( base == address ) |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
515 // |
65 | 516 Node *base = addp->in(AddPNode::Base)->uncast(); |
517 if (base->is_top()) { // The AddP case #3 and #6. | |
518 base = addp->in(AddPNode::Address)->uncast(); | |
957 | 519 while (base->is_AddP()) { |
520 // Case #6 (unsafe access) may have several chained AddP nodes. | |
521 assert(base->in(AddPNode::Base)->is_top(), "expected unsafe access address only"); | |
522 base = base->in(AddPNode::Address)->uncast(); | |
523 } | |
65 | 524 assert(base->Opcode() == Op_ConP || base->Opcode() == Op_ThreadLocal || |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
525 base->Opcode() == Op_CastX2P || base->is_DecodeN() || |
77 | 526 (base->is_Mem() && base->bottom_type() == TypeRawPtr::NOTNULL) || |
527 (base->is_Proj() && base->in(0)->is_Allocate()), "sanity"); | |
0 | 528 } |
65 | 529 return base; |
530 } | |
531 | |
532 static Node* find_second_addp(Node* addp, Node* n) { | |
533 assert(addp->is_AddP() && addp->outcnt() > 0, "Don't process dead nodes"); | |
534 | |
535 Node* addp2 = addp->raw_out(0); | |
536 if (addp->outcnt() == 1 && addp2->is_AddP() && | |
537 addp2->in(AddPNode::Base) == n && | |
538 addp2->in(AddPNode::Address) == addp) { | |
539 | |
540 assert(addp->in(AddPNode::Base) == n, "expecting the same base"); | |
541 // | |
542 // Find array's offset to push it on worklist first and | |
543 // as result process an array's element offset first (pushed second) | |
544 // to avoid CastPP for the array's offset. | |
545 // Otherwise the inserted CastPP (LocalVar) will point to what | |
546 // the AddP (Field) points to. Which would be wrong since | |
547 // the algorithm expects the CastPP has the same point as | |
548 // as AddP's base CheckCastPP (LocalVar). | |
549 // | |
550 // ArrayAllocation | |
551 // | | |
552 // CheckCastPP | |
553 // | | |
554 // memProj (from ArrayAllocation CheckCastPP) | |
555 // | || | |
556 // | || Int (element index) | |
557 // | || | ConI (log(element size)) | |
558 // | || | / | |
559 // | || LShift | |
560 // | || / | |
561 // | AddP (array's element offset) | |
562 // | | | |
563 // | | ConI (array's offset: #12(32-bits) or #24(64-bits)) | |
564 // | / / | |
565 // AddP (array's offset) | |
566 // | | |
567 // Load/Store (memory operation on array's element) | |
568 // | |
569 return addp2; | |
570 } | |
571 return NULL; | |
0 | 572 } |
573 | |
574 // | |
575 // Adjust the type and inputs of an AddP which computes the | |
576 // address of a field of an instance | |
577 // | |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
578 bool ConnectionGraph::split_AddP(Node *addp, Node *base, PhaseGVN *igvn) { |
65 | 579 const TypeOopPtr *base_t = igvn->type(base)->isa_oopptr(); |
223 | 580 assert(base_t != NULL && base_t->is_known_instance(), "expecting instance oopptr"); |
0 | 581 const TypeOopPtr *t = igvn->type(addp)->isa_oopptr(); |
65 | 582 if (t == NULL) { |
583 // We are computing a raw address for a store captured by an Initialize | |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
584 // compute an appropriate address type (cases #3 and #5). |
65 | 585 assert(igvn->type(addp) == TypeRawPtr::NOTNULL, "must be raw pointer"); |
586 assert(addp->in(AddPNode::Address)->is_Proj(), "base of raw address must be result projection from allocation"); | |
306
af945ba2e739
6741738: TypePtr::add_offset() set incorrect offset when the add overflows
kvn
parents:
293
diff
changeset
|
587 intptr_t offs = (int)igvn->find_intptr_t_con(addp->in(AddPNode::Offset), Type::OffsetBot); |
65 | 588 assert(offs != Type::OffsetBot, "offset must be a constant"); |
589 t = base_t->add_offset(offs)->is_oopptr(); | |
590 } | |
223 | 591 int inst_id = base_t->instance_id(); |
592 assert(!t->is_known_instance() || t->instance_id() == inst_id, | |
0 | 593 "old type must be non-instance or match new type"); |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
594 |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
595 // The type 't' could be subclass of 'base_t'. |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
596 // As result t->offset() could be large then base_t's size and it will |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
597 // cause the failure in add_offset() with narrow oops since TypeOopPtr() |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
598 // constructor verifies correctness of the offset. |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
599 // |
605 | 600 // It could happened on subclass's branch (from the type profiling |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
601 // inlining) which was not eliminated during parsing since the exactness |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
602 // of the allocation type was not propagated to the subclass type check. |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
603 // |
988
7e309ecb83ce
6879362: assert(!klass_is_exact(),"only non-exact klass")
kvn
parents:
957
diff
changeset
|
604 // Or the type 't' could be not related to 'base_t' at all. |
7e309ecb83ce
6879362: assert(!klass_is_exact(),"only non-exact klass")
kvn
parents:
957
diff
changeset
|
605 // It could happened when CHA type is different from MDO type on a dead path |
7e309ecb83ce
6879362: assert(!klass_is_exact(),"only non-exact klass")
kvn
parents:
957
diff
changeset
|
606 // (for example, from instanceof check) which is not collapsed during parsing. |
7e309ecb83ce
6879362: assert(!klass_is_exact(),"only non-exact klass")
kvn
parents:
957
diff
changeset
|
607 // |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
608 // Do nothing for such AddP node and don't process its users since |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
609 // this code branch will go away. |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
610 // |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
611 if (!t->is_known_instance() && |
988
7e309ecb83ce
6879362: assert(!klass_is_exact(),"only non-exact klass")
kvn
parents:
957
diff
changeset
|
612 !base_t->klass()->is_subtype_of(t->klass())) { |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
613 return false; // bail out |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
614 } |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
615 |
0 | 616 const TypeOopPtr *tinst = base_t->add_offset(t->offset())->is_oopptr(); |
1062
dcdcc8c16e20
6896352: CTW fails hotspot/src/share/vm/opto/escape.cpp:1155
kvn
parents:
988
diff
changeset
|
617 // Do NOT remove the next line: ensure a new alias index is allocated |
dcdcc8c16e20
6896352: CTW fails hotspot/src/share/vm/opto/escape.cpp:1155
kvn
parents:
988
diff
changeset
|
618 // for the instance type. Note: C++ will not remove it since the call |
dcdcc8c16e20
6896352: CTW fails hotspot/src/share/vm/opto/escape.cpp:1155
kvn
parents:
988
diff
changeset
|
619 // has side effect. |
0 | 620 int alias_idx = _compile->get_alias_index(tinst); |
621 igvn->set_type(addp, tinst); | |
622 // record the allocation in the node map | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
623 assert(ptnode_adr(addp->_idx)->_node != NULL, "should be registered"); |
0 | 624 set_map(addp->_idx, get_map(base->_idx)); |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
625 |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
626 // Set addp's Base and Address to 'base'. |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
627 Node *abase = addp->in(AddPNode::Base); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
628 Node *adr = addp->in(AddPNode::Address); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
629 if (adr->is_Proj() && adr->in(0)->is_Allocate() && |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
630 adr->in(0)->_idx == (uint)inst_id) { |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
631 // Skip AddP cases #3 and #5. |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
632 } else { |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
633 assert(!abase->is_top(), "sanity"); // AddP case #3 |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
634 if (abase != base) { |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
635 igvn->hash_delete(addp); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
636 addp->set_req(AddPNode::Base, base); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
637 if (abase == adr) { |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
638 addp->set_req(AddPNode::Address, base); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
639 } else { |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
640 // AddP case #4 (adr is array's element offset AddP node) |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
641 #ifdef ASSERT |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
642 const TypeOopPtr *atype = igvn->type(adr)->isa_oopptr(); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
643 assert(adr->is_AddP() && atype != NULL && |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
644 atype->instance_id() == inst_id, "array's element offset should be processed first"); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
645 #endif |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
646 } |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
647 igvn->hash_insert(addp); |
0 | 648 } |
649 } | |
65 | 650 // Put on IGVN worklist since at least addp's type was changed above. |
651 record_for_optimizer(addp); | |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
652 return true; |
0 | 653 } |
654 | |
655 // | |
656 // Create a new version of orig_phi if necessary. Returns either the newly | |
2459
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
657 // created phi or an existing phi. Sets create_new to indicate whether a new |
0 | 658 // phi was created. Cache the last newly created phi in the node map. |
659 // | |
660 PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn, bool &new_created) { | |
661 Compile *C = _compile; | |
662 new_created = false; | |
663 int phi_alias_idx = C->get_alias_index(orig_phi->adr_type()); | |
664 // nothing to do if orig_phi is bottom memory or matches alias_idx | |
65 | 665 if (phi_alias_idx == alias_idx) { |
0 | 666 return orig_phi; |
667 } | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
668 // Have we recently created a Phi for this alias index? |
0 | 669 PhiNode *result = get_map_phi(orig_phi->_idx); |
670 if (result != NULL && C->get_alias_index(result->adr_type()) == alias_idx) { | |
671 return result; | |
672 } | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
673 // Previous check may fail when the same wide memory Phi was split into Phis |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
674 // for different memory slices. Search all Phis for this region. |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
675 if (result != NULL) { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
676 Node* region = orig_phi->in(0); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
677 for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
678 Node* phi = region->fast_out(i); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
679 if (phi->is_Phi() && |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
680 C->get_alias_index(phi->as_Phi()->adr_type()) == alias_idx) { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
681 assert(phi->_idx >= nodes_size(), "only new Phi per instance memory slice"); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
682 return phi->as_Phi(); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
683 } |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
684 } |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
685 } |
38
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
686 if ((int)C->unique() + 2*NodeLimitFudgeFactor > MaxNodeLimit) { |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
687 if (C->do_escape_analysis() == true && !C->failing()) { |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
688 // Retry compilation without escape analysis. |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
689 // If this is the first failure, the sentinel string will "stick" |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
690 // to the Compile object, and the C2Compiler will see it and retry. |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
691 C->record_failure(C2Compiler::retry_no_escape_analysis()); |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
692 } |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
693 return NULL; |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
694 } |
0 | 695 orig_phi_worklist.append_if_missing(orig_phi); |
65 | 696 const TypePtr *atype = C->get_adr_type(alias_idx); |
0 | 697 result = PhiNode::make(orig_phi->in(0), NULL, Type::MEMORY, atype); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
784
diff
changeset
|
698 C->copy_node_notes_to(result, orig_phi); |
0 | 699 igvn->set_type(result, result->bottom_type()); |
700 record_for_optimizer(result); | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
701 |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
702 debug_only(Node* pn = ptnode_adr(orig_phi->_idx)->_node;) |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
703 assert(pn == NULL || pn == orig_phi, "wrong node"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
704 set_map(orig_phi->_idx, result); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
705 ptnode_adr(orig_phi->_idx)->_node = orig_phi; |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
706 |
0 | 707 new_created = true; |
708 return result; | |
709 } | |
710 | |
711 // | |
2459
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
712 // Return a new version of Memory Phi "orig_phi" with the inputs having the |
0 | 713 // specified alias index. |
714 // | |
715 PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn) { | |
716 | |
717 assert(alias_idx != Compile::AliasIdxBot, "can't split out bottom memory"); | |
718 Compile *C = _compile; | |
719 bool new_phi_created; | |
65 | 720 PhiNode *result = create_split_phi(orig_phi, alias_idx, orig_phi_worklist, igvn, new_phi_created); |
0 | 721 if (!new_phi_created) { |
722 return result; | |
723 } | |
724 | |
725 GrowableArray<PhiNode *> phi_list; | |
726 GrowableArray<uint> cur_input; | |
727 | |
728 PhiNode *phi = orig_phi; | |
729 uint idx = 1; | |
730 bool finished = false; | |
731 while(!finished) { | |
732 while (idx < phi->req()) { | |
65 | 733 Node *mem = find_inst_mem(phi->in(idx), alias_idx, orig_phi_worklist, igvn); |
0 | 734 if (mem != NULL && mem->is_Phi()) { |
65 | 735 PhiNode *newphi = create_split_phi(mem->as_Phi(), alias_idx, orig_phi_worklist, igvn, new_phi_created); |
0 | 736 if (new_phi_created) { |
737 // found an phi for which we created a new split, push current one on worklist and begin | |
738 // processing new one | |
739 phi_list.push(phi); | |
740 cur_input.push(idx); | |
741 phi = mem->as_Phi(); | |
65 | 742 result = newphi; |
0 | 743 idx = 1; |
744 continue; | |
745 } else { | |
65 | 746 mem = newphi; |
0 | 747 } |
748 } | |
38
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
749 if (C->failing()) { |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
750 return NULL; |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
751 } |
0 | 752 result->set_req(idx++, mem); |
753 } | |
754 #ifdef ASSERT | |
755 // verify that the new Phi has an input for each input of the original | |
756 assert( phi->req() == result->req(), "must have same number of inputs."); | |
757 assert( result->in(0) != NULL && result->in(0) == phi->in(0), "regions must match"); | |
65 | 758 #endif |
759 // Check if all new phi's inputs have specified alias index. | |
760 // Otherwise use old phi. | |
0 | 761 for (uint i = 1; i < phi->req(); i++) { |
65 | 762 Node* in = result->in(i); |
763 assert((phi->in(i) == NULL) == (in == NULL), "inputs must correspond."); | |
0 | 764 } |
765 // we have finished processing a Phi, see if there are any more to do | |
766 finished = (phi_list.length() == 0 ); | |
767 if (!finished) { | |
768 phi = phi_list.pop(); | |
769 idx = cur_input.pop(); | |
65 | 770 PhiNode *prev_result = get_map_phi(phi->_idx); |
771 prev_result->set_req(idx++, result); | |
772 result = prev_result; | |
0 | 773 } |
774 } | |
775 return result; | |
776 } | |
777 | |
65 | 778 |
779 // | |
780 // The next methods are derived from methods in MemNode. | |
781 // | |
1815 | 782 static Node *step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop) { |
65 | 783 Node *mem = mmem; |
1815 | 784 // TypeOopPtr::NOTNULL+any is an OOP with unknown offset - generally |
65 | 785 // means an array I have not precisely typed yet. Do not do any |
786 // alias stuff with it any time soon. | |
1815 | 787 if( toop->base() != Type::AnyPtr && |
788 !(toop->klass() != NULL && | |
789 toop->klass()->is_java_lang_Object() && | |
790 toop->offset() == Type::OffsetBot) ) { | |
65 | 791 mem = mmem->memory_at(alias_idx); |
792 // Update input if it is progress over what we have now | |
793 } | |
794 return mem; | |
795 } | |
796 | |
797 // | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
798 // Move memory users to their memory slices. |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
799 // |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
800 void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis, PhaseGVN *igvn) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
801 Compile* C = _compile; |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
802 |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
803 const TypePtr* tp = igvn->type(n->in(MemNode::Address))->isa_ptr(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
804 assert(tp != NULL, "ptr type"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
805 int alias_idx = C->get_alias_index(tp); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
806 int general_idx = C->get_general_index(alias_idx); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
807 |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
808 // Move users first |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
809 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
810 Node* use = n->fast_out(i); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
811 if (use->is_MergeMem()) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
812 MergeMemNode* mmem = use->as_MergeMem(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
813 assert(n == mmem->memory_at(alias_idx), "should be on instance memory slice"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
814 if (n != mmem->memory_at(general_idx) || alias_idx == general_idx) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
815 continue; // Nothing to do |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
816 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
817 // Replace previous general reference to mem node. |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
818 uint orig_uniq = C->unique(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
819 Node* m = find_inst_mem(n, general_idx, orig_phis, igvn); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
820 assert(orig_uniq == C->unique(), "no new nodes"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
821 mmem->set_memory_at(general_idx, m); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
822 --imax; |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
823 --i; |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
824 } else if (use->is_MemBar()) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
825 assert(!use->is_Initialize(), "initializing stores should not be moved"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
826 if (use->req() > MemBarNode::Precedent && |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
827 use->in(MemBarNode::Precedent) == n) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
828 // Don't move related membars. |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
829 record_for_optimizer(use); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
830 continue; |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
831 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
832 tp = use->as_MemBar()->adr_type()->isa_ptr(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
833 if (tp != NULL && C->get_alias_index(tp) == alias_idx || |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
834 alias_idx == general_idx) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
835 continue; // Nothing to do |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
836 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
837 // Move to general memory slice. |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
838 uint orig_uniq = C->unique(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
839 Node* m = find_inst_mem(n, general_idx, orig_phis, igvn); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
840 assert(orig_uniq == C->unique(), "no new nodes"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
841 igvn->hash_delete(use); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
842 imax -= use->replace_edge(n, m); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
843 igvn->hash_insert(use); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
844 record_for_optimizer(use); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
845 --i; |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
846 #ifdef ASSERT |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
847 } else if (use->is_Mem()) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
848 if (use->Opcode() == Op_StoreCM && use->in(MemNode::OopStore) == n) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
849 // Don't move related cardmark. |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
850 continue; |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
851 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
852 // Memory nodes should have new memory input. |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
853 tp = igvn->type(use->in(MemNode::Address))->isa_ptr(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
854 assert(tp != NULL, "ptr type"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
855 int idx = C->get_alias_index(tp); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
856 assert(get_map(use->_idx) != NULL || idx == alias_idx, |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
857 "Following memory nodes should have new memory input or be on the same memory slice"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
858 } else if (use->is_Phi()) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
859 // Phi nodes should be split and moved already. |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
860 tp = use->as_Phi()->adr_type()->isa_ptr(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
861 assert(tp != NULL, "ptr type"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
862 int idx = C->get_alias_index(tp); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
863 assert(idx == alias_idx, "Following Phi nodes should be on the same memory slice"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
864 } else { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
865 use->dump(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
866 assert(false, "should not be here"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
867 #endif |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
868 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
869 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
870 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
871 |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
872 // |
65 | 873 // Search memory chain of "mem" to find a MemNode whose address |
874 // is the specified alias index. | |
875 // | |
876 Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArray<PhiNode *> &orig_phis, PhaseGVN *phase) { | |
877 if (orig_mem == NULL) | |
878 return orig_mem; | |
879 Compile* C = phase->C; | |
1815 | 880 const TypeOopPtr *toop = C->get_adr_type(alias_idx)->isa_oopptr(); |
881 bool is_instance = (toop != NULL) && toop->is_known_instance(); | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
882 Node *start_mem = C->start()->proj_out(TypeFunc::Memory); |
65 | 883 Node *prev = NULL; |
884 Node *result = orig_mem; | |
885 while (prev != result) { | |
886 prev = result; | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
887 if (result == start_mem) |
605 | 888 break; // hit one of our sentinels |
65 | 889 if (result->is_Mem()) { |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
890 const Type *at = phase->type(result->in(MemNode::Address)); |
2459
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
891 if (at == Type::TOP) |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
892 break; // Dead |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
893 assert (at->isa_ptr() != NULL, "pointer type required."); |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
894 int idx = C->get_alias_index(at->is_ptr()); |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
895 if (idx == alias_idx) |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
896 break; // Found |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
897 if (!is_instance && (at->isa_oopptr() == NULL || |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
898 !at->is_oopptr()->is_known_instance())) { |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
899 break; // Do not skip store to general memory slice. |
65 | 900 } |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
901 result = result->in(MemNode::Memory); |
65 | 902 } |
903 if (!is_instance) | |
904 continue; // don't search further for non-instance types | |
905 // skip over a call which does not affect this memory slice | |
906 if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) { | |
907 Node *proj_in = result->in(0); | |
1815 | 908 if (proj_in->is_Allocate() && proj_in->_idx == (uint)toop->instance_id()) { |
605 | 909 break; // hit one of our sentinels |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
910 } else if (proj_in->is_Call()) { |
65 | 911 CallNode *call = proj_in->as_Call(); |
1815 | 912 if (!call->may_modify(toop, phase)) { |
65 | 913 result = call->in(TypeFunc::Memory); |
914 } | |
915 } else if (proj_in->is_Initialize()) { | |
916 AllocateNode* alloc = proj_in->as_Initialize()->allocation(); | |
917 // Stop if this is the initialization for the object instance which | |
918 // which contains this memory slice, otherwise skip over it. | |
1815 | 919 if (alloc == NULL || alloc->_idx != (uint)toop->instance_id()) { |
65 | 920 result = proj_in->in(TypeFunc::Memory); |
921 } | |
922 } else if (proj_in->is_MemBar()) { | |
923 result = proj_in->in(TypeFunc::Memory); | |
924 } | |
925 } else if (result->is_MergeMem()) { | |
926 MergeMemNode *mmem = result->as_MergeMem(); | |
1815 | 927 result = step_through_mergemem(mmem, alias_idx, toop); |
65 | 928 if (result == mmem->base_memory()) { |
929 // Didn't find instance memory, search through general slice recursively. | |
930 result = mmem->memory_at(C->get_general_index(alias_idx)); | |
931 result = find_inst_mem(result, alias_idx, orig_phis, phase); | |
932 if (C->failing()) { | |
933 return NULL; | |
934 } | |
935 mmem->set_memory_at(alias_idx, result); | |
936 } | |
937 } else if (result->is_Phi() && | |
938 C->get_alias_index(result->as_Phi()->adr_type()) != alias_idx) { | |
939 Node *un = result->as_Phi()->unique_input(phase); | |
940 if (un != NULL) { | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
941 orig_phis.append_if_missing(result->as_Phi()); |
65 | 942 result = un; |
943 } else { | |
944 break; | |
945 } | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
946 } else if (result->is_ClearArray()) { |
1815 | 947 if (!ClearArrayNode::step_through(&result, (uint)toop->instance_id(), phase)) { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
948 // Can not bypass initialization of the instance |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
949 // we are looking for. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
950 break; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
951 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
952 // Otherwise skip it (the call updated 'result' value). |
584 | 953 } else if (result->Opcode() == Op_SCMemProj) { |
954 assert(result->in(0)->is_LoadStore(), "sanity"); | |
955 const Type *at = phase->type(result->in(0)->in(MemNode::Address)); | |
956 if (at != Type::TOP) { | |
957 assert (at->isa_ptr() != NULL, "pointer type required."); | |
958 int idx = C->get_alias_index(at->is_ptr()); | |
959 assert(idx != alias_idx, "Object is not scalar replaceable if a LoadStore node access its field"); | |
960 break; | |
961 } | |
962 result = result->in(0)->in(MemNode::Memory); | |
65 | 963 } |
964 } | |
247 | 965 if (result->is_Phi()) { |
65 | 966 PhiNode *mphi = result->as_Phi(); |
967 assert(mphi->bottom_type() == Type::MEMORY, "memory phi required"); | |
968 const TypePtr *t = mphi->adr_type(); | |
2459
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
969 if (!is_instance) { |
247 | 970 // Push all non-instance Phis on the orig_phis worklist to update inputs |
971 // during Phase 4 if needed. | |
972 orig_phis.append_if_missing(mphi); | |
2459
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
973 } else if (C->get_alias_index(t) != alias_idx) { |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
974 // Create a new Phi with the specified alias index type. |
55973726c600
6992789: assert(phi->_idx >= nodes_size()) failed: only new Phi per instance memory slice
kvn
parents:
2249
diff
changeset
|
975 result = split_memory_phi(mphi, alias_idx, orig_phis, phase); |
65 | 976 } |
977 } | |
978 // the result is either MemNode, PhiNode, InitializeNode. | |
979 return result; | |
980 } | |
981 | |
0 | 982 // |
983 // Convert the types of unescaped object to instance types where possible, | |
984 // propagate the new type information through the graph, and update memory | |
985 // edges and MergeMem inputs to reflect the new type. | |
986 // | |
987 // We start with allocations (and calls which may be allocations) on alloc_worklist. | |
988 // The processing is done in 4 phases: | |
989 // | |
990 // Phase 1: Process possible allocations from alloc_worklist. Create instance | |
991 // types for the CheckCastPP for allocations where possible. | |
992 // Propagate the the new types through users as follows: | |
993 // casts and Phi: push users on alloc_worklist | |
994 // AddP: cast Base and Address inputs to the instance type | |
995 // push any AddP users on alloc_worklist and push any memnode | |
996 // users onto memnode_worklist. | |
997 // Phase 2: Process MemNode's from memnode_worklist. compute new address type and | |
998 // search the Memory chain for a store with the appropriate type | |
999 // address type. If a Phi is found, create a new version with | |
605 | 1000 // the appropriate memory slices from each of the Phi inputs. |
0 | 1001 // For stores, process the users as follows: |
1002 // MemNode: push on memnode_worklist | |
1003 // MergeMem: push on mergemem_worklist | |
1004 // Phase 3: Process MergeMem nodes from mergemem_worklist. Walk each memory slice | |
1005 // moving the first node encountered of each instance type to the | |
1006 // the input corresponding to its alias index. | |
1007 // appropriate memory slice. | |
1008 // Phase 4: Update the inputs of non-instance memory Phis and the Memory input of memnodes. | |
1009 // | |
1010 // In the following example, the CheckCastPP nodes are the cast of allocation | |
1011 // results and the allocation of node 29 is unescaped and eligible to be an | |
1012 // instance type. | |
1013 // | |
1014 // We start with: | |
1015 // | |
1016 // 7 Parm #memory | |
1017 // 10 ConI "12" | |
1018 // 19 CheckCastPP "Foo" | |
1019 // 20 AddP _ 19 19 10 Foo+12 alias_index=4 | |
1020 // 29 CheckCastPP "Foo" | |
1021 // 30 AddP _ 29 29 10 Foo+12 alias_index=4 | |
1022 // | |
1023 // 40 StoreP 25 7 20 ... alias_index=4 | |
1024 // 50 StoreP 35 40 30 ... alias_index=4 | |
1025 // 60 StoreP 45 50 20 ... alias_index=4 | |
1026 // 70 LoadP _ 60 30 ... alias_index=4 | |
1027 // 80 Phi 75 50 60 Memory alias_index=4 | |
1028 // 90 LoadP _ 80 30 ... alias_index=4 | |
1029 // 100 LoadP _ 80 20 ... alias_index=4 | |
1030 // | |
1031 // | |
1032 // Phase 1 creates an instance type for node 29 assigning it an instance id of 24 | |
1033 // and creating a new alias index for node 30. This gives: | |
1034 // | |
1035 // 7 Parm #memory | |
1036 // 10 ConI "12" | |
1037 // 19 CheckCastPP "Foo" | |
1038 // 20 AddP _ 19 19 10 Foo+12 alias_index=4 | |
1039 // 29 CheckCastPP "Foo" iid=24 | |
1040 // 30 AddP _ 29 29 10 Foo+12 alias_index=6 iid=24 | |
1041 // | |
1042 // 40 StoreP 25 7 20 ... alias_index=4 | |
1043 // 50 StoreP 35 40 30 ... alias_index=6 | |
1044 // 60 StoreP 45 50 20 ... alias_index=4 | |
1045 // 70 LoadP _ 60 30 ... alias_index=6 | |
1046 // 80 Phi 75 50 60 Memory alias_index=4 | |
1047 // 90 LoadP _ 80 30 ... alias_index=6 | |
1048 // 100 LoadP _ 80 20 ... alias_index=4 | |
1049 // | |
1050 // In phase 2, new memory inputs are computed for the loads and stores, | |
1051 // And a new version of the phi is created. In phase 4, the inputs to | |
1052 // node 80 are updated and then the memory nodes are updated with the | |
1053 // values computed in phase 2. This results in: | |
1054 // | |
1055 // 7 Parm #memory | |
1056 // 10 ConI "12" | |
1057 // 19 CheckCastPP "Foo" | |
1058 // 20 AddP _ 19 19 10 Foo+12 alias_index=4 | |
1059 // 29 CheckCastPP "Foo" iid=24 | |
1060 // 30 AddP _ 29 29 10 Foo+12 alias_index=6 iid=24 | |
1061 // | |
1062 // 40 StoreP 25 7 20 ... alias_index=4 | |
1063 // 50 StoreP 35 7 30 ... alias_index=6 | |
1064 // 60 StoreP 45 40 20 ... alias_index=4 | |
1065 // 70 LoadP _ 50 30 ... alias_index=6 | |
1066 // 80 Phi 75 40 60 Memory alias_index=4 | |
1067 // 120 Phi 75 50 50 Memory alias_index=6 | |
1068 // 90 LoadP _ 120 30 ... alias_index=6 | |
1069 // 100 LoadP _ 80 20 ... alias_index=4 | |
1070 // | |
1071 void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) { | |
1072 GrowableArray<Node *> memnode_worklist; | |
1073 GrowableArray<PhiNode *> orig_phis; | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1074 |
1921 | 1075 PhaseIterGVN *igvn = _igvn; |
0 | 1076 uint new_index_start = (uint) _compile->num_alias_types(); |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1077 Arena* arena = Thread::current()->resource_area(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1078 VectorSet visited(arena); |
0 | 1079 |
65 | 1080 |
1081 // Phase 1: Process possible allocations from alloc_worklist. | |
1082 // Create instance types for the CheckCastPP for allocations where possible. | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1083 // |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1084 // (Note: don't forget to change the order of the second AddP node on |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1085 // the alloc_worklist if the order of the worklist processing is changed, |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1086 // see the comment in find_second_addp().) |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1087 // |
0 | 1088 while (alloc_worklist.length() != 0) { |
1089 Node *n = alloc_worklist.pop(); | |
1090 uint ni = n->_idx; | |
65 | 1091 const TypeOopPtr* tinst = NULL; |
0 | 1092 if (n->is_Call()) { |
1093 CallNode *alloc = n->as_Call(); | |
1094 // copy escape information to call node | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1095 PointsToNode* ptn = ptnode_adr(alloc->_idx); |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1096 PointsToNode::EscapeState es = escape_state(alloc); |
65 | 1097 // We have an allocation or call which returns a Java object, |
1098 // see if it is unescaped. | |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1099 if (es != PointsToNode::NoEscape || !ptn->scalar_replaceable()) |
0 | 1100 continue; |
784
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1101 |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1102 // Find CheckCastPP for the allocate or for the return value of a call |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1103 n = alloc->result_cast(); |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1104 if (n == NULL) { // No uses except Initialize node |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1105 if (alloc->is_Allocate()) { |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1106 // Set the scalar_replaceable flag for allocation |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1107 // so it could be eliminated if it has no uses. |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1108 alloc->as_Allocate()->_is_scalar_replaceable = true; |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1109 } |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1110 continue; |
39
76256d272075
6667612: (Escape Analysis) disable loop cloning if it has a scalar replaceable allocation
kvn
parents:
38
diff
changeset
|
1111 } |
784
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1112 if (!n->is_CheckCastPP()) { // not unique CheckCastPP. |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1113 assert(!alloc->is_Allocate(), "allocation should have unique type"); |
65 | 1114 continue; |
784
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1115 } |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1116 |
65 | 1117 // The inline code for Object.clone() casts the allocation result to |
247 | 1118 // java.lang.Object and then to the actual type of the allocated |
65 | 1119 // object. Detect this case and use the second cast. |
247 | 1120 // Also detect j.l.reflect.Array.newInstance(jobject, jint) case when |
1121 // the allocation result is cast to java.lang.Object and then | |
1122 // to the actual Array type. | |
65 | 1123 if (alloc->is_Allocate() && n->as_Type()->type() == TypeInstPtr::NOTNULL |
247 | 1124 && (alloc->is_AllocateArray() || |
1125 igvn->type(alloc->in(AllocateNode::KlassNode)) != TypeKlassPtr::OBJECT)) { | |
65 | 1126 Node *cast2 = NULL; |
1127 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { | |
1128 Node *use = n->fast_out(i); | |
1129 if (use->is_CheckCastPP()) { | |
1130 cast2 = use; | |
1131 break; | |
1132 } | |
1133 } | |
1134 if (cast2 != NULL) { | |
1135 n = cast2; | |
1136 } else { | |
784
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1137 // Non-scalar replaceable if the allocation type is unknown statically |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1138 // (reflection allocation), the object can't be restored during |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1139 // deoptimization without precise type. |
65 | 1140 continue; |
1141 } | |
1142 } | |
784
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1143 if (alloc->is_Allocate()) { |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1144 // Set the scalar_replaceable flag for allocation |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1145 // so it could be eliminated. |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1146 alloc->as_Allocate()->_is_scalar_replaceable = true; |
b2934faac289
6836054: java/util/Arrays/CopyMethods.java fails on solaris-sparc with IllegalArgumentException
kvn
parents:
605
diff
changeset
|
1147 } |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1148 set_escape_state(n->_idx, es); // CheckCastPP escape state |
247 | 1149 // in order for an object to be scalar-replaceable, it must be: |
65 | 1150 // - a direct allocation (not a call returning an object) |
1151 // - non-escaping | |
1152 // - eligible to be a unique type | |
1153 // - not determined to be ineligible by escape analysis | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1154 assert(ptnode_adr(alloc->_idx)->_node != NULL && |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1155 ptnode_adr(n->_idx)->_node != NULL, "should be registered"); |
0 | 1156 set_map(alloc->_idx, n); |
1157 set_map(n->_idx, alloc); | |
65 | 1158 const TypeOopPtr *t = igvn->type(n)->isa_oopptr(); |
1159 if (t == NULL) | |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1160 continue; // not a TypeOopPtr |
247 | 1161 tinst = t->cast_to_exactness(true)->is_oopptr()->cast_to_instance_id(ni); |
0 | 1162 igvn->hash_delete(n); |
1163 igvn->set_type(n, tinst); | |
1164 n->raise_bottom_type(tinst); | |
1165 igvn->hash_insert(n); | |
65 | 1166 record_for_optimizer(n); |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1167 if (alloc->is_Allocate() && (t->isa_instptr() || t->isa_aryptr())) { |
163 | 1168 |
1169 // First, put on the worklist all Field edges from Connection Graph | |
1170 // which is more accurate then putting immediate users from Ideal Graph. | |
1171 for (uint e = 0; e < ptn->edge_count(); e++) { | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1172 Node *use = ptnode_adr(ptn->edge_target(e))->_node; |
163 | 1173 assert(ptn->edge_type(e) == PointsToNode::FieldEdge && use->is_AddP(), |
1174 "only AddP nodes are Field edges in CG"); | |
1175 if (use->outcnt() > 0) { // Don't process dead nodes | |
1176 Node* addp2 = find_second_addp(use, use->in(AddPNode::Base)); | |
1177 if (addp2 != NULL) { | |
1178 assert(alloc->is_AllocateArray(),"array allocation was expected"); | |
1179 alloc_worklist.append_if_missing(addp2); | |
1180 } | |
1181 alloc_worklist.append_if_missing(use); | |
1182 } | |
1183 } | |
1184 | |
65 | 1185 // An allocation may have an Initialize which has raw stores. Scan |
1186 // the users of the raw allocation result and push AddP users | |
1187 // on alloc_worklist. | |
1188 Node *raw_result = alloc->proj_out(TypeFunc::Parms); | |
1189 assert (raw_result != NULL, "must have an allocation result"); | |
1190 for (DUIterator_Fast imax, i = raw_result->fast_outs(imax); i < imax; i++) { | |
1191 Node *use = raw_result->fast_out(i); | |
1192 if (use->is_AddP() && use->outcnt() > 0) { // Don't process dead nodes | |
1193 Node* addp2 = find_second_addp(use, raw_result); | |
1194 if (addp2 != NULL) { | |
1195 assert(alloc->is_AllocateArray(),"array allocation was expected"); | |
1196 alloc_worklist.append_if_missing(addp2); | |
1197 } | |
1198 alloc_worklist.append_if_missing(use); | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1199 } else if (use->is_MemBar()) { |
65 | 1200 memnode_worklist.append_if_missing(use); |
1201 } | |
1202 } | |
1203 } | |
0 | 1204 } else if (n->is_AddP()) { |
2249 | 1205 VectorSet* ptset = PointsTo(get_addp_base(n)); |
1206 assert(ptset->Size() == 1, "AddP address is unique"); | |
1207 uint elem = ptset->getelem(); // Allocation node's index | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1208 if (elem == _phantom_object) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1209 assert(false, "escaped allocation"); |
65 | 1210 continue; // Assume the value was set outside this method. |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1211 } |
65 | 1212 Node *base = get_map(elem); // CheckCastPP node |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1213 if (!split_AddP(n, base, igvn)) continue; // wrong type from dead path |
65 | 1214 tinst = igvn->type(base)->isa_oopptr(); |
1215 } else if (n->is_Phi() || | |
1216 n->is_CheckCastPP() || | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1217 n->is_EncodeP() || |
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1218 n->is_DecodeN() || |
65 | 1219 (n->is_ConstraintCast() && n->Opcode() == Op_CastPP)) { |
0 | 1220 if (visited.test_set(n->_idx)) { |
1221 assert(n->is_Phi(), "loops only through Phi's"); | |
1222 continue; // already processed | |
1223 } | |
2249 | 1224 VectorSet* ptset = PointsTo(n); |
1225 if (ptset->Size() == 1) { | |
1226 uint elem = ptset->getelem(); // Allocation node's index | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1227 if (elem == _phantom_object) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1228 assert(false, "escaped allocation"); |
65 | 1229 continue; // Assume the value was set outside this method. |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1230 } |
65 | 1231 Node *val = get_map(elem); // CheckCastPP node |
0 | 1232 TypeNode *tn = n->as_Type(); |
65 | 1233 tinst = igvn->type(val)->isa_oopptr(); |
223 | 1234 assert(tinst != NULL && tinst->is_known_instance() && |
1235 (uint)tinst->instance_id() == elem , "instance type expected."); | |
163 | 1236 |
1237 const Type *tn_type = igvn->type(tn); | |
223 | 1238 const TypeOopPtr *tn_t; |
1239 if (tn_type->isa_narrowoop()) { | |
1240 tn_t = tn_type->make_ptr()->isa_oopptr(); | |
1241 } else { | |
1242 tn_t = tn_type->isa_oopptr(); | |
1243 } | |
0 | 1244 |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1245 if (tn_t != NULL && tinst->klass()->is_subtype_of(tn_t->klass())) { |
163 | 1246 if (tn_type->isa_narrowoop()) { |
1247 tn_type = tinst->make_narrowoop(); | |
1248 } else { | |
1249 tn_type = tinst; | |
1250 } | |
0 | 1251 igvn->hash_delete(tn); |
163 | 1252 igvn->set_type(tn, tn_type); |
1253 tn->set_type(tn_type); | |
0 | 1254 igvn->hash_insert(tn); |
65 | 1255 record_for_optimizer(n); |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
1256 } else { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1257 assert(tn_type == TypePtr::NULL_PTR || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1258 tn_t != NULL && !tinst->klass()->is_subtype_of(tn_t->klass()), |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1259 "unexpected type"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1260 continue; // Skip dead path with different type |
0 | 1261 } |
1262 } | |
1263 } else { | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1264 debug_only(n->dump();) |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1265 assert(false, "EA: unexpected node"); |
0 | 1266 continue; |
1267 } | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1268 // push allocation's users on appropriate worklist |
0 | 1269 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
1270 Node *use = n->fast_out(i); | |
1271 if(use->is_Mem() && use->in(MemNode::Address) == n) { | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1272 // Load/store to instance's field |
65 | 1273 memnode_worklist.append_if_missing(use); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1274 } else if (use->is_MemBar()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1275 memnode_worklist.append_if_missing(use); |
65 | 1276 } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes |
1277 Node* addp2 = find_second_addp(use, n); | |
1278 if (addp2 != NULL) { | |
1279 alloc_worklist.append_if_missing(addp2); | |
1280 } | |
1281 alloc_worklist.append_if_missing(use); | |
1282 } else if (use->is_Phi() || | |
1283 use->is_CheckCastPP() || | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1284 use->is_EncodeP() || |
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1285 use->is_DecodeN() || |
65 | 1286 (use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) { |
1287 alloc_worklist.append_if_missing(use); | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1288 #ifdef ASSERT |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1289 } else if (use->is_Mem()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1290 assert(use->in(MemNode::Address) != n, "EA: missing allocation reference path"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1291 } else if (use->is_MergeMem()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1292 assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1293 } else if (use->is_SafePoint()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1294 // Look for MergeMem nodes for calls which reference unique allocation |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1295 // (through CheckCastPP nodes) even for debug info. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1296 Node* m = use->in(TypeFunc::Memory); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1297 if (m->is_MergeMem()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1298 assert(_mergemem_worklist.contains(m->as_MergeMem()), "EA: missing MergeMem node in the worklist"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1299 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1300 } else { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1301 uint op = use->Opcode(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1302 if (!(op == Op_CmpP || op == Op_Conv2B || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1303 op == Op_CastP2X || op == Op_StoreCM || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1304 op == Op_FastLock || op == Op_AryEq || op == Op_StrComp || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1305 op == Op_StrEquals || op == Op_StrIndexOf)) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1306 n->dump(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1307 use->dump(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1308 assert(false, "EA: missing allocation reference path"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1309 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1310 #endif |
0 | 1311 } |
1312 } | |
1313 | |
1314 } | |
65 | 1315 // New alias types were created in split_AddP(). |
0 | 1316 uint new_index_end = (uint) _compile->num_alias_types(); |
1317 | |
1318 // Phase 2: Process MemNode's from memnode_worklist. compute new address type and | |
1319 // compute new values for Memory inputs (the Memory inputs are not | |
1320 // actually updated until phase 4.) | |
1321 if (memnode_worklist.length() == 0) | |
1322 return; // nothing to do | |
1323 | |
1324 while (memnode_worklist.length() != 0) { | |
1325 Node *n = memnode_worklist.pop(); | |
65 | 1326 if (visited.test_set(n->_idx)) |
1327 continue; | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1328 if (n->is_Phi() || n->is_ClearArray()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1329 // we don't need to do anything, but the users must be pushed |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1330 } else if (n->is_MemBar()) { // Initialize, MemBar nodes |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1331 // we don't need to do anything, but the users must be pushed |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1332 n = n->as_MemBar()->proj_out(TypeFunc::Memory); |
65 | 1333 if (n == NULL) |
0 | 1334 continue; |
1335 } else { | |
1336 assert(n->is_Mem(), "memory node required."); | |
1337 Node *addr = n->in(MemNode::Address); | |
1338 const Type *addr_t = igvn->type(addr); | |
1339 if (addr_t == Type::TOP) | |
1340 continue; | |
1341 assert (addr_t->isa_ptr() != NULL, "pointer type required."); | |
1342 int alias_idx = _compile->get_alias_index(addr_t->is_ptr()); | |
65 | 1343 assert ((uint)alias_idx < new_index_end, "wrong alias index"); |
1344 Node *mem = find_inst_mem(n->in(MemNode::Memory), alias_idx, orig_phis, igvn); | |
38
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
1345 if (_compile->failing()) { |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
1346 return; |
b789bcaf2dd9
6667610: (Escape Analysis) retry compilation without EA if it fails
kvn
parents:
0
diff
changeset
|
1347 } |
65 | 1348 if (mem != n->in(MemNode::Memory)) { |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1349 // We delay the memory edge update since we need old one in |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1350 // MergeMem code below when instances memory slices are separated. |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1351 debug_only(Node* pn = ptnode_adr(n->_idx)->_node;) |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1352 assert(pn == NULL || pn == n, "wrong node"); |
0 | 1353 set_map(n->_idx, mem); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1354 ptnode_adr(n->_idx)->_node = n; |
65 | 1355 } |
0 | 1356 if (n->is_Load()) { |
1357 continue; // don't push users | |
1358 } else if (n->is_LoadStore()) { | |
1359 // get the memory projection | |
1360 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { | |
1361 Node *use = n->fast_out(i); | |
1362 if (use->Opcode() == Op_SCMemProj) { | |
1363 n = use; | |
1364 break; | |
1365 } | |
1366 } | |
1367 assert(n->Opcode() == Op_SCMemProj, "memory projection required"); | |
1368 } | |
1369 } | |
1370 // push user on appropriate worklist | |
1371 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { | |
1372 Node *use = n->fast_out(i); | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1373 if (use->is_Phi() || use->is_ClearArray()) { |
65 | 1374 memnode_worklist.append_if_missing(use); |
0 | 1375 } else if(use->is_Mem() && use->in(MemNode::Memory) == n) { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1376 if (use->Opcode() == Op_StoreCM) // Ignore cardmark stores |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1377 continue; |
65 | 1378 memnode_worklist.append_if_missing(use); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1379 } else if (use->is_MemBar()) { |
65 | 1380 memnode_worklist.append_if_missing(use); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1381 #ifdef ASSERT |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1382 } else if(use->is_Mem()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1383 assert(use->in(MemNode::Memory) != n, "EA: missing memory path"); |
0 | 1384 } else if (use->is_MergeMem()) { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1385 assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1386 } else { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1387 uint op = use->Opcode(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1388 if (!(op == Op_StoreCM || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1389 (op == Op_CallLeaf && use->as_CallLeaf()->_name != NULL && |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1390 strcmp(use->as_CallLeaf()->_name, "g1_wb_pre") == 0) || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1391 op == Op_AryEq || op == Op_StrComp || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1392 op == Op_StrEquals || op == Op_StrIndexOf)) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1393 n->dump(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1394 use->dump(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1395 assert(false, "EA: missing memory path"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1396 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1397 #endif |
0 | 1398 } |
1399 } | |
1400 } | |
1401 | |
65 | 1402 // Phase 3: Process MergeMem nodes from mergemem_worklist. |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1403 // Walk each memory slice moving the first node encountered of each |
65 | 1404 // instance type to the the input corresponding to its alias index. |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1405 uint length = _mergemem_worklist.length(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1406 for( uint next = 0; next < length; ++next ) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1407 MergeMemNode* nmm = _mergemem_worklist.at(next); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1408 assert(!visited.test_set(nmm->_idx), "should not be visited before"); |
0 | 1409 // Note: we don't want to use MergeMemStream here because we only want to |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1410 // scan inputs which exist at the start, not ones we add during processing. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1411 // Note 2: MergeMem may already contains instance memory slices added |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1412 // during find_inst_mem() call when memory nodes were processed above. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1413 igvn->hash_delete(nmm); |
0 | 1414 uint nslices = nmm->req(); |
1415 for (uint i = Compile::AliasIdxRaw+1; i < nslices; i++) { | |
65 | 1416 Node* mem = nmm->in(i); |
1417 Node* cur = NULL; | |
0 | 1418 if (mem == NULL || mem->is_top()) |
1419 continue; | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1420 // First, update mergemem by moving memory nodes to corresponding slices |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1421 // if their type became more precise since this mergemem was created. |
0 | 1422 while (mem->is_Mem()) { |
1423 const Type *at = igvn->type(mem->in(MemNode::Address)); | |
1424 if (at != Type::TOP) { | |
1425 assert (at->isa_ptr() != NULL, "pointer type required."); | |
1426 uint idx = (uint)_compile->get_alias_index(at->is_ptr()); | |
1427 if (idx == i) { | |
1428 if (cur == NULL) | |
1429 cur = mem; | |
1430 } else { | |
1431 if (idx >= nmm->req() || nmm->is_empty_memory(nmm->in(idx))) { | |
1432 nmm->set_memory_at(idx, mem); | |
1433 } | |
1434 } | |
1435 } | |
1436 mem = mem->in(MemNode::Memory); | |
1437 } | |
1438 nmm->set_memory_at(i, (cur != NULL) ? cur : mem); | |
65 | 1439 // Find any instance of the current type if we haven't encountered |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1440 // already a memory slice of the instance along the memory chain. |
65 | 1441 for (uint ni = new_index_start; ni < new_index_end; ni++) { |
1442 if((uint)_compile->get_general_index(ni) == i) { | |
1443 Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni); | |
1444 if (nmm->is_empty_memory(m)) { | |
1445 Node* result = find_inst_mem(mem, ni, orig_phis, igvn); | |
1446 if (_compile->failing()) { | |
1447 return; | |
1448 } | |
1449 nmm->set_memory_at(ni, result); | |
1450 } | |
1451 } | |
1452 } | |
1453 } | |
1454 // Find the rest of instances values | |
1455 for (uint ni = new_index_start; ni < new_index_end; ni++) { | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1456 const TypeOopPtr *tinst = _compile->get_adr_type(ni)->isa_oopptr(); |
65 | 1457 Node* result = step_through_mergemem(nmm, ni, tinst); |
1458 if (result == nmm->base_memory()) { | |
1459 // Didn't find instance memory, search through general slice recursively. | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1460 result = nmm->memory_at(_compile->get_general_index(ni)); |
65 | 1461 result = find_inst_mem(result, ni, orig_phis, igvn); |
1462 if (_compile->failing()) { | |
1463 return; | |
1464 } | |
1465 nmm->set_memory_at(ni, result); | |
1466 } | |
1467 } | |
1468 igvn->hash_insert(nmm); | |
1469 record_for_optimizer(nmm); | |
0 | 1470 } |
1471 | |
65 | 1472 // Phase 4: Update the inputs of non-instance memory Phis and |
1473 // the Memory input of memnodes | |
0 | 1474 // First update the inputs of any non-instance Phi's from |
1475 // which we split out an instance Phi. Note we don't have | |
1476 // to recursively process Phi's encounted on the input memory | |
1477 // chains as is done in split_memory_phi() since they will | |
1478 // also be processed here. | |
247 | 1479 for (int j = 0; j < orig_phis.length(); j++) { |
1480 PhiNode *phi = orig_phis.at(j); | |
0 | 1481 int alias_idx = _compile->get_alias_index(phi->adr_type()); |
1482 igvn->hash_delete(phi); | |
1483 for (uint i = 1; i < phi->req(); i++) { | |
1484 Node *mem = phi->in(i); | |
65 | 1485 Node *new_mem = find_inst_mem(mem, alias_idx, orig_phis, igvn); |
1486 if (_compile->failing()) { | |
1487 return; | |
1488 } | |
0 | 1489 if (mem != new_mem) { |
1490 phi->set_req(i, new_mem); | |
1491 } | |
1492 } | |
1493 igvn->hash_insert(phi); | |
1494 record_for_optimizer(phi); | |
1495 } | |
1496 | |
1497 // Update the memory inputs of MemNodes with the value we computed | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1498 // in Phase 2 and move stores memory users to corresponding memory slices. |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2459
diff
changeset
|
1499 |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2459
diff
changeset
|
1500 // Disable memory split verification code until the fix for 6984348. |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2459
diff
changeset
|
1501 // Currently it produces false negative results since it does not cover all cases. |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2459
diff
changeset
|
1502 #if 0 // ifdef ASSERT |
2249 | 1503 visited.Reset(); |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1504 Node_Stack old_mems(arena, _compile->unique() >> 2); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1505 #endif |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1506 for (uint i = 0; i < nodes_size(); i++) { |
0 | 1507 Node *nmem = get_map(i); |
1508 if (nmem != NULL) { | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1509 Node *n = ptnode_adr(i)->_node; |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1510 assert(n != NULL, "sanity"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1511 if (n->is_Mem()) { |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2459
diff
changeset
|
1512 #if 0 // ifdef ASSERT |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1513 Node* old_mem = n->in(MemNode::Memory); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1514 if (!visited.test_set(old_mem->_idx)) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1515 old_mems.push(old_mem, old_mem->outcnt()); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1516 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1517 #endif |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1518 assert(n->in(MemNode::Memory) != nmem, "sanity"); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1519 if (!n->is_Load()) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1520 // Move memory users of a store first. |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1521 move_inst_mem(n, orig_phis, igvn); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1522 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1523 // Now update memory input |
0 | 1524 igvn->hash_delete(n); |
1525 n->set_req(MemNode::Memory, nmem); | |
1526 igvn->hash_insert(n); | |
1527 record_for_optimizer(n); | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1528 } else { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1529 assert(n->is_Allocate() || n->is_CheckCastPP() || |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1530 n->is_AddP() || n->is_Phi(), "unknown node used for set_map()"); |
0 | 1531 } |
1532 } | |
1533 } | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2459
diff
changeset
|
1534 #if 0 // ifdef ASSERT |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1535 // Verify that memory was split correctly |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1536 while (old_mems.is_nonempty()) { |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1537 Node* old_mem = old_mems.node(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1538 uint old_cnt = old_mems.index(); |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1539 old_mems.pop(); |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2459
diff
changeset
|
1540 assert(old_cnt == old_mem->outcnt(), "old mem could be lost"); |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1541 } |
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
1542 #endif |
0 | 1543 } |
1544 | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1545 bool ConnectionGraph::has_candidates(Compile *C) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1546 // EA brings benefits only when the code has allocations and/or locks which |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1547 // are represented by ideal Macro nodes. |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1548 int cnt = C->macro_count(); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1549 for( int i=0; i < cnt; i++ ) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1550 Node *n = C->macro_node(i); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1551 if ( n->is_Allocate() ) |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1552 return true; |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1553 if( n->is_Lock() ) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1554 Node* obj = n->as_Lock()->obj_node()->uncast(); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1555 if( !(obj->is_Parm() || obj->is_Con()) ) |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1556 return true; |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1557 } |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1558 } |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1559 return false; |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1560 } |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1561 |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1562 void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) { |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1563 // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1564 // to create space for them in ConnectionGraph::_nodes[]. |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1565 Node* oop_null = igvn->zerocon(T_OBJECT); |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1566 Node* noop_null = igvn->zerocon(T_NARROWOOP); |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1567 |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1568 ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn); |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1569 // Perform escape analysis |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1570 if (congraph->compute_escape()) { |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1571 // There are non escaping objects. |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1572 C->set_congraph(congraph); |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1573 } |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1574 |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1575 // Cleanup. |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1576 if (oop_null->outcnt() == 0) |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1577 igvn->hash_delete(oop_null); |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1578 if (noop_null->outcnt() == 0) |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1579 igvn->hash_delete(noop_null); |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1580 } |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1581 |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1582 bool ConnectionGraph::compute_escape() { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1583 Compile* C = _compile; |
65 | 1584 |
163 | 1585 // 1. Populate Connection Graph (CG) with Ideal nodes. |
65 | 1586 |
1587 Unique_Node_List worklist_init; | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1588 worklist_init.map(C->unique(), NULL); // preallocate space |
65 | 1589 |
1590 // Initialize worklist | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1591 if (C->root() != NULL) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1592 worklist_init.push(C->root()); |
65 | 1593 } |
1594 | |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1595 GrowableArray<Node*> alloc_worklist; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1596 GrowableArray<Node*> addp_worklist; |
4113 | 1597 GrowableArray<Node*> ptr_cmp_worklist; |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1598 PhaseGVN* igvn = _igvn; |
65 | 1599 |
1600 // Push all useful nodes onto CG list and set their type. | |
1601 for( uint next = 0; next < worklist_init.size(); ++next ) { | |
1602 Node* n = worklist_init.at(next); | |
1603 record_for_escape_analysis(n, igvn); | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1604 // Only allocations and java static calls results are checked |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1605 // for an escape status. See process_call_result() below. |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1606 if (n->is_Allocate() || n->is_CallStaticJava() && |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1607 ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) { |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1608 alloc_worklist.append(n); |
4113 | 1609 } else if(n->is_AddP()) { |
1921 | 1610 // Collect address nodes. Use them during stage 3 below |
1611 // to build initial connection graph field edges. | |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1612 addp_worklist.append(n); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1613 } else if (n->is_MergeMem()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1614 // Collect all MergeMem nodes to add memory slices for |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1615 // scalar replaceable objects in split_unique_types(). |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1616 _mergemem_worklist.append(n->as_MergeMem()); |
4113 | 1617 } else if (OptimizePtrCompare && n->is_Cmp() && |
1618 (n->Opcode() == Op_CmpP || n->Opcode() == Op_CmpN)) { | |
1619 // Compare pointers nodes | |
1620 ptr_cmp_worklist.append(n); | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1621 } |
65 | 1622 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
1623 Node* m = n->fast_out(i); // Get user | |
1624 worklist_init.push(m); | |
1625 } | |
1626 } | |
0 | 1627 |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1628 if (alloc_worklist.length() == 0) { |
65 | 1629 _collecting = false; |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1630 return false; // Nothing to do. |
65 | 1631 } |
1632 | |
1633 // 2. First pass to create simple CG edges (doesn't require to walk CG). | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1634 uint delayed_size = _delayed_worklist.size(); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1635 for( uint next = 0; next < delayed_size; ++next ) { |
65 | 1636 Node* n = _delayed_worklist.at(next); |
1637 build_connection_graph(n, igvn); | |
1638 } | |
0 | 1639 |
1921 | 1640 // 3. Pass to create initial fields edges (JavaObject -F-> AddP) |
1641 // to reduce number of iterations during stage 4 below. | |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1642 uint addp_length = addp_worklist.length(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1643 for( uint next = 0; next < addp_length; ++next ) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1644 Node* n = addp_worklist.at(next); |
1921 | 1645 Node* base = get_addp_base(n); |
4113 | 1646 if (base->is_Proj() && base->in(0)->is_Call()) |
1921 | 1647 base = base->in(0); |
1648 PointsToNode::NodeType nt = ptnode_adr(base->_idx)->node_type(); | |
1649 if (nt == PointsToNode::JavaObject) { | |
1650 build_connection_graph(n, igvn); | |
1651 } | |
65 | 1652 } |
1653 | |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1654 GrowableArray<int> cg_worklist; |
65 | 1655 cg_worklist.append(_phantom_object); |
1921 | 1656 GrowableArray<uint> worklist; |
65 | 1657 |
1658 // 4. Build Connection Graph which need | |
1659 // to walk the connection graph. | |
1921 | 1660 _progress = false; |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1661 for (uint ni = 0; ni < nodes_size(); ni++) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1662 PointsToNode* ptn = ptnode_adr(ni); |
65 | 1663 Node *n = ptn->_node; |
1664 if (n != NULL) { // Call, AddP, LoadP, StoreP | |
1665 build_connection_graph(n, igvn); | |
1666 if (ptn->node_type() != PointsToNode::UnknownType) | |
1667 cg_worklist.append(n->_idx); // Collect CG nodes | |
1921 | 1668 if (!_processed.test(n->_idx)) |
1669 worklist.append(n->_idx); // Collect C/A/L/S nodes | |
65 | 1670 } |
0 | 1671 } |
1672 | |
1921 | 1673 // After IGVN user nodes may have smaller _idx than |
1674 // their inputs so they will be processed first in | |
1675 // previous loop. Because of that not all Graph | |
1676 // edges will be created. Walk over interesting | |
1677 // nodes again until no new edges are created. | |
1678 // | |
1679 // Normally only 1-3 passes needed to build | |
1680 // Connection Graph depending on graph complexity. | |
2086
a21ff35351ec
7003130: assert(iterations<CG_BUILD_ITER_LIMIT) failed: infinite EA connection graph
kvn
parents:
1972
diff
changeset
|
1681 // Observed 8 passes in jvm2008 compiler.compiler. |
a21ff35351ec
7003130: assert(iterations<CG_BUILD_ITER_LIMIT) failed: infinite EA connection graph
kvn
parents:
1972
diff
changeset
|
1682 // Set limit to 20 to catch situation when something |
1921 | 1683 // did go wrong and recompile the method without EA. |
1684 | |
2086
a21ff35351ec
7003130: assert(iterations<CG_BUILD_ITER_LIMIT) failed: infinite EA connection graph
kvn
parents:
1972
diff
changeset
|
1685 #define CG_BUILD_ITER_LIMIT 20 |
1921 | 1686 |
1687 uint length = worklist.length(); | |
1688 int iterations = 0; | |
1689 while(_progress && (iterations++ < CG_BUILD_ITER_LIMIT)) { | |
1690 _progress = false; | |
1691 for( uint next = 0; next < length; ++next ) { | |
1692 int ni = worklist.at(next); | |
1693 PointsToNode* ptn = ptnode_adr(ni); | |
1694 Node* n = ptn->_node; | |
1695 assert(n != NULL, "should be known node"); | |
1696 build_connection_graph(n, igvn); | |
1697 } | |
1698 } | |
1699 if (iterations >= CG_BUILD_ITER_LIMIT) { | |
1700 assert(iterations < CG_BUILD_ITER_LIMIT, | |
1701 err_msg("infinite EA connection graph build with %d nodes and worklist size %d", | |
1702 nodes_size(), length)); | |
1703 // Possible infinite build_connection_graph loop, | |
1704 // retry compilation without escape analysis. | |
1705 C->record_failure(C2Compiler::retry_no_escape_analysis()); | |
1706 _collecting = false; | |
1707 return false; | |
1708 } | |
1709 #undef CG_BUILD_ITER_LIMIT | |
1710 | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1711 // 5. Propagate escaped states. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1712 worklist.clear(); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1713 |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1714 // mark all nodes reachable from GlobalEscape nodes |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1715 (void)propagate_escape_state(&cg_worklist, &worklist, PointsToNode::GlobalEscape); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1716 |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1717 // mark all nodes reachable from ArgEscape nodes |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1718 bool has_non_escaping_obj = propagate_escape_state(&cg_worklist, &worklist, PointsToNode::ArgEscape); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1719 |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1720 Arena* arena = Thread::current()->resource_area(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1721 VectorSet visited(arena); |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1722 |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1723 // 6. Find fields initializing values for not escaped allocations |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1724 uint alloc_length = alloc_worklist.length(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1725 for (uint next = 0; next < alloc_length; ++next) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1726 Node* n = alloc_worklist.at(next); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1727 if (ptnode_adr(n->_idx)->escape_state() == PointsToNode::NoEscape) { |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1728 has_non_escaping_obj = true; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1729 if (n->is_Allocate()) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1730 find_init_values(n, &visited, igvn); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1731 } |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1732 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1733 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1734 |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1735 uint cg_length = cg_worklist.length(); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1736 |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1737 // Skip the rest of code if all objects escaped. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1738 if (!has_non_escaping_obj) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1739 cg_length = 0; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1740 addp_length = 0; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1741 } |
0 | 1742 |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1743 for (uint next = 0; next < cg_length; ++next) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1744 int ni = cg_worklist.at(next); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1745 PointsToNode* ptn = ptnode_adr(ni); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1746 PointsToNode::NodeType nt = ptn->node_type(); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1747 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1748 if (ptn->edge_count() == 0) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1749 // No values were found. Assume the value was set |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1750 // outside this method - add edge to phantom object. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1751 add_pointsto_edge(ni, _phantom_object); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1752 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1753 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1754 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1755 |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1756 // 7. Remove deferred edges from the graph. |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1757 for (uint next = 0; next < cg_length; ++next) { |
65 | 1758 int ni = cg_worklist.at(next); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1759 PointsToNode* ptn = ptnode_adr(ni); |
0 | 1760 PointsToNode::NodeType nt = ptn->node_type(); |
1761 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { | |
1921 | 1762 remove_deferred(ni, &worklist, &visited); |
0 | 1763 } |
1764 } | |
65 | 1765 |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1766 // 8. Adjust escape state of nonescaping objects. |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1767 for (uint next = 0; next < addp_length; ++next) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1768 Node* n = addp_worklist.at(next); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1769 adjust_escape_state(n); |
0 | 1770 } |
1771 | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1772 // push all NoEscape nodes on the worklist |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1773 worklist.clear(); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1774 for( uint next = 0; next < cg_length; ++next ) { |
65 | 1775 int nk = cg_worklist.at(next); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1776 if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape && |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1777 !is_null_ptr(nk)) |
65 | 1778 worklist.push(nk); |
1779 } | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1780 |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1781 alloc_worklist.clear(); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1782 // Propagate scalar_replaceable value. |
65 | 1783 while(worklist.length() > 0) { |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
1784 uint nk = worklist.pop(); |
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
1785 PointsToNode* ptn = ptnode_adr(nk); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1786 Node* n = ptn->_node; |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1787 bool scalar_replaceable = ptn->scalar_replaceable(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1788 if (n->is_Allocate() && scalar_replaceable) { |
605 | 1789 // Push scalar replaceable allocations on alloc_worklist |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1790 // for processing in split_unique_types(). Note, |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1791 // following code may change scalar_replaceable value. |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1792 alloc_worklist.append(n); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1793 } |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1794 uint e_cnt = ptn->edge_count(); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1795 for (uint ei = 0; ei < e_cnt; ei++) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1796 uint npi = ptn->edge_target(ei); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1797 if (is_null_ptr(npi)) |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1798 continue; |
65 | 1799 PointsToNode *np = ptnode_adr(npi); |
1800 if (np->escape_state() < PointsToNode::NoEscape) { | |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
1801 set_escape_state(npi, PointsToNode::NoEscape); |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1802 if (!scalar_replaceable) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1803 np->set_scalar_replaceable(false); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1804 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1805 worklist.push(npi); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1806 } else if (np->scalar_replaceable() && !scalar_replaceable) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1807 np->set_scalar_replaceable(false); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1808 worklist.push(npi); |
65 | 1809 } |
1810 } | |
1811 } | |
1812 | |
0 | 1813 _collecting = false; |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1814 assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build"); |
0 | 1815 |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1816 assert(ptnode_adr(_oop_null)->escape_state() == PointsToNode::NoEscape && |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1817 ptnode_adr(_oop_null)->edge_count() == 0, "sanity"); |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
1818 if (UseCompressedOops) { |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1819 assert(ptnode_adr(_noop_null)->escape_state() == PointsToNode::NoEscape && |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1820 ptnode_adr(_noop_null)->edge_count() == 0, "sanity"); |
4046
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
1821 } |
e69a66a1457b
7059039: EA: don't change non-escaping state of NULL pointer
kvn
parents:
3754
diff
changeset
|
1822 |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1823 if (EliminateLocks && has_non_escaping_obj) { |
3754
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1824 // Mark locks before changing ideal graph. |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1825 int cnt = C->macro_count(); |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1826 for( int i=0; i < cnt; i++ ) { |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1827 Node *n = C->macro_node(i); |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1828 if (n->is_AbstractLock()) { // Lock and Unlock nodes |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1829 AbstractLockNode* alock = n->as_AbstractLock(); |
4115 | 1830 if (!alock->is_eliminated() || alock->is_coarsened()) { |
3754
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1831 PointsToNode::EscapeState es = escape_state(alock->obj_node()); |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1832 assert(es != PointsToNode::UnknownEscape, "should know"); |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1833 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) { |
4115 | 1834 if (!alock->is_eliminated()) { |
1835 // Mark it eliminated to update any counters | |
1836 alock->set_eliminated(); | |
1837 } else { | |
1838 // The lock could be marked eliminated by lock coarsening | |
1839 // code during first IGVN before EA. Clear coarsened flag | |
1840 // to eliminate all associated locks/unlocks and relock | |
1841 // during deoptimization. | |
1842 alock->clear_coarsened(); | |
1843 } | |
3754
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1844 } |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1845 } |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1846 } |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1847 } |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1848 } |
642c68c75db9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
3278
diff
changeset
|
1849 |
4113 | 1850 if (OptimizePtrCompare && has_non_escaping_obj) { |
1851 // Add ConI(#CC_GT) and ConI(#CC_EQ). | |
1852 _pcmp_neq = igvn->makecon(TypeInt::CC_GT); | |
1853 _pcmp_eq = igvn->makecon(TypeInt::CC_EQ); | |
1854 // Optimize objects compare. | |
1855 while (ptr_cmp_worklist.length() != 0) { | |
1856 Node *n = ptr_cmp_worklist.pop(); | |
1857 Node *res = optimize_ptr_compare(n); | |
1858 if (res != NULL) { | |
1859 #ifndef PRODUCT | |
1860 if (PrintOptimizePtrCompare) { | |
1861 tty->print_cr("++++ Replaced: %d %s(%d,%d) --> %s", n->_idx, (n->Opcode() == Op_CmpP ? "CmpP" : "CmpN"), n->in(1)->_idx, n->in(2)->_idx, (res == _pcmp_eq ? "EQ" : "NotEQ")); | |
1862 if (Verbose) { | |
1863 n->dump(1); | |
1864 } | |
1865 } | |
1866 #endif | |
1867 _igvn->replace_node(n, res); | |
1868 } | |
1869 } | |
1870 // cleanup | |
1871 if (_pcmp_neq->outcnt() == 0) | |
1872 igvn->hash_delete(_pcmp_neq); | |
1873 if (_pcmp_eq->outcnt() == 0) | |
1874 igvn->hash_delete(_pcmp_eq); | |
1875 } | |
1876 | |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1877 #ifndef PRODUCT |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1878 if (PrintEscapeAnalysis) { |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1879 dump(); // Dump ConnectionGraph |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1880 } |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1881 #endif |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
1882 |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1883 bool has_scalar_replaceable_candidates = false; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1884 alloc_length = alloc_worklist.length(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1885 for (uint next = 0; next < alloc_length; ++next) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1886 Node* n = alloc_worklist.at(next); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1887 PointsToNode* ptn = ptnode_adr(n->_idx); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1888 assert(ptn->escape_state() == PointsToNode::NoEscape, "sanity"); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1889 if (ptn->scalar_replaceable()) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1890 has_scalar_replaceable_candidates = true; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1891 break; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1892 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1893 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1894 |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1895 if ( has_scalar_replaceable_candidates && |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1896 C->AliasLevel() >= 3 && EliminateAllocations ) { |
0 | 1897 |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1898 // Now use the escape information to create unique types for |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1899 // scalar replaceable objects. |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1900 split_unique_types(alloc_worklist); |
0 | 1901 |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1902 if (C->failing()) return false; |
0 | 1903 |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1904 C->print_method("After Escape Analysis", 2); |
0 | 1905 |
65 | 1906 #ifdef ASSERT |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1907 } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) { |
65 | 1908 tty->print("=== No allocations eliminated for "); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1909 C->method()->print_short_name(); |
65 | 1910 if(!EliminateAllocations) { |
1911 tty->print(" since EliminateAllocations is off ==="); | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1912 } else if(!has_scalar_replaceable_candidates) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1913 tty->print(" since there are no scalar replaceable candidates ==="); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1914 } else if(C->AliasLevel() < 3) { |
65 | 1915 tty->print(" since AliasLevel < 3 ==="); |
0 | 1916 } |
65 | 1917 tty->cr(); |
1918 #endif | |
0 | 1919 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
1920 return has_non_escaping_obj; |
0 | 1921 } |
1922 | |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1923 // Find fields initializing values for allocations. |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1924 void ConnectionGraph::find_init_values(Node* alloc, VectorSet* visited, PhaseTransform* phase) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1925 assert(alloc->is_Allocate(), "Should be called for Allocate nodes only"); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1926 PointsToNode* pta = ptnode_adr(alloc->_idx); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1927 assert(pta->escape_state() == PointsToNode::NoEscape, "Not escaped Allocate nodes only"); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1928 InitializeNode* ini = alloc->as_Allocate()->initialization(); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1929 |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1930 Compile* C = _compile; |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1931 visited->Reset(); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1932 // Check if a oop field's initializing value is recorded and add |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1933 // a corresponding NULL field's value if it is not recorded. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1934 // Connection Graph does not record a default initialization by NULL |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1935 // captured by Initialize node. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1936 // |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1937 uint null_idx = UseCompressedOops ? _noop_null : _oop_null; |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1938 uint ae_cnt = pta->edge_count(); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1939 bool visited_bottom_offset = false; |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1940 for (uint ei = 0; ei < ae_cnt; ei++) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1941 uint nidx = pta->edge_target(ei); // Field (AddP) |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1942 PointsToNode* ptn = ptnode_adr(nidx); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1943 assert(ptn->_node->is_AddP(), "Should be AddP nodes only"); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1944 int offset = ptn->offset(); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1945 if (offset == Type::OffsetBot) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1946 if (!visited_bottom_offset) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1947 visited_bottom_offset = true; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1948 // Check only oop fields. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1949 const Type* adr_type = ptn->_node->as_AddP()->bottom_type(); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1950 if (!adr_type->isa_aryptr() || |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1951 (adr_type->isa_aryptr()->klass() == NULL) || |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1952 adr_type->isa_aryptr()->klass()->is_obj_array_klass()) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1953 // OffsetBot is used to reference array's element, |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1954 // always add reference to NULL since we don't |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1955 // known which element is referenced. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1956 add_edge_from_fields(alloc->_idx, null_idx, offset); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1957 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1958 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1959 } else if (offset != oopDesc::klass_offset_in_bytes() && |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
1960 !visited->test_set(offset)) { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1961 |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1962 // Check only oop fields. |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1963 const Type* adr_type = ptn->_node->as_AddP()->bottom_type(); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1964 BasicType basic_field_type = T_INT; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1965 if (adr_type->isa_instptr()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1966 ciField* field = C->alias_type(adr_type->isa_instptr())->field(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1967 if (field != NULL) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1968 basic_field_type = field->layout_type(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1969 } else { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1970 // Ignore non field load (for example, klass load) |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1971 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1972 } else if (adr_type->isa_aryptr()) { |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1973 if (offset != arrayOopDesc::length_offset_in_bytes()) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1974 const Type* elemtype = adr_type->isa_aryptr()->elem(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1975 basic_field_type = elemtype->array_element_basic_type(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1976 } else { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1977 // Ignore array length load |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1978 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1979 #ifdef ASSERT |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1980 } else { |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1981 // Raw pointers are used for initializing stores so skip it |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1982 // since it should be recorded already |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1983 Node* base = get_addp_base(ptn->_node); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1984 assert(adr_type->isa_rawptr() && base->is_Proj() && |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1985 (base->in(0) == alloc),"unexpected pointer type"); |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
1986 #endif |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1987 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1988 if (basic_field_type == T_OBJECT || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1989 basic_field_type == T_NARROWOOP || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1990 basic_field_type == T_ARRAY) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1991 Node* value = NULL; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1992 if (ini != NULL) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1993 BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1994 Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1995 if (store != NULL && store->is_Store()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1996 value = store->in(MemNode::ValueIn); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1997 } else if (ptn->edge_count() > 0) { // Are there oop stores? |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1998 // Check for a store which follows allocation without branches. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
1999 // For example, a volatile field store is not collected |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2000 // by Initialize node. TODO: it would be nice to use idom() here. |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2001 // |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2002 // Search all references to the same field which use different |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2003 // AddP nodes, for example, in the next case: |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2004 // |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2005 // Point p[] = new Point[1]; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2006 // if ( x ) { p[0] = new Point(); p[0].x = x; } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2007 // if ( p[0] != null ) { y = p[0].x; } // has CastPP |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2008 // |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2009 for (uint next = ei; (next < ae_cnt) && (value == NULL); next++) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2010 uint fpi = pta->edge_target(next); // Field (AddP) |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2011 PointsToNode *ptf = ptnode_adr(fpi); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2012 if (ptf->offset() == offset) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2013 Node* nf = ptf->_node; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2014 for (DUIterator_Fast imax, i = nf->fast_outs(imax); i < imax; i++) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2015 store = nf->fast_out(i); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2016 if (store->is_Store() && store->in(0) != NULL) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2017 Node* ctrl = store->in(0); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2018 while(!(ctrl == ini || ctrl == alloc || ctrl == NULL || |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2019 ctrl == C->root() || ctrl == C->top() || ctrl->is_Region() || |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2020 ctrl->is_IfTrue() || ctrl->is_IfFalse())) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2021 ctrl = ctrl->in(0); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2022 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2023 if (ctrl == ini || ctrl == alloc) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2024 value = store->in(MemNode::ValueIn); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2025 break; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2026 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2027 } |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2028 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2029 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2030 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2031 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2032 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2033 if (value == NULL || value != ptnode_adr(value->_idx)->_node) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2034 // A field's initializing value was not recorded. Add NULL. |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2035 add_edge_from_fields(alloc->_idx, null_idx, offset); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2036 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2037 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2038 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2039 } |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2040 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2041 |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2042 // Adjust escape state after Connection Graph is built. |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2043 void ConnectionGraph::adjust_escape_state(Node* n) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2044 PointsToNode* ptn = ptnode_adr(n->_idx); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2045 assert(n->is_AddP(), "Should be called for AddP nodes only"); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2046 // Search for objects which are not scalar replaceable |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2047 // and mark them to propagate the state to referenced objects. |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2048 // |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2049 |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2050 int offset = ptn->offset(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2051 Node* base = get_addp_base(n); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2052 VectorSet* ptset = PointsTo(base); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2053 int ptset_size = ptset->Size(); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2054 |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2055 // An object is not scalar replaceable if the field which may point |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2056 // to it has unknown offset (unknown element of an array of objects). |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2057 // |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2058 |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2059 if (offset == Type::OffsetBot) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2060 uint e_cnt = ptn->edge_count(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2061 for (uint ei = 0; ei < e_cnt; ei++) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2062 uint npi = ptn->edge_target(ei); |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2063 ptnode_adr(npi)->set_scalar_replaceable(false); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2064 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2065 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2066 |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2067 // Currently an object is not scalar replaceable if a LoadStore node |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2068 // access its field since the field value is unknown after it. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2069 // |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2070 bool has_LoadStore = false; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2071 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2072 Node *use = n->fast_out(i); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2073 if (use->is_LoadStore()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2074 has_LoadStore = true; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2075 break; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2076 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2077 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2078 // An object is not scalar replaceable if the address points |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2079 // to unknown field (unknown element for arrays, offset is OffsetBot). |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2080 // |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2081 // Or the address may point to more then one object. This may produce |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2082 // the false positive result (set not scalar replaceable) |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2083 // since the flow-insensitive escape analysis can't separate |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2084 // the case when stores overwrite the field's value from the case |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2085 // when stores happened on different control branches. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2086 // |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2087 // Note: it will disable scalar replacement in some cases: |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2088 // |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2089 // Point p[] = new Point[1]; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2090 // p[0] = new Point(); // Will be not scalar replaced |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2091 // |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2092 // but it will save us from incorrect optimizations in next cases: |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2093 // |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2094 // Point p[] = new Point[1]; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2095 // if ( x ) p[0] = new Point(); // Will be not scalar replaced |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2096 // |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2097 if (ptset_size > 1 || ptset_size != 0 && |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2098 (has_LoadStore || offset == Type::OffsetBot)) { |
2249 | 2099 for( VectorSetI j(ptset); j.test(); ++j ) { |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2100 ptnode_adr(j.elem)->set_scalar_replaceable(false); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2101 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2102 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2103 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2104 |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2105 // Propagate escape states to referenced nodes. |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2106 bool ConnectionGraph::propagate_escape_state(GrowableArray<int>* cg_worklist, |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2107 GrowableArray<uint>* worklist, |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2108 PointsToNode::EscapeState esc_state) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2109 bool has_java_obj = false; |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2110 |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2111 // push all nodes with the same escape state on the worklist |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2112 uint cg_length = cg_worklist->length(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2113 for (uint next = 0; next < cg_length; ++next) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2114 int nk = cg_worklist->at(next); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2115 if (ptnode_adr(nk)->escape_state() == esc_state) |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2116 worklist->push(nk); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2117 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2118 // mark all reachable nodes |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2119 while (worklist->length() > 0) { |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2120 int pt = worklist->pop(); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2121 PointsToNode* ptn = ptnode_adr(pt); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2122 if (ptn->node_type() == PointsToNode::JavaObject && |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2123 !is_null_ptr(pt)) { |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2124 has_java_obj = true; |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2125 if (esc_state > PointsToNode::NoEscape) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2126 // fields values are unknown if object escapes |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2127 add_edge_from_fields(pt, _phantom_object, Type::OffsetBot); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2128 } |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2129 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2130 uint e_cnt = ptn->edge_count(); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2131 for (uint ei = 0; ei < e_cnt; ei++) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2132 uint npi = ptn->edge_target(ei); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2133 if (is_null_ptr(npi)) |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2134 continue; |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2135 PointsToNode *np = ptnode_adr(npi); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2136 if (np->escape_state() < esc_state) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2137 set_escape_state(npi, esc_state); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2138 worklist->push(npi); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2139 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2140 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2141 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2142 // Has not escaping java objects |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2143 return has_java_obj && (esc_state < PointsToNode::GlobalEscape); |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2144 } |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2145 |
4113 | 2146 // Optimize objects compare. |
2147 Node* ConnectionGraph::optimize_ptr_compare(Node* n) { | |
2148 assert(OptimizePtrCompare, "sanity"); | |
2149 // Clone returned Set since PointsTo() returns pointer | |
2150 // to the same structure ConnectionGraph.pt_ptset. | |
2151 VectorSet ptset1 = *PointsTo(n->in(1)); | |
2152 VectorSet ptset2 = *PointsTo(n->in(2)); | |
2153 | |
2154 // Check simple cases first. | |
2155 if (ptset1.Size() == 1) { | |
2156 uint pt1 = ptset1.getelem(); | |
2157 PointsToNode* ptn1 = ptnode_adr(pt1); | |
2158 if (ptn1->escape_state() == PointsToNode::NoEscape) { | |
2159 if (ptset2.Size() == 1 && ptset2.getelem() == pt1) { | |
2160 // Comparing the same not escaping object. | |
2161 return _pcmp_eq; | |
2162 } | |
2163 Node* obj = ptn1->_node; | |
2164 // Comparing not escaping allocation. | |
2165 if ((obj->is_Allocate() || obj->is_CallStaticJava()) && | |
2166 !ptset2.test(pt1)) { | |
2167 return _pcmp_neq; // This includes nullness check. | |
2168 } | |
2169 } | |
2170 } else if (ptset2.Size() == 1) { | |
2171 uint pt2 = ptset2.getelem(); | |
2172 PointsToNode* ptn2 = ptnode_adr(pt2); | |
2173 if (ptn2->escape_state() == PointsToNode::NoEscape) { | |
2174 Node* obj = ptn2->_node; | |
2175 // Comparing not escaping allocation. | |
2176 if ((obj->is_Allocate() || obj->is_CallStaticJava()) && | |
2177 !ptset1.test(pt2)) { | |
2178 return _pcmp_neq; // This includes nullness check. | |
2179 } | |
2180 } | |
2181 } | |
2182 | |
2183 if (!ptset1.disjoint(ptset2)) { | |
2184 return NULL; // Sets are not disjoint | |
2185 } | |
2186 | |
2187 // Sets are disjoint. | |
2188 bool set1_has_unknown_ptr = ptset1.test(_phantom_object) != 0; | |
2189 bool set2_has_unknown_ptr = ptset2.test(_phantom_object) != 0; | |
2190 bool set1_has_null_ptr = (ptset1.test(_oop_null) | ptset1.test(_noop_null)) != 0; | |
2191 bool set2_has_null_ptr = (ptset2.test(_oop_null) | ptset2.test(_noop_null)) != 0; | |
2192 | |
2193 if (set1_has_unknown_ptr && set2_has_null_ptr || | |
2194 set2_has_unknown_ptr && set1_has_null_ptr) { | |
2195 // Check nullness of unknown object. | |
2196 return NULL; | |
2197 } | |
2198 | |
2199 // Disjointness by itself is not sufficient since | |
2200 // alias analysis is not complete for escaped objects. | |
2201 // Disjoint sets are definitely unrelated only when | |
2202 // at least one set has only not escaping objects. | |
2203 if (!set1_has_unknown_ptr && !set1_has_null_ptr) { | |
2204 bool has_only_non_escaping_alloc = true; | |
2205 for (VectorSetI i(&ptset1); i.test(); ++i) { | |
2206 uint pt = i.elem; | |
2207 PointsToNode* ptn = ptnode_adr(pt); | |
2208 Node* obj = ptn->_node; | |
2209 if (ptn->escape_state() != PointsToNode::NoEscape || | |
2210 !(obj->is_Allocate() || obj->is_CallStaticJava())) { | |
2211 has_only_non_escaping_alloc = false; | |
2212 break; | |
2213 } | |
2214 } | |
2215 if (has_only_non_escaping_alloc) { | |
2216 return _pcmp_neq; | |
2217 } | |
2218 } | |
2219 if (!set2_has_unknown_ptr && !set2_has_null_ptr) { | |
2220 bool has_only_non_escaping_alloc = true; | |
2221 for (VectorSetI i(&ptset2); i.test(); ++i) { | |
2222 uint pt = i.elem; | |
2223 PointsToNode* ptn = ptnode_adr(pt); | |
2224 Node* obj = ptn->_node; | |
2225 if (ptn->escape_state() != PointsToNode::NoEscape || | |
2226 !(obj->is_Allocate() || obj->is_CallStaticJava())) { | |
2227 has_only_non_escaping_alloc = false; | |
2228 break; | |
2229 } | |
2230 } | |
2231 if (has_only_non_escaping_alloc) { | |
2232 return _pcmp_neq; | |
2233 } | |
2234 } | |
2235 return NULL; | |
2236 } | |
2237 | |
0 | 2238 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) { |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2239 bool is_arraycopy = false; |
0 | 2240 switch (call->Opcode()) { |
65 | 2241 #ifdef ASSERT |
0 | 2242 case Op_Allocate: |
2243 case Op_AllocateArray: | |
2244 case Op_Lock: | |
2245 case Op_Unlock: | |
65 | 2246 assert(false, "should be done already"); |
0 | 2247 break; |
65 | 2248 #endif |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2249 case Op_CallLeafNoFP: |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2250 is_arraycopy = (call->as_CallLeaf()->_name != NULL && |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2251 strstr(call->as_CallLeaf()->_name, "arraycopy") != 0); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2252 // fall through |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2253 case Op_CallLeaf: |
65 | 2254 { |
2255 // Stub calls, objects do not escape but they are not scale replaceable. | |
2256 // Adjust escape state for outgoing arguments. | |
2257 const TypeTuple * d = call->tf()->domain(); | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2258 bool src_has_oops = false; |
65 | 2259 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { |
2260 const Type* at = d->field_at(i); | |
2261 Node *arg = call->in(i)->uncast(); | |
2262 const Type *aat = phase->type(arg); | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2263 PointsToNode::EscapeState arg_esc = ptnode_adr(arg->_idx)->escape_state(); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2264 if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() && |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2265 (is_arraycopy || arg_esc < PointsToNode::ArgEscape)) { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2266 |
65 | 2267 assert(aat == Type::TOP || aat == TypePtr::NULL_PTR || |
2268 aat->isa_ptr() != NULL, "expecting an Ptr"); | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2269 bool arg_has_oops = aat->isa_oopptr() && |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2270 (aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() || |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2271 (aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass())); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2272 if (i == TypeFunc::Parms) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2273 src_has_oops = arg_has_oops; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2274 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2275 // |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2276 // src or dst could be j.l.Object when other is basic type array: |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2277 // |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2278 // arraycopy(char[],0,Object*,0,size); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2279 // arraycopy(Object*,0,char[],0,size); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2280 // |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2281 // Don't add edges from dst's fields in such cases. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2282 // |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2283 bool arg_is_arraycopy_dest = src_has_oops && is_arraycopy && |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2284 arg_has_oops && (i > TypeFunc::Parms); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2285 #ifdef ASSERT |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2286 if (!(is_arraycopy || |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2287 call->as_CallLeaf()->_name != NULL && |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2288 (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2289 strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 )) |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2290 ) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2291 call->dump(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2292 assert(false, "EA: unexpected CallLeaf"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2293 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2294 #endif |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2295 // Always process arraycopy's destination object since |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2296 // we need to add all possible edges to references in |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2297 // source object. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2298 if (arg_esc >= PointsToNode::ArgEscape && |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2299 !arg_is_arraycopy_dest) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2300 continue; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2301 } |
65 | 2302 set_escape_state(arg->_idx, PointsToNode::ArgEscape); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2303 Node* arg_base = arg; |
65 | 2304 if (arg->is_AddP()) { |
2305 // | |
2306 // The inline_native_clone() case when the arraycopy stub is called | |
2307 // after the allocation before Initialize and CheckCastPP nodes. | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2308 // Or normal arraycopy for object arrays case. |
65 | 2309 // |
2310 // Set AddP's base (Allocate) as not scalar replaceable since | |
2311 // pointer to the base (with offset) is passed as argument. | |
2312 // | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2313 arg_base = get_addp_base(arg); |
65 | 2314 } |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2315 VectorSet argset = *PointsTo(arg_base); // Clone set |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2316 for( VectorSetI j(&argset); j.test(); ++j ) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2317 uint pd = j.elem; // Destination object |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2318 set_escape_state(pd, PointsToNode::ArgEscape); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2319 |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2320 if (arg_is_arraycopy_dest) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2321 PointsToNode* ptd = ptnode_adr(pd); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2322 // Conservatively reference an unknown object since |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2323 // not all source's fields/elements may be known. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2324 add_edge_from_fields(pd, _phantom_object, Type::OffsetBot); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2325 |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2326 Node *src = call->in(TypeFunc::Parms)->uncast(); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2327 Node* src_base = src; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2328 if (src->is_AddP()) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2329 src_base = get_addp_base(src); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2330 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2331 // Create edges from destination's fields to |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2332 // everything known source's fields could point to. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2333 for( VectorSetI s(PointsTo(src_base)); s.test(); ++s ) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2334 uint ps = s.elem; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2335 bool has_bottom_offset = false; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2336 for (uint fd = 0; fd < ptd->edge_count(); fd++) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2337 assert(ptd->edge_type(fd) == PointsToNode::FieldEdge, "expecting a field edge"); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2338 int fdi = ptd->edge_target(fd); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2339 PointsToNode* pfd = ptnode_adr(fdi); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2340 int offset = pfd->offset(); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2341 if (offset == Type::OffsetBot) |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2342 has_bottom_offset = true; |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2343 assert(offset != -1, "offset should be set"); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2344 add_deferred_edge_to_fields(fdi, ps, offset); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2345 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2346 // Destination object may not have access (no field edge) |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2347 // to fields which are accessed in source object. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2348 // As result no edges will be created to those source's |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2349 // fields and escape state of destination object will |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2350 // not be propagated to those fields. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2351 // |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2352 // Mark source object as global escape except in |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2353 // the case with Type::OffsetBot field (which is |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2354 // common case for array elements access) when |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2355 // edges are created to all source's fields. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2356 if (!has_bottom_offset) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2357 set_escape_state(ps, PointsToNode::GlobalEscape); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2358 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2359 } |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2360 } |
65 | 2361 } |
2362 } | |
2363 } | |
2364 break; | |
2365 } | |
0 | 2366 |
2367 case Op_CallStaticJava: | |
2368 // For a static call, we know exactly what method is being called. | |
2369 // Use bytecode estimator to record the call's escape affects | |
2370 { | |
2371 ciMethod *meth = call->as_CallJava()->method(); | |
65 | 2372 BCEscapeAnalyzer *call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL; |
2373 // fall-through if not a Java method or no analyzer information | |
2374 if (call_analyzer != NULL) { | |
0 | 2375 const TypeTuple * d = call->tf()->domain(); |
65 | 2376 bool copy_dependencies = false; |
0 | 2377 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { |
2378 const Type* at = d->field_at(i); | |
2379 int k = i - TypeFunc::Parms; | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2380 Node *arg = call->in(i)->uncast(); |
0 | 2381 |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2382 if (at->isa_oopptr() != NULL && |
1136
4b84186a8248
6913075: EA identifies escape state incorrectly after 6895383 fix
kvn
parents:
1101
diff
changeset
|
2383 ptnode_adr(arg->_idx)->escape_state() < PointsToNode::GlobalEscape) { |
0 | 2384 |
65 | 2385 bool global_escapes = false; |
2386 bool fields_escapes = false; | |
2387 if (!call_analyzer->is_arg_stack(k)) { | |
2388 // The argument global escapes, mark everything it could point to | |
2389 set_escape_state(arg->_idx, PointsToNode::GlobalEscape); | |
2390 global_escapes = true; | |
2391 } else { | |
2392 if (!call_analyzer->is_arg_local(k)) { | |
2393 // The argument itself doesn't escape, but any fields might | |
2394 fields_escapes = true; | |
0 | 2395 } |
65 | 2396 set_escape_state(arg->_idx, PointsToNode::ArgEscape); |
2397 copy_dependencies = true; | |
2398 } | |
2399 | |
2249 | 2400 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { |
65 | 2401 uint pt = j.elem; |
2402 if (global_escapes) { | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2403 // The argument global escapes, mark everything it could point to |
65 | 2404 set_escape_state(pt, PointsToNode::GlobalEscape); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2405 add_edge_from_fields(pt, _phantom_object, Type::OffsetBot); |
65 | 2406 } else { |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2407 set_escape_state(pt, PointsToNode::ArgEscape); |
65 | 2408 if (fields_escapes) { |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2409 // The argument itself doesn't escape, but any fields might. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2410 // Use OffsetTop to indicate such case. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2411 add_edge_from_fields(pt, _phantom_object, Type::OffsetTop); |
65 | 2412 } |
0 | 2413 } |
2414 } | |
2415 } | |
2416 } | |
65 | 2417 if (copy_dependencies) |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2418 call_analyzer->copy_dependencies(_compile->dependencies()); |
0 | 2419 break; |
2420 } | |
2421 } | |
2422 | |
2423 default: | |
65 | 2424 // Fall-through here if not a Java method or no analyzer information |
2425 // or some other type of call, assume the worst case: all arguments | |
0 | 2426 // globally escape. |
2427 { | |
2428 // adjust escape state for outgoing arguments | |
2429 const TypeTuple * d = call->tf()->domain(); | |
2430 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { | |
2431 const Type* at = d->field_at(i); | |
2432 if (at->isa_oopptr() != NULL) { | |
65 | 2433 Node *arg = call->in(i)->uncast(); |
2434 set_escape_state(arg->_idx, PointsToNode::GlobalEscape); | |
2249 | 2435 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { |
0 | 2436 uint pt = j.elem; |
2437 set_escape_state(pt, PointsToNode::GlobalEscape); | |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2438 add_edge_from_fields(pt, _phantom_object, Type::OffsetBot); |
0 | 2439 } |
2440 } | |
2441 } | |
2442 } | |
2443 } | |
2444 } | |
2445 void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *phase) { | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2446 CallNode *call = resproj->in(0)->as_Call(); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2447 uint call_idx = call->_idx; |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2448 uint resproj_idx = resproj->_idx; |
0 | 2449 |
2450 switch (call->Opcode()) { | |
2451 case Op_Allocate: | |
2452 { | |
2453 Node *k = call->in(AllocateNode::KlassNode); | |
1539
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2454 const TypeKlassPtr *kt = k->bottom_type()->isa_klassptr(); |
0 | 2455 assert(kt != NULL, "TypeKlassPtr required."); |
2456 ciKlass* cik = kt->klass(); | |
2457 | |
65 | 2458 PointsToNode::EscapeState es; |
2459 uint edge_to; | |
1539
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2460 if (cik->is_subclass_of(_compile->env()->Thread_klass()) || |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2461 !cik->is_instance_klass() || // StressReflectiveCode |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2462 cik->as_instance_klass()->has_finalizer()) { |
65 | 2463 es = PointsToNode::GlobalEscape; |
2464 edge_to = _phantom_object; // Could not be worse | |
0 | 2465 } else { |
65 | 2466 es = PointsToNode::NoEscape; |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2467 edge_to = call_idx; |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2468 assert(ptnode_adr(call_idx)->scalar_replaceable(), "sanity"); |
0 | 2469 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2470 set_escape_state(call_idx, es); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2471 add_pointsto_edge(resproj_idx, edge_to); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2472 _processed.set(resproj_idx); |
0 | 2473 break; |
2474 } | |
2475 | |
2476 case Op_AllocateArray: | |
2477 { | |
1539
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2478 |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2479 Node *k = call->in(AllocateNode::KlassNode); |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2480 const TypeKlassPtr *kt = k->bottom_type()->isa_klassptr(); |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2481 assert(kt != NULL, "TypeKlassPtr required."); |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2482 ciKlass* cik = kt->klass(); |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2483 |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2484 PointsToNode::EscapeState es; |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2485 uint edge_to; |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2486 if (!cik->is_array_klass()) { // StressReflectiveCode |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2487 es = PointsToNode::GlobalEscape; |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2488 edge_to = _phantom_object; |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2489 } else { |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2490 es = PointsToNode::NoEscape; |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2491 edge_to = call_idx; |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2492 assert(ptnode_adr(call_idx)->scalar_replaceable(), "sanity"); |
1539
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2493 int length = call->in(AllocateNode::ALength)->find_int_con(-1); |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2494 if (length < 0 || length > EliminateAllocationArraySizeLimit) { |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2495 // Not scalar replaceable if the length is not constant or too big. |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2496 ptnode_adr(call_idx)->set_scalar_replaceable(false); |
1539
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2497 } |
65 | 2498 } |
1539
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2499 set_escape_state(call_idx, es); |
c52275c698d1
6953267: assert in EA code with -XX:+StressReflectiveCode
kvn
parents:
1136
diff
changeset
|
2500 add_pointsto_edge(resproj_idx, edge_to); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2501 _processed.set(resproj_idx); |
0 | 2502 break; |
2503 } | |
2504 | |
2505 case Op_CallStaticJava: | |
2506 // For a static call, we know exactly what method is being called. | |
2507 // Use bytecode estimator to record whether the call's return value escapes | |
2508 { | |
65 | 2509 bool done = true; |
0 | 2510 const TypeTuple *r = call->tf()->range(); |
2511 const Type* ret_type = NULL; | |
2512 | |
2513 if (r->cnt() > TypeFunc::Parms) | |
2514 ret_type = r->field_at(TypeFunc::Parms); | |
2515 | |
2516 // Note: we use isa_ptr() instead of isa_oopptr() here because the | |
2517 // _multianewarray functions return a TypeRawPtr. | |
65 | 2518 if (ret_type == NULL || ret_type->isa_ptr() == NULL) { |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2519 _processed.set(resproj_idx); |
0 | 2520 break; // doesn't return a pointer type |
65 | 2521 } |
0 | 2522 ciMethod *meth = call->as_CallJava()->method(); |
65 | 2523 const TypeTuple * d = call->tf()->domain(); |
0 | 2524 if (meth == NULL) { |
2525 // not a Java method, assume global escape | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2526 set_escape_state(call_idx, PointsToNode::GlobalEscape); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2527 add_pointsto_edge(resproj_idx, _phantom_object); |
0 | 2528 } else { |
65 | 2529 BCEscapeAnalyzer *call_analyzer = meth->get_bcea(); |
2530 bool copy_dependencies = false; | |
0 | 2531 |
65 | 2532 if (call_analyzer->is_return_allocated()) { |
2533 // Returns a newly allocated unescaped object, simply | |
2534 // update dependency information. | |
2535 // Mark it as NoEscape so that objects referenced by | |
2536 // it's fields will be marked as NoEscape at least. | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2537 set_escape_state(call_idx, PointsToNode::NoEscape); |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2538 ptnode_adr(call_idx)->set_scalar_replaceable(false); |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2539 // Fields values are unknown |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2540 add_edge_from_fields(call_idx, _phantom_object, Type::OffsetBot); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2541 add_pointsto_edge(resproj_idx, call_idx); |
65 | 2542 copy_dependencies = true; |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2543 } else { |
0 | 2544 // determine whether any arguments are returned |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2545 set_escape_state(call_idx, PointsToNode::ArgEscape); |
307
892493c3d862
6732732: CTW with EA: assert(n != 0L,"Bad immediate dominator info.")
kvn
parents:
306
diff
changeset
|
2546 bool ret_arg = false; |
0 | 2547 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { |
2548 const Type* at = d->field_at(i); | |
2549 if (at->isa_oopptr() != NULL) { | |
65 | 2550 Node *arg = call->in(i)->uncast(); |
0 | 2551 |
65 | 2552 if (call_analyzer->is_arg_returned(i - TypeFunc::Parms)) { |
307
892493c3d862
6732732: CTW with EA: assert(n != 0L,"Bad immediate dominator info.")
kvn
parents:
306
diff
changeset
|
2553 ret_arg = true; |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2554 PointsToNode *arg_esp = ptnode_adr(arg->_idx); |
65 | 2555 if (arg_esp->node_type() == PointsToNode::UnknownType) |
2556 done = false; | |
2557 else if (arg_esp->node_type() == PointsToNode::JavaObject) | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2558 add_pointsto_edge(resproj_idx, arg->_idx); |
0 | 2559 else |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2560 add_deferred_edge(resproj_idx, arg->_idx); |
0 | 2561 } |
2562 } | |
2563 } | |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2564 if (done) { |
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2565 copy_dependencies = true; |
4122
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2566 // is_return_local() is true when only arguments are returned. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2567 if (!ret_arg || !call_analyzer->is_return_local()) { |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2568 // Returns unknown object. |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2569 add_pointsto_edge(resproj_idx, _phantom_object); |
cc81b9c09bbb
7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE
kvn
parents:
4115
diff
changeset
|
2570 } |
4058
59e515ee9354
7059047: EA: can't find initializing store with several CheckCastPP
kvn
parents:
4046
diff
changeset
|
2571 } |
0 | 2572 } |
65 | 2573 if (copy_dependencies) |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2574 call_analyzer->copy_dependencies(_compile->dependencies()); |
0 | 2575 } |
65 | 2576 if (done) |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2577 _processed.set(resproj_idx); |
0 | 2578 break; |
2579 } | |
2580 | |
2581 default: | |
2582 // Some other type of call, assume the worst case that the | |
2583 // returned value, if any, globally escapes. | |
2584 { | |
2585 const TypeTuple *r = call->tf()->range(); | |
2586 if (r->cnt() > TypeFunc::Parms) { | |
2587 const Type* ret_type = r->field_at(TypeFunc::Parms); | |
2588 | |
2589 // Note: we use isa_ptr() instead of isa_oopptr() here because the | |
2590 // _multianewarray functions return a TypeRawPtr. | |
2591 if (ret_type->isa_ptr() != NULL) { | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2592 set_escape_state(call_idx, PointsToNode::GlobalEscape); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2593 add_pointsto_edge(resproj_idx, _phantom_object); |
0 | 2594 } |
2595 } | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2596 _processed.set(resproj_idx); |
0 | 2597 } |
2598 } | |
2599 } | |
2600 | |
65 | 2601 // Populate Connection Graph with Ideal nodes and create simple |
2602 // connection graph edges (do not need to check the node_type of inputs | |
2603 // or to call PointsTo() to walk the connection graph). | |
2604 void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) { | |
2605 if (_processed.test(n->_idx)) | |
2606 return; // No need to redefine node's state. | |
2607 | |
2608 if (n->is_Call()) { | |
2609 // Arguments to allocation and locking don't escape. | |
2610 if (n->is_Allocate()) { | |
2611 add_node(n, PointsToNode::JavaObject, PointsToNode::UnknownEscape, true); | |
2612 record_for_optimizer(n); | |
2613 } else if (n->is_Lock() || n->is_Unlock()) { | |
2614 // Put Lock and Unlock nodes on IGVN worklist to process them during | |
2615 // the first IGVN optimization when escape information is still available. | |
2616 record_for_optimizer(n); | |
2617 _processed.set(n->_idx); | |
2618 } else { | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2619 // Don't mark as processed since call's arguments have to be processed. |
65 | 2620 PointsToNode::NodeType nt = PointsToNode::UnknownType; |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2621 PointsToNode::EscapeState es = PointsToNode::UnknownEscape; |
65 | 2622 |
2623 // Check if a call returns an object. | |
2624 const TypeTuple *r = n->as_Call()->tf()->range(); | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2625 if (r->cnt() > TypeFunc::Parms && |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2626 r->field_at(TypeFunc::Parms)->isa_ptr() && |
65 | 2627 n->as_Call()->proj_out(TypeFunc::Parms) != NULL) { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2628 nt = PointsToNode::JavaObject; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2629 if (!n->is_CallStaticJava()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2630 // Since the called mathod is statically unknown assume |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2631 // the worst case that the returned value globally escapes. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2632 es = PointsToNode::GlobalEscape; |
65 | 2633 } |
2634 } | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2635 add_node(n, nt, es, false); |
65 | 2636 } |
2637 return; | |
2638 } | |
2639 | |
2640 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because | |
2641 // ThreadLocal has RawPrt type. | |
2642 switch (n->Opcode()) { | |
2643 case Op_AddP: | |
2644 { | |
2645 add_node(n, PointsToNode::Field, PointsToNode::UnknownEscape, false); | |
2646 break; | |
2647 } | |
2648 case Op_CastX2P: | |
2649 { // "Unsafe" memory access. | |
2650 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true); | |
2651 break; | |
2652 } | |
2653 case Op_CastPP: | |
2654 case Op_CheckCastPP: | |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
2655 case Op_EncodeP: |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
2656 case Op_DecodeN: |
65 | 2657 { |
2658 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); | |
2659 int ti = n->in(1)->_idx; | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2660 PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); |
65 | 2661 if (nt == PointsToNode::UnknownType) { |
2662 _delayed_worklist.push(n); // Process it later. | |
2663 break; | |
2664 } else if (nt == PointsToNode::JavaObject) { | |
2665 add_pointsto_edge(n->_idx, ti); | |
2666 } else { | |
2667 add_deferred_edge(n->_idx, ti); | |
2668 } | |
2669 _processed.set(n->_idx); | |
2670 break; | |
2671 } | |
2672 case Op_ConP: | |
2673 { | |
2674 // assume all pointer constants globally escape except for null | |
2675 PointsToNode::EscapeState es; | |
2676 if (phase->type(n) == TypePtr::NULL_PTR) | |
2677 es = PointsToNode::NoEscape; | |
2678 else | |
2679 es = PointsToNode::GlobalEscape; | |
0 | 2680 |
65 | 2681 add_node(n, PointsToNode::JavaObject, es, true); |
2682 break; | |
2683 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2684 case Op_ConN: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2685 { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2686 // assume all narrow oop constants globally escape except for null |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2687 PointsToNode::EscapeState es; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2688 if (phase->type(n) == TypeNarrowOop::NULL_PTR) |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2689 es = PointsToNode::NoEscape; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2690 else |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2691 es = PointsToNode::GlobalEscape; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2692 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2693 add_node(n, PointsToNode::JavaObject, es, true); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2694 break; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2695 } |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
2696 case Op_CreateEx: |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
2697 { |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
2698 // assume that all exception objects globally escape |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
2699 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true); |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
2700 break; |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
2701 } |
65 | 2702 case Op_LoadKlass: |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2703 case Op_LoadNKlass: |
65 | 2704 { |
2705 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true); | |
2706 break; | |
2707 } | |
2708 case Op_LoadP: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2709 case Op_LoadN: |
65 | 2710 { |
2711 const Type *t = phase->type(n); | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
2712 if (t->make_ptr() == NULL) { |
65 | 2713 _processed.set(n->_idx); |
2714 return; | |
2715 } | |
2716 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); | |
2717 break; | |
2718 } | |
2719 case Op_Parm: | |
2720 { | |
2721 _processed.set(n->_idx); // No need to redefine it state. | |
2722 uint con = n->as_Proj()->_con; | |
2723 if (con < TypeFunc::Parms) | |
2724 return; | |
2725 const Type *t = n->in(0)->as_Start()->_domain->field_at(con); | |
2726 if (t->isa_ptr() == NULL) | |
2727 return; | |
2728 // We have to assume all input parameters globally escape | |
2729 // (Note: passing 'false' since _processed is already set). | |
2730 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, false); | |
2731 break; | |
2732 } | |
4113 | 2733 case Op_PartialSubtypeCheck: |
2734 { // Produces Null or notNull and is used in CmpP. | |
2735 add_node(n, PointsToNode::JavaObject, PointsToNode::ArgEscape, true); | |
2736 break; | |
2737 } | |
65 | 2738 case Op_Phi: |
2739 { | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
2740 const Type *t = n->as_Phi()->type(); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
2741 if (t->make_ptr() == NULL) { |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
2742 // nothing to do if not an oop or narrow oop |
65 | 2743 _processed.set(n->_idx); |
2744 return; | |
2745 } | |
2746 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); | |
2747 uint i; | |
2748 for (i = 1; i < n->req() ; i++) { | |
2749 Node* in = n->in(i); | |
2750 if (in == NULL) | |
2751 continue; // ignore NULL | |
2752 in = in->uncast(); | |
2753 if (in->is_top() || in == n) | |
2754 continue; // ignore top or inputs which go back this node | |
2755 int ti = in->_idx; | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2756 PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); |
65 | 2757 if (nt == PointsToNode::UnknownType) { |
2758 break; | |
2759 } else if (nt == PointsToNode::JavaObject) { | |
2760 add_pointsto_edge(n->_idx, ti); | |
2761 } else { | |
2762 add_deferred_edge(n->_idx, ti); | |
2763 } | |
2764 } | |
2765 if (i >= n->req()) | |
2766 _processed.set(n->_idx); | |
2767 else | |
2768 _delayed_worklist.push(n); | |
2769 break; | |
2770 } | |
2771 case Op_Proj: | |
2772 { | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2773 // we are only interested in the oop result projection from a call |
65 | 2774 if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2775 const TypeTuple *r = n->in(0)->as_Call()->tf()->range(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2776 assert(r->cnt() > TypeFunc::Parms, "sanity"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2777 if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2778 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2779 int ti = n->in(0)->_idx; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2780 // The call may not be registered yet (since not all its inputs are registered) |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2781 // if this is the projection from backbranch edge of Phi. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2782 if (ptnode_adr(ti)->node_type() != PointsToNode::UnknownType) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2783 process_call_result(n->as_Proj(), phase); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2784 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2785 if (!_processed.test(n->_idx)) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2786 // The call's result may need to be processed later if the call |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2787 // returns it's argument and the argument is not processed yet. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2788 _delayed_worklist.push(n); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2789 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2790 break; |
65 | 2791 } |
2792 } | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2793 _processed.set(n->_idx); |
65 | 2794 break; |
2795 } | |
2796 case Op_Return: | |
2797 { | |
2798 if( n->req() > TypeFunc::Parms && | |
2799 phase->type(n->in(TypeFunc::Parms))->isa_oopptr() ) { | |
2800 // Treat Return value as LocalVar with GlobalEscape escape state. | |
2801 add_node(n, PointsToNode::LocalVar, PointsToNode::GlobalEscape, false); | |
2802 int ti = n->in(TypeFunc::Parms)->_idx; | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2803 PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); |
65 | 2804 if (nt == PointsToNode::UnknownType) { |
2805 _delayed_worklist.push(n); // Process it later. | |
2806 break; | |
2807 } else if (nt == PointsToNode::JavaObject) { | |
2808 add_pointsto_edge(n->_idx, ti); | |
2809 } else { | |
2810 add_deferred_edge(n->_idx, ti); | |
2811 } | |
2812 } | |
2813 _processed.set(n->_idx); | |
2814 break; | |
2815 } | |
2816 case Op_StoreP: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2817 case Op_StoreN: |
65 | 2818 { |
2819 const Type *adr_type = phase->type(n->in(MemNode::Address)); | |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
168
diff
changeset
|
2820 adr_type = adr_type->make_ptr(); |
65 | 2821 if (adr_type->isa_oopptr()) { |
2822 add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false); | |
2823 } else { | |
2824 Node* adr = n->in(MemNode::Address); | |
2825 if (adr->is_AddP() && phase->type(adr) == TypeRawPtr::NOTNULL && | |
2826 adr->in(AddPNode::Address)->is_Proj() && | |
2827 adr->in(AddPNode::Address)->in(0)->is_Allocate()) { | |
2828 add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false); | |
2829 // We are computing a raw address for a store captured | |
2830 // by an Initialize compute an appropriate address type. | |
2831 int offs = (int)phase->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot); | |
2832 assert(offs != Type::OffsetBot, "offset must be a constant"); | |
2833 } else { | |
2834 _processed.set(n->_idx); | |
2835 return; | |
2836 } | |
2837 } | |
2838 break; | |
2839 } | |
2840 case Op_StorePConditional: | |
2841 case Op_CompareAndSwapP: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2842 case Op_CompareAndSwapN: |
65 | 2843 { |
2844 const Type *adr_type = phase->type(n->in(MemNode::Address)); | |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
168
diff
changeset
|
2845 adr_type = adr_type->make_ptr(); |
65 | 2846 if (adr_type->isa_oopptr()) { |
2847 add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false); | |
2848 } else { | |
2849 _processed.set(n->_idx); | |
2850 return; | |
2851 } | |
2852 break; | |
2853 } | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2854 case Op_AryEq: |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2855 case Op_StrComp: |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2856 case Op_StrEquals: |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2857 case Op_StrIndexOf: |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2858 { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2859 // char[] arrays passed to string intrinsics are not scalar replaceable. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2860 add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2861 break; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2862 } |
65 | 2863 case Op_ThreadLocal: |
2864 { | |
2865 add_node(n, PointsToNode::JavaObject, PointsToNode::ArgEscape, true); | |
2866 break; | |
2867 } | |
2868 default: | |
2869 ; | |
2870 // nothing to do | |
2871 } | |
2872 return; | |
2873 } | |
2874 | |
2875 void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2876 uint n_idx = n->_idx; |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2877 assert(ptnode_adr(n_idx)->_node != NULL, "node should be registered"); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2878 |
65 | 2879 // Don't set processed bit for AddP, LoadP, StoreP since |
2880 // they may need more then one pass to process. | |
1921 | 2881 // Also don't mark as processed Call nodes since their |
2882 // arguments may need more then one pass to process. | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2883 if (_processed.test(n_idx)) |
65 | 2884 return; // No need to redefine node's state. |
2885 | |
0 | 2886 if (n->is_Call()) { |
2887 CallNode *call = n->as_Call(); | |
2888 process_call_arguments(call, phase); | |
2889 return; | |
2890 } | |
2891 | |
65 | 2892 switch (n->Opcode()) { |
0 | 2893 case Op_AddP: |
2894 { | |
65 | 2895 Node *base = get_addp_base(n); |
4113 | 2896 int offset = address_offset(n, phase); |
65 | 2897 // Create a field edge to this node from everything base could point to. |
2249 | 2898 for( VectorSetI i(PointsTo(base)); i.test(); ++i ) { |
0 | 2899 uint pt = i.elem; |
4113 | 2900 add_field_edge(pt, n_idx, offset); |
65 | 2901 } |
2902 break; | |
2903 } | |
2904 case Op_CastX2P: | |
2905 { | |
2906 assert(false, "Op_CastX2P"); | |
2907 break; | |
2908 } | |
2909 case Op_CastPP: | |
2910 case Op_CheckCastPP: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2911 case Op_EncodeP: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
102
diff
changeset
|
2912 case Op_DecodeN: |
65 | 2913 { |
2914 int ti = n->in(1)->_idx; | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
2915 assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "all nodes should be registered"); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2916 if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2917 add_pointsto_edge(n_idx, ti); |
65 | 2918 } else { |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2919 add_deferred_edge(n_idx, ti); |
65 | 2920 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2921 _processed.set(n_idx); |
65 | 2922 break; |
2923 } | |
2924 case Op_ConP: | |
2925 { | |
2926 assert(false, "Op_ConP"); | |
2927 break; | |
2928 } | |
163 | 2929 case Op_ConN: |
2930 { | |
2931 assert(false, "Op_ConN"); | |
2932 break; | |
2933 } | |
65 | 2934 case Op_CreateEx: |
2935 { | |
2936 assert(false, "Op_CreateEx"); | |
2937 break; | |
2938 } | |
2939 case Op_LoadKlass: | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2940 case Op_LoadNKlass: |
65 | 2941 { |
2942 assert(false, "Op_LoadKlass"); | |
2943 break; | |
2944 } | |
2945 case Op_LoadP: | |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
2946 case Op_LoadN: |
65 | 2947 { |
2948 const Type *t = phase->type(n); | |
2949 #ifdef ASSERT | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
2950 if (t->make_ptr() == NULL) |
65 | 2951 assert(false, "Op_LoadP"); |
2952 #endif | |
2953 | |
2954 Node* adr = n->in(MemNode::Address)->uncast(); | |
2955 Node* adr_base; | |
2956 if (adr->is_AddP()) { | |
2957 adr_base = get_addp_base(adr); | |
2958 } else { | |
2959 adr_base = adr; | |
2960 } | |
2961 | |
2962 // For everything "adr_base" could point to, create a deferred edge from | |
2963 // this node to each field with the same offset. | |
2964 int offset = address_offset(adr, phase); | |
2249 | 2965 for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) { |
65 | 2966 uint pt = i.elem; |
4113 | 2967 if (adr->is_AddP()) { |
2968 // Add field edge if it is missing. | |
2969 add_field_edge(pt, adr->_idx, offset); | |
2970 } | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
2971 add_deferred_edge_to_fields(n_idx, pt, offset); |
0 | 2972 } |
2973 break; | |
2974 } | |
2975 case Op_Parm: | |
2976 { | |
65 | 2977 assert(false, "Op_Parm"); |
0 | 2978 break; |
2979 } | |
4113 | 2980 case Op_PartialSubtypeCheck: |
2981 { | |
2982 assert(false, "Op_PartialSubtypeCheck"); | |
2983 break; | |
2984 } | |
0 | 2985 case Op_Phi: |
2986 { | |
65 | 2987 #ifdef ASSERT |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
2988 const Type *t = n->as_Phi()->type(); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
2989 if (t->make_ptr() == NULL) |
65 | 2990 assert(false, "Op_Phi"); |
2991 #endif | |
2992 for (uint i = 1; i < n->req() ; i++) { | |
2993 Node* in = n->in(i); | |
2994 if (in == NULL) | |
2995 continue; // ignore NULL | |
2996 in = in->uncast(); | |
2997 if (in->is_top() || in == n) | |
2998 continue; // ignore top or inputs which go back this node | |
2999 int ti = in->_idx; | |
307
892493c3d862
6732732: CTW with EA: assert(n != 0L,"Bad immediate dominator info.")
kvn
parents:
306
diff
changeset
|
3000 PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); |
892493c3d862
6732732: CTW with EA: assert(n != 0L,"Bad immediate dominator info.")
kvn
parents:
306
diff
changeset
|
3001 assert(nt != PointsToNode::UnknownType, "all nodes should be known"); |
892493c3d862
6732732: CTW with EA: assert(n != 0L,"Bad immediate dominator info.")
kvn
parents:
306
diff
changeset
|
3002 if (nt == PointsToNode::JavaObject) { |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3003 add_pointsto_edge(n_idx, ti); |
65 | 3004 } else { |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3005 add_deferred_edge(n_idx, ti); |
65 | 3006 } |
3007 } | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3008 _processed.set(n_idx); |
0 | 3009 break; |
3010 } | |
65 | 3011 case Op_Proj: |
0 | 3012 { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3013 // we are only interested in the oop result projection from a call |
65 | 3014 if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) { |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3015 assert(ptnode_adr(n->in(0)->_idx)->node_type() != PointsToNode::UnknownType, |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3016 "all nodes should be registered"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3017 const TypeTuple *r = n->in(0)->as_Call()->tf()->range(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3018 assert(r->cnt() > TypeFunc::Parms, "sanity"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3019 if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3020 process_call_result(n->as_Proj(), phase); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3021 assert(_processed.test(n_idx), "all call results should be processed"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3022 break; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3023 } |
65 | 3024 } |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3025 assert(false, "Op_Proj"); |
0 | 3026 break; |
3027 } | |
65 | 3028 case Op_Return: |
0 | 3029 { |
65 | 3030 #ifdef ASSERT |
3031 if( n->req() <= TypeFunc::Parms || | |
3032 !phase->type(n->in(TypeFunc::Parms))->isa_oopptr() ) { | |
3033 assert(false, "Op_Return"); | |
0 | 3034 } |
65 | 3035 #endif |
3036 int ti = n->in(TypeFunc::Parms)->_idx; | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3037 assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "node should be registered"); |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3038 if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3039 add_pointsto_edge(n_idx, ti); |
65 | 3040 } else { |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3041 add_deferred_edge(n_idx, ti); |
65 | 3042 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3043 _processed.set(n_idx); |
0 | 3044 break; |
3045 } | |
3046 case Op_StoreP: | |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
3047 case Op_StoreN: |
0 | 3048 case Op_StorePConditional: |
3049 case Op_CompareAndSwapP: | |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
3050 case Op_CompareAndSwapN: |
0 | 3051 { |
3052 Node *adr = n->in(MemNode::Address); | |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
168
diff
changeset
|
3053 const Type *adr_type = phase->type(adr)->make_ptr(); |
65 | 3054 #ifdef ASSERT |
0 | 3055 if (!adr_type->isa_oopptr()) |
65 | 3056 assert(phase->type(adr) == TypeRawPtr::NOTNULL, "Op_StoreP"); |
3057 #endif | |
0 | 3058 |
65 | 3059 assert(adr->is_AddP(), "expecting an AddP"); |
3060 Node *adr_base = get_addp_base(adr); | |
3061 Node *val = n->in(MemNode::ValueIn)->uncast(); | |
4113 | 3062 int offset = address_offset(adr, phase); |
65 | 3063 // For everything "adr_base" could point to, create a deferred edge |
3064 // to "val" from each field with the same offset. | |
2249 | 3065 for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) { |
0 | 3066 uint pt = i.elem; |
4113 | 3067 // Add field edge if it is missing. |
3068 add_field_edge(pt, adr->_idx, offset); | |
3069 add_edge_from_fields(pt, val->_idx, offset); | |
0 | 3070 } |
3071 break; | |
3072 } | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3073 case Op_AryEq: |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3074 case Op_StrComp: |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3075 case Op_StrEquals: |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3076 case Op_StrIndexOf: |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3077 { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3078 // char[] arrays passed to string intrinsic do not escape but |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3079 // they are not scalar replaceable. Adjust escape state for them. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3080 // Start from in(2) edge since in(1) is memory edge. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3081 for (uint i = 2; i < n->req(); i++) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3082 Node* adr = n->in(i)->uncast(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3083 const Type *at = phase->type(adr); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3084 if (!adr->is_top() && at->isa_ptr()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3085 assert(at == Type::TOP || at == TypePtr::NULL_PTR || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3086 at->isa_ptr() != NULL, "expecting an Ptr"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3087 if (adr->is_AddP()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3088 adr = get_addp_base(adr); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3089 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3090 // Mark as ArgEscape everything "adr" could point to. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3091 set_escape_state(adr->_idx, PointsToNode::ArgEscape); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3092 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3093 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3094 _processed.set(n_idx); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3095 break; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3096 } |
65 | 3097 case Op_ThreadLocal: |
0 | 3098 { |
65 | 3099 assert(false, "Op_ThreadLocal"); |
0 | 3100 break; |
3101 } | |
3102 default: | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3103 // This method should be called only for EA specific nodes. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1072
diff
changeset
|
3104 ShouldNotReachHere(); |
0 | 3105 } |
3106 } | |
3107 | |
3108 #ifndef PRODUCT | |
3109 void ConnectionGraph::dump() { | |
3110 bool first = true; | |
3111 | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3112 uint size = nodes_size(); |
65 | 3113 for (uint ni = 0; ni < size; ni++) { |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3114 PointsToNode *ptn = ptnode_adr(ni); |
65 | 3115 PointsToNode::NodeType ptn_type = ptn->node_type(); |
3116 | |
3117 if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL) | |
0 | 3118 continue; |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
3119 PointsToNode::EscapeState es = escape_state(ptn->_node); |
65 | 3120 if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) { |
3121 if (first) { | |
3122 tty->cr(); | |
3123 tty->print("======== Connection graph for "); | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3124 _compile->method()->print_short_name(); |
65 | 3125 tty->cr(); |
3126 first = false; | |
3127 } | |
3128 tty->print("%6d ", ni); | |
3129 ptn->dump(); | |
3130 // Print all locals which reference this allocation | |
3131 for (uint li = ni; li < size; li++) { | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
223
diff
changeset
|
3132 PointsToNode *ptn_loc = ptnode_adr(li); |
65 | 3133 PointsToNode::NodeType ptn_loc_type = ptn_loc->node_type(); |
3134 if ( ptn_loc_type == PointsToNode::LocalVar && ptn_loc->_node != NULL && | |
3135 ptn_loc->edge_count() == 1 && ptn_loc->edge_target(0) == ni ) { | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
3136 ptnode_adr(li)->dump(false); |
0 | 3137 } |
3138 } | |
65 | 3139 if (Verbose) { |
3140 // Print all fields which reference this allocation | |
3141 for (uint i = 0; i < ptn->edge_count(); i++) { | |
3142 uint ei = ptn->edge_target(i); | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
3143 ptnode_adr(ei)->dump(false); |
65 | 3144 } |
3145 } | |
3146 tty->cr(); | |
0 | 3147 } |
3148 } | |
3149 } | |
3150 #endif |