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