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