Mercurial > hg > truffle
annotate src/share/vm/opto/escape.hpp @ 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 | e4fcbeb5a698 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1101
diff
changeset
|
2 * Copyright (c) 2005, 2008, 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:
1101
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1101
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:
1101
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 // | |
26 // Adaptation for C2 of the escape analysis algorithm described in: | |
27 // | |
65 | 28 // [Choi99] Jong-Deok Shoi, Manish Gupta, Mauricio Seffano, |
29 // Vugranam C. Sreedhar, Sam Midkiff, | |
30 // "Escape Analysis for Java", Procedings of ACM SIGPLAN | |
31 // OOPSLA Conference, November 1, 1999 | |
0 | 32 // |
33 // The flow-insensitive analysis described in the paper has been implemented. | |
34 // | |
65 | 35 // The analysis requires construction of a "connection graph" (CG) for |
36 // the method being analyzed. The nodes of the connection graph are: | |
0 | 37 // |
38 // - Java objects (JO) | |
39 // - Local variables (LV) | |
40 // - Fields of an object (OF), these also include array elements | |
41 // | |
42 // The CG contains 3 types of edges: | |
43 // | |
65 | 44 // - PointsTo (-P>) {LV, OF} to JO |
45 // - Deferred (-D>) from {LV, OF} to {LV, OF} | |
0 | 46 // - Field (-F>) from JO to OF |
47 // | |
48 // The following utility functions is used by the algorithm: | |
49 // | |
65 | 50 // PointsTo(n) - n is any CG node, it returns the set of JO that n could |
51 // point to. | |
0 | 52 // |
65 | 53 // The algorithm describes how to construct the connection graph |
54 // in the following 4 cases: | |
0 | 55 // |
56 // Case Edges Created | |
57 // | |
65 | 58 // (1) p = new T() LV -P> JO |
59 // (2) p = q LV -D> LV | |
60 // (3) p.f = q JO -F> OF, OF -D> LV | |
61 // (4) p = q.f JO -F> OF, LV -D> OF | |
0 | 62 // |
65 | 63 // In all these cases, p and q are local variables. For static field |
64 // references, we can construct a local variable containing a reference | |
65 // to the static memory. | |
0 | 66 // |
67 // C2 does not have local variables. However for the purposes of constructing | |
68 // the connection graph, the following IR nodes are treated as local variables: | |
69 // Phi (pointer values) | |
70 // LoadP | |
65 | 71 // Proj#5 (value returned from callnodes including allocations) |
72 // CheckCastPP, CastPP | |
0 | 73 // |
65 | 74 // The LoadP, Proj and CheckCastPP behave like variables assigned to only once. |
75 // Only a Phi can have multiple assignments. Each input to a Phi is treated | |
0 | 76 // as an assignment to it. |
77 // | |
65 | 78 // The following node types are JavaObject: |
0 | 79 // |
80 // top() | |
81 // Allocate | |
82 // AllocateArray | |
83 // Parm (for incoming arguments) | |
65 | 84 // CastX2P ("unsafe" operations) |
0 | 85 // CreateEx |
86 // ConP | |
87 // LoadKlass | |
65 | 88 // ThreadLocal |
0 | 89 // |
90 // AddP nodes are fields. | |
91 // | |
92 // After building the graph, a pass is made over the nodes, deleting deferred | |
93 // nodes and copying the edges from the target of the deferred edge to the | |
94 // source. This results in a graph with no deferred edges, only: | |
95 // | |
96 // LV -P> JO | |
65 | 97 // OF -P> JO (the object whose oop is stored in the field) |
0 | 98 // JO -F> OF |
99 // | |
100 // Then, for each node which is GlobalEscape, anything it could point to | |
101 // is marked GlobalEscape. Finally, for any node marked ArgEscape, anything | |
102 // it could point to is marked ArgEscape. | |
103 // | |
104 | |
105 class Compile; | |
106 class Node; | |
107 class CallNode; | |
108 class PhiNode; | |
109 class PhaseTransform; | |
110 class Type; | |
111 class TypePtr; | |
112 class VectorSet; | |
113 | |
114 class PointsToNode { | |
115 friend class ConnectionGraph; | |
116 public: | |
117 typedef enum { | |
65 | 118 UnknownType = 0, |
119 JavaObject = 1, | |
120 LocalVar = 2, | |
121 Field = 3 | |
0 | 122 } NodeType; |
123 | |
124 typedef enum { | |
125 UnknownEscape = 0, | |
65 | 126 NoEscape = 1, // A scalar replaceable object with unique type. |
127 ArgEscape = 2, // An object passed as argument or referenced by | |
128 // argument (and not globally escape during call). | |
129 GlobalEscape = 3 // An object escapes the method and thread. | |
0 | 130 } EscapeState; |
131 | |
132 typedef enum { | |
133 UnknownEdge = 0, | |
134 PointsToEdge = 1, | |
135 DeferredEdge = 2, | |
136 FieldEdge = 3 | |
137 } EdgeType; | |
138 | |
139 private: | |
140 enum { | |
141 EdgeMask = 3, | |
142 EdgeShift = 2, | |
143 | |
144 INITIAL_EDGE_COUNT = 4 | |
145 }; | |
146 | |
147 NodeType _type; | |
148 EscapeState _escape; | |
65 | 149 GrowableArray<uint>* _edges; // outgoing edges |
0 | 150 |
151 public: | |
65 | 152 Node* _node; // Ideal node corresponding to this PointsTo node. |
153 int _offset; // Object fields offsets. | |
154 bool _scalar_replaceable;// Not escaped object could be replaced with scalar | |
155 bool _hidden_alias; // This node is an argument to a function. | |
156 // which may return it creating a hidden alias. | |
0 | 157 |
65 | 158 PointsToNode(): |
159 _type(UnknownType), | |
160 _escape(UnknownEscape), | |
161 _edges(NULL), | |
162 _node(NULL), | |
163 _offset(-1), | |
164 _scalar_replaceable(true), | |
165 _hidden_alias(false) {} | |
0 | 166 |
167 | |
168 EscapeState escape_state() const { return _escape; } | |
169 NodeType node_type() const { return _type;} | |
170 int offset() { return _offset;} | |
171 | |
172 void set_offset(int offs) { _offset = offs;} | |
173 void set_escape_state(EscapeState state) { _escape = state; } | |
174 void set_node_type(NodeType ntype) { | |
175 assert(_type == UnknownType || _type == ntype, "Can't change node type"); | |
176 _type = ntype; | |
177 } | |
178 | |
179 // count of outgoing edges | |
180 uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); } | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
181 |
0 | 182 // node index of target of outgoing edge "e" |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
183 uint edge_target(uint e) const { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
184 assert(_edges != NULL, "valid edge index"); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
185 return (_edges->at(e) >> EdgeShift); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
186 } |
0 | 187 // type of outgoing edge "e" |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
188 EdgeType edge_type(uint e) const { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
189 assert(_edges != NULL, "valid edge index"); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
190 return (EdgeType) (_edges->at(e) & EdgeMask); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
191 } |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
192 |
0 | 193 // add a edge of the specified type pointing to the specified target |
194 void add_edge(uint targIdx, EdgeType et); | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
195 |
0 | 196 // remove an edge of the specified type pointing to the specified target |
197 void remove_edge(uint targIdx, EdgeType et); | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
198 |
0 | 199 #ifndef PRODUCT |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
245
diff
changeset
|
200 void dump(bool print_state=true) const; |
0 | 201 #endif |
202 | |
203 }; | |
204 | |
205 class ConnectionGraph: public ResourceObj { | |
206 private: | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
207 GrowableArray<PointsToNode> _nodes; // Connection graph nodes indexed |
65 | 208 // by ideal node index. |
0 | 209 |
65 | 210 Unique_Node_List _delayed_worklist; // Nodes to be processed before |
211 // the call build_connection_graph(). | |
212 | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
293
diff
changeset
|
213 GrowableArray<MergeMemNode *> _mergemem_worklist; // List of all MergeMem nodes |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
293
diff
changeset
|
214 |
65 | 215 VectorSet _processed; // Records which nodes have been |
216 // processed. | |
0 | 217 |
65 | 218 bool _collecting; // Indicates whether escape information |
219 // is still being collected. If false, | |
220 // no new nodes will be processed. | |
221 | |
222 uint _phantom_object; // Index of globally escaping object | |
223 // that pointer values loaded from | |
224 // a field which has not been set | |
225 // are assumed to point to. | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
245
diff
changeset
|
226 uint _oop_null; // ConP(#NULL) |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
245
diff
changeset
|
227 uint _noop_null; // ConN(#NULL) |
65 | 228 |
229 Compile * _compile; // Compile object for current compilation | |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
230 PhaseIterGVN * _igvn; // Value numbering |
0 | 231 |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
232 // Address of an element in _nodes. Used when the element is to be modified |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
233 PointsToNode *ptnode_adr(uint idx) const { |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
234 // There should be no new ideal nodes during ConnectionGraph build, |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
235 // growableArray::adr_at() will throw assert otherwise. |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
236 return _nodes.adr_at(idx); |
0 | 237 } |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
238 uint nodes_size() const { return _nodes.length(); } |
0 | 239 |
65 | 240 // Add node to ConnectionGraph. |
241 void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done); | |
242 | |
0 | 243 // offset of a field reference |
65 | 244 int address_offset(Node* adr, PhaseTransform *phase); |
0 | 245 |
246 // compute the escape state for arguments to a call | |
247 void process_call_arguments(CallNode *call, PhaseTransform *phase); | |
248 | |
249 // compute the escape state for the return value of a call | |
250 void process_call_result(ProjNode *resproj, PhaseTransform *phase); | |
251 | |
65 | 252 // Populate Connection Graph with Ideal nodes. |
253 void record_for_escape_analysis(Node *n, PhaseTransform *phase); | |
0 | 254 |
65 | 255 // Build Connection Graph and set nodes escape state. |
256 void build_connection_graph(Node *n, PhaseTransform *phase); | |
0 | 257 |
258 // walk the connection graph starting at the node corresponding to "n" and | |
259 // add the index of everything it could point to, to "ptset". This may cause | |
260 // Phi's encountered to get (re)processed (which requires "phase".) | |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
261 void PointsTo(VectorSet &ptset, Node * n); |
0 | 262 |
263 // Edge manipulation. The "from_i" and "to_i" arguments are the | |
264 // node indices of the source and destination of the edge | |
265 void add_pointsto_edge(uint from_i, uint to_i); | |
266 void add_deferred_edge(uint from_i, uint to_i); | |
267 void add_field_edge(uint from_i, uint to_i, int offs); | |
268 | |
269 | |
270 // Add an edge to node given by "to_i" from any field of adr_i whose offset | |
271 // matches "offset" A deferred edge is added if to_i is a LocalVar, and | |
272 // a pointsto edge is added if it is a JavaObject | |
273 void add_edge_from_fields(uint adr, uint to_i, int offs); | |
274 | |
65 | 275 // Add a deferred edge from node given by "from_i" to any field |
276 // of adr_i whose offset matches "offset" | |
0 | 277 void add_deferred_edge_to_fields(uint from_i, uint adr, int offs); |
278 | |
279 | |
280 // Remove outgoing deferred edges from the node referenced by "ni". | |
281 // Any outgoing edges from the target of the deferred edge are copied | |
282 // to "ni". | |
101
a6cb86dd209b
6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
kvn
parents:
65
diff
changeset
|
283 void remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited); |
0 | 284 |
285 Node_Array _node_map; // used for bookeeping during type splitting | |
286 // Used for the following purposes: | |
287 // Memory Phi - most recent unique Phi split out | |
288 // from this Phi | |
289 // MemNode - new memory input for this node | |
290 // ChecCastPP - allocation that this is a cast of | |
291 // allocation - CheckCastPP of the allocation | |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
292 bool split_AddP(Node *addp, Node *base, PhaseGVN *igvn); |
0 | 293 PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn, bool &new_created); |
294 PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn); | |
1101
7fee0a6cc6d4
6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
kvn
parents:
1100
diff
changeset
|
295 void move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis, PhaseGVN *igvn); |
65 | 296 Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn); |
297 | |
0 | 298 // Propagate unique types created for unescaped allocated objects |
299 // through the graph | |
300 void split_unique_types(GrowableArray<Node *> &alloc_worklist); | |
301 | |
302 // manage entries in _node_map | |
303 void set_map(int idx, Node *n) { _node_map.map(idx, n); } | |
304 Node *get_map(int idx) { return _node_map[idx]; } | |
305 PhiNode *get_map_phi(int idx) { | |
306 Node *phi = _node_map[idx]; | |
307 return (phi == NULL) ? NULL : phi->as_Phi(); | |
308 } | |
309 | |
310 // Notify optimizer that a node has been modified | |
311 // Node: This assumes that escape analysis is run before | |
312 // PhaseIterGVN creation | |
313 void record_for_optimizer(Node *n) { | |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
314 _igvn->_worklist.push(n); |
0 | 315 } |
316 | |
317 // Set the escape state of a node | |
318 void set_escape_state(uint ni, PointsToNode::EscapeState es); | |
319 | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
293
diff
changeset
|
320 // Search for objects which are not scalar replaceable. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
293
diff
changeset
|
321 void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
293
diff
changeset
|
322 |
0 | 323 public: |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
324 ConnectionGraph(Compile *C, PhaseIterGVN *igvn); |
0 | 325 |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
326 // Check for non-escaping candidates |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
327 static bool has_candidates(Compile *C); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
328 |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
329 // Perform escape analysis |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
330 static void do_analysis(Compile *C, PhaseIterGVN *igvn); |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
331 |
65 | 332 // Compute the escape information |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
333 bool compute_escape(); |
0 | 334 |
335 // escape state of a node | |
1634
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
336 PointsToNode::EscapeState escape_state(Node *n); |
60a14ad85270
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
kvn
parents:
1552
diff
changeset
|
337 |
65 | 338 // other information we have collected |
339 bool is_scalar_replaceable(Node *n) { | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
340 if (_collecting || (n->_idx >= nodes_size())) |
65 | 341 return false; |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
342 PointsToNode* ptn = ptnode_adr(n->_idx); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
343 return ptn->escape_state() == PointsToNode::NoEscape && ptn->_scalar_replaceable; |
65 | 344 } |
0 | 345 |
346 bool hidden_alias(Node *n) { | |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
347 if (_collecting || (n->_idx >= nodes_size())) |
0 | 348 return true; |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
349 PointsToNode* ptn = ptnode_adr(n->_idx); |
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
101
diff
changeset
|
350 return (ptn->escape_state() != PointsToNode::NoEscape) || ptn->_hidden_alias; |
0 | 351 } |
352 | |
353 #ifndef PRODUCT | |
354 void dump(); | |
355 #endif | |
356 }; |