author | mcberg |
Wed, 16 Sep 2015 13:16:17 -0700 | |
changeset 33065 | 55892792936f |
parent 32084 | 7743e6943cdf |
child 33129 | e0bcbb5015b3 |
permissions | -rw-r--r-- |
1 | 1 |
/* |
32084
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
2 |
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. |
1 | 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 |
* |
|
5547
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
4470
diff
changeset
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
4470
diff
changeset
|
20 |
* or visit www.oracle.com if you need additional information or have any |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
4470
diff
changeset
|
21 |
* questions. |
1 | 22 |
* |
23 |
*/ |
|
24 |
||
7397 | 25 |
#ifndef SHARE_VM_OPTO_NODE_HPP |
26 |
#define SHARE_VM_OPTO_NODE_HPP |
|
27 |
||
28 |
#include "libadt/vectset.hpp" |
|
29 |
#include "opto/compile.hpp" |
|
30 |
#include "opto/type.hpp" |
|
31 |
||
1 | 32 |
// Portions of code courtesy of Clifford Click |
33 |
||
34 |
// Optimization - Graph Style |
|
35 |
||
36 |
||
37 |
class AbstractLockNode; |
|
38 |
class AddNode; |
|
39 |
class AddPNode; |
|
40 |
class AliasInfo; |
|
41 |
class AllocateArrayNode; |
|
42 |
class AllocateNode; |
|
26166 | 43 |
class ArrayCopyNode; |
1 | 44 |
class Block; |
45 |
class BoolNode; |
|
46 |
class BoxLockNode; |
|
47 |
class CMoveNode; |
|
48 |
class CallDynamicJavaNode; |
|
49 |
class CallJavaNode; |
|
50 |
class CallLeafNode; |
|
51 |
class CallNode; |
|
52 |
class CallRuntimeNode; |
|
53 |
class CallStaticJavaNode; |
|
54 |
class CatchNode; |
|
55 |
class CatchProjNode; |
|
56 |
class CheckCastPPNode; |
|
4470
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
57 |
class ClearArrayNode; |
1 | 58 |
class CmpNode; |
59 |
class CodeBuffer; |
|
60 |
class ConstraintCastNode; |
|
61 |
class ConNode; |
|
62 |
class CountedLoopNode; |
|
63 |
class CountedLoopEndNode; |
|
13969
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
64 |
class DecodeNarrowPtrNode; |
594
9f4474e5dbaf
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
375
diff
changeset
|
65 |
class DecodeNNode; |
13969
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
66 |
class DecodeNKlassNode; |
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
67 |
class EncodeNarrowPtrNode; |
594
9f4474e5dbaf
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
375
diff
changeset
|
68 |
class EncodePNode; |
13969
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
69 |
class EncodePKlassNode; |
1 | 70 |
class FastLockNode; |
71 |
class FastUnlockNode; |
|
72 |
class IfNode; |
|
10255 | 73 |
class IfFalseNode; |
74 |
class IfTrueNode; |
|
1 | 75 |
class InitializeNode; |
76 |
class JVMState; |
|
77 |
class JumpNode; |
|
78 |
class JumpProjNode; |
|
79 |
class LoadNode; |
|
80 |
class LoadStoreNode; |
|
81 |
class LockNode; |
|
82 |
class LoopNode; |
|
10266
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
83 |
class MachBranchNode; |
1 | 84 |
class MachCallDynamicJavaNode; |
85 |
class MachCallJavaNode; |
|
86 |
class MachCallLeafNode; |
|
87 |
class MachCallNode; |
|
88 |
class MachCallRuntimeNode; |
|
89 |
class MachCallStaticJavaNode; |
|
7433 | 90 |
class MachConstantBaseNode; |
91 |
class MachConstantNode; |
|
10255 | 92 |
class MachGotoNode; |
1 | 93 |
class MachIfNode; |
94 |
class MachNode; |
|
95 |
class MachNullCheckNode; |
|
10255 | 96 |
class MachProjNode; |
1 | 97 |
class MachReturnNode; |
98 |
class MachSafePointNode; |
|
99 |
class MachSpillCopyNode; |
|
100 |
class MachTempNode; |
|
28648
102bdbb42723
8068881: SIGBUS in C2 compiled method weblogic.wsee.jaxws.framework.jaxrpc.EnvironmentFactory$SimulatedWsdlDefinitions.<init>
iveresov
parents:
28643
diff
changeset
|
101 |
class MachMergeNode; |
1 | 102 |
class Matcher; |
103 |
class MemBarNode; |
|
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11196
diff
changeset
|
104 |
class MemBarStoreStoreNode; |
1 | 105 |
class MemNode; |
106 |
class MergeMemNode; |
|
13104
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
107 |
class MulNode; |
1 | 108 |
class MultiNode; |
109 |
class MultiBranchNode; |
|
110 |
class NeverBranchNode; |
|
111 |
class Node; |
|
112 |
class Node_Array; |
|
113 |
class Node_List; |
|
114 |
class Node_Stack; |
|
115 |
class NullCheckNode; |
|
116 |
class OopMap; |
|
206 | 117 |
class ParmNode; |
1 | 118 |
class PCTableNode; |
119 |
class PhaseCCP; |
|
120 |
class PhaseGVN; |
|
121 |
class PhaseIterGVN; |
|
122 |
class PhaseRegAlloc; |
|
123 |
class PhaseTransform; |
|
124 |
class PhaseValues; |
|
125 |
class PhiNode; |
|
126 |
class Pipeline; |
|
127 |
class ProjNode; |
|
128 |
class RegMask; |
|
129 |
class RegionNode; |
|
130 |
class RootNode; |
|
131 |
class SafePointNode; |
|
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
213
diff
changeset
|
132 |
class SafePointScalarObjectNode; |
1 | 133 |
class StartNode; |
134 |
class State; |
|
135 |
class StoreNode; |
|
136 |
class SubNode; |
|
137 |
class Type; |
|
138 |
class TypeNode; |
|
139 |
class UnlockNode; |
|
10255 | 140 |
class VectorNode; |
13104
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
141 |
class LoadVectorNode; |
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
142 |
class StoreVectorNode; |
1 | 143 |
class VectorSet; |
144 |
typedef void (*NFunc)(Node&,void*); |
|
145 |
extern "C" { |
|
146 |
typedef int (*C_sort_func_t)(const void *, const void *); |
|
147 |
} |
|
148 |
||
149 |
// The type of all node counts and indexes. |
|
150 |
// It must hold at least 16 bits, but must also be fast to load and store. |
|
151 |
// This type, if less than 32 bits, could limit the number of possible nodes. |
|
152 |
// (To make this type platform-specific, move to globalDefinitions_xxx.hpp.) |
|
153 |
typedef unsigned int node_idx_t; |
|
154 |
||
155 |
||
156 |
#ifndef OPTO_DU_ITERATOR_ASSERT |
|
157 |
#ifdef ASSERT |
|
158 |
#define OPTO_DU_ITERATOR_ASSERT 1 |
|
159 |
#else |
|
160 |
#define OPTO_DU_ITERATOR_ASSERT 0 |
|
161 |
#endif |
|
162 |
#endif //OPTO_DU_ITERATOR_ASSERT |
|
163 |
||
164 |
#if OPTO_DU_ITERATOR_ASSERT |
|
165 |
class DUIterator; |
|
166 |
class DUIterator_Fast; |
|
167 |
class DUIterator_Last; |
|
168 |
#else |
|
169 |
typedef uint DUIterator; |
|
170 |
typedef Node** DUIterator_Fast; |
|
171 |
typedef Node** DUIterator_Last; |
|
172 |
#endif |
|
173 |
||
174 |
// Node Sentinel |
|
175 |
#define NodeSentinel (Node*)-1 |
|
176 |
||
177 |
// Unknown count frequency |
|
178 |
#define COUNT_UNKNOWN (-1.0f) |
|
179 |
||
180 |
//------------------------------Node------------------------------------------- |
|
181 |
// Nodes define actions in the program. They create values, which have types. |
|
182 |
// They are both vertices in a directed graph and program primitives. Nodes |
|
183 |
// are labeled; the label is the "opcode", the primitive function in the lambda |
|
184 |
// calculus sense that gives meaning to the Node. Node inputs are ordered (so |
|
185 |
// that "a-b" is different from "b-a"). The inputs to a Node are the inputs to |
|
186 |
// the Node's function. These inputs also define a Type equation for the Node. |
|
187 |
// Solving these Type equations amounts to doing dataflow analysis. |
|
188 |
// Control and data are uniformly represented in the graph. Finally, Nodes |
|
189 |
// have a unique dense integer index which is used to index into side arrays |
|
190 |
// whenever I have phase-specific information. |
|
191 |
||
192 |
class Node { |
|
10547 | 193 |
friend class VMStructs; |
194 |
||
1 | 195 |
// Lots of restrictions on cloning Nodes |
196 |
Node(const Node&); // not defined; linker error to use these |
|
197 |
Node &operator=(const Node &rhs); |
|
198 |
||
199 |
public: |
|
200 |
friend class Compile; |
|
201 |
#if OPTO_DU_ITERATOR_ASSERT |
|
202 |
friend class DUIterator_Common; |
|
203 |
friend class DUIterator; |
|
204 |
friend class DUIterator_Fast; |
|
205 |
friend class DUIterator_Last; |
|
206 |
#endif |
|
207 |
||
208 |
// Because Nodes come and go, I define an Arena of Node structures to pull |
|
209 |
// from. This should allow fast access to node creation & deletion. This |
|
210 |
// field is a local cache of a value defined in some "program fragment" for |
|
211 |
// which these Nodes are just a part of. |
|
212 |
||
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
24425
diff
changeset
|
213 |
inline void* operator new(size_t x) throw() { |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
24425
diff
changeset
|
214 |
Compile* C = Compile::current(); |
1 | 215 |
Node* n = (Node*)C->node_arena()->Amalloc_D(x); |
216 |
#ifdef ASSERT |
|
217 |
n->_in = (Node**)n; // magic cookie for assertion check |
|
218 |
#endif |
|
219 |
return (void*)n; |
|
220 |
} |
|
221 |
||
222 |
// Delete is a NOP |
|
223 |
void operator delete( void *ptr ) {} |
|
224 |
// Fancy destructor; eagerly attempt to reclaim Node numberings and storage |
|
225 |
void destruct(); |
|
226 |
||
227 |
// Create a new Node. Required is the number is of inputs required for |
|
228 |
// semantic correctness. |
|
229 |
Node( uint required ); |
|
230 |
||
231 |
// Create a new Node with given input edges. |
|
232 |
// This version requires use of the "edge-count" new. |
|
233 |
// E.g. new (C,3) FooNode( C, NULL, left, right ); |
|
234 |
Node( Node *n0 ); |
|
235 |
Node( Node *n0, Node *n1 ); |
|
236 |
Node( Node *n0, Node *n1, Node *n2 ); |
|
237 |
Node( Node *n0, Node *n1, Node *n2, Node *n3 ); |
|
238 |
Node( Node *n0, Node *n1, Node *n2, Node *n3, Node *n4 ); |
|
239 |
Node( Node *n0, Node *n1, Node *n2, Node *n3, Node *n4, Node *n5 ); |
|
240 |
Node( Node *n0, Node *n1, Node *n2, Node *n3, |
|
241 |
Node *n4, Node *n5, Node *n6 ); |
|
242 |
||
243 |
// Clone an inherited Node given only the base Node type. |
|
244 |
Node* clone() const; |
|
245 |
||
246 |
// Clone a Node, immediately supplying one or two new edges. |
|
247 |
// The first and second arguments, if non-null, replace in(1) and in(2), |
|
248 |
// respectively. |
|
249 |
Node* clone_with_data_edge(Node* in1, Node* in2 = NULL) const { |
|
250 |
Node* nn = clone(); |
|
251 |
if (in1 != NULL) nn->set_req(1, in1); |
|
252 |
if (in2 != NULL) nn->set_req(2, in2); |
|
253 |
return nn; |
|
254 |
} |
|
255 |
||
256 |
private: |
|
257 |
// Shared setup for the above constructors. |
|
258 |
// Handles all interactions with Compile::current. |
|
259 |
// Puts initial values in all Node fields except _idx. |
|
260 |
// Returns the initial value for _idx, which cannot |
|
261 |
// be initialized by assignment. |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
24425
diff
changeset
|
262 |
inline int Init(int req); |
1 | 263 |
|
264 |
//----------------- input edge handling |
|
265 |
protected: |
|
266 |
friend class PhaseCFG; // Access to address of _in array elements |
|
267 |
Node **_in; // Array of use-def references to Nodes |
|
268 |
Node **_out; // Array of def-use references to Nodes |
|
269 |
||
2131 | 270 |
// Input edges are split into two categories. Required edges are required |
1 | 271 |
// for semantic correctness; order is important and NULLs are allowed. |
272 |
// Precedence edges are used to help determine execution order and are |
|
273 |
// added, e.g., for scheduling purposes. They are unordered and not |
|
274 |
// duplicated; they have no embedded NULLs. Edges from 0 to _cnt-1 |
|
275 |
// are required, from _cnt to _max-1 are precedence edges. |
|
276 |
node_idx_t _cnt; // Total number of required Node inputs. |
|
277 |
||
278 |
node_idx_t _max; // Actual length of input array. |
|
279 |
||
280 |
// Output edges are an unordered list of def-use edges which exactly |
|
281 |
// correspond to required input edges which point from other nodes |
|
282 |
// to this one. Thus the count of the output edges is the number of |
|
283 |
// users of this node. |
|
284 |
node_idx_t _outcnt; // Total number of Node outputs. |
|
285 |
||
286 |
node_idx_t _outmax; // Actual length of output array. |
|
287 |
||
288 |
// Grow the actual input array to the next larger power-of-2 bigger than len. |
|
289 |
void grow( uint len ); |
|
290 |
// Grow the output array to the next larger power-of-2 bigger than len. |
|
291 |
void out_grow( uint len ); |
|
292 |
||
293 |
public: |
|
294 |
// Each Node is assigned a unique small/dense number. This number is used |
|
295 |
// to index into auxiliary arrays of data and bitvectors. |
|
296 |
// It is declared const to defend against inadvertant assignment, |
|
297 |
// since it is used by clients as a naked field. |
|
298 |
const node_idx_t _idx; |
|
299 |
||
300 |
// Get the (read-only) number of input edges |
|
301 |
uint req() const { return _cnt; } |
|
302 |
uint len() const { return _max; } |
|
303 |
// Get the (read-only) number of output edges |
|
304 |
uint outcnt() const { return _outcnt; } |
|
305 |
||
306 |
#if OPTO_DU_ITERATOR_ASSERT |
|
307 |
// Iterate over the out-edges of this node. Deletions are illegal. |
|
308 |
inline DUIterator outs() const; |
|
309 |
// Use this when the out array might have changed to suppress asserts. |
|
310 |
inline DUIterator& refresh_out_pos(DUIterator& i) const; |
|
311 |
// Does the node have an out at this position? (Used for iteration.) |
|
312 |
inline bool has_out(DUIterator& i) const; |
|
313 |
inline Node* out(DUIterator& i) const; |
|
314 |
// Iterate over the out-edges of this node. All changes are illegal. |
|
315 |
inline DUIterator_Fast fast_outs(DUIterator_Fast& max) const; |
|
316 |
inline Node* fast_out(DUIterator_Fast& i) const; |
|
317 |
// Iterate over the out-edges of this node, deleting one at a time. |
|
318 |
inline DUIterator_Last last_outs(DUIterator_Last& min) const; |
|
319 |
inline Node* last_out(DUIterator_Last& i) const; |
|
320 |
// The inline bodies of all these methods are after the iterator definitions. |
|
321 |
#else |
|
322 |
// Iterate over the out-edges of this node. Deletions are illegal. |
|
323 |
// This iteration uses integral indexes, to decouple from array reallocations. |
|
324 |
DUIterator outs() const { return 0; } |
|
325 |
// Use this when the out array might have changed to suppress asserts. |
|
326 |
DUIterator refresh_out_pos(DUIterator i) const { return i; } |
|
327 |
||
328 |
// Reference to the i'th output Node. Error if out of bounds. |
|
329 |
Node* out(DUIterator i) const { assert(i < _outcnt, "oob"); return _out[i]; } |
|
330 |
// Does the node have an out at this position? (Used for iteration.) |
|
331 |
bool has_out(DUIterator i) const { return i < _outcnt; } |
|
332 |
||
333 |
// Iterate over the out-edges of this node. All changes are illegal. |
|
334 |
// This iteration uses a pointer internal to the out array. |
|
335 |
DUIterator_Fast fast_outs(DUIterator_Fast& max) const { |
|
336 |
Node** out = _out; |
|
337 |
// Assign a limit pointer to the reference argument: |
|
338 |
max = out + (ptrdiff_t)_outcnt; |
|
339 |
// Return the base pointer: |
|
340 |
return out; |
|
341 |
} |
|
342 |
Node* fast_out(DUIterator_Fast i) const { return *i; } |
|
343 |
// Iterate over the out-edges of this node, deleting one at a time. |
|
344 |
// This iteration uses a pointer internal to the out array. |
|
345 |
DUIterator_Last last_outs(DUIterator_Last& min) const { |
|
346 |
Node** out = _out; |
|
347 |
// Assign a limit pointer to the reference argument: |
|
348 |
min = out; |
|
349 |
// Return the pointer to the start of the iteration: |
|
350 |
return out + (ptrdiff_t)_outcnt - 1; |
|
351 |
} |
|
352 |
Node* last_out(DUIterator_Last i) const { return *i; } |
|
353 |
#endif |
|
354 |
||
355 |
// Reference to the i'th input Node. Error if out of bounds. |
|
13393
f0344cc50a90
7187454: stack overflow in C2 compiler thread on Solaris x86
kvn
parents:
13391
diff
changeset
|
356 |
Node* in(uint i) const { assert(i < _max, err_msg_res("oob: i=%d, _max=%d", i, _max)); return _in[i]; } |
22844
90f76a40ed8a
8003854: PPC64 (part 115): Introduce PostallocExpand that expands nodes after register allocation
goetz
parents:
21105
diff
changeset
|
357 |
// Reference to the i'th input Node. NULL if out of bounds. |
90f76a40ed8a
8003854: PPC64 (part 115): Introduce PostallocExpand that expands nodes after register allocation
goetz
parents:
21105
diff
changeset
|
358 |
Node* lookup(uint i) const { return ((i < _max) ? _in[i] : NULL); } |
1 | 359 |
// Reference to the i'th output Node. Error if out of bounds. |
360 |
// Use this accessor sparingly. We are going trying to use iterators instead. |
|
361 |
Node* raw_out(uint i) const { assert(i < _outcnt,"oob"); return _out[i]; } |
|
362 |
// Return the unique out edge. |
|
363 |
Node* unique_out() const { assert(_outcnt==1,"not unique"); return _out[0]; } |
|
364 |
// Delete out edge at position 'i' by moving last out edge to position 'i' |
|
365 |
void raw_del_out(uint i) { |
|
366 |
assert(i < _outcnt,"oob"); |
|
367 |
assert(_outcnt > 0,"oob"); |
|
368 |
#if OPTO_DU_ITERATOR_ASSERT |
|
369 |
// Record that a change happened here. |
|
370 |
debug_only(_last_del = _out[i]; ++_del_tick); |
|
371 |
#endif |
|
372 |
_out[i] = _out[--_outcnt]; |
|
373 |
// Smash the old edge so it can't be used accidentally. |
|
374 |
debug_only(_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef); |
|
375 |
} |
|
376 |
||
377 |
#ifdef ASSERT |
|
378 |
bool is_dead() const; |
|
379 |
#define is_not_dead(n) ((n) == NULL || !VerifyIterativeGVN || !((n)->is_dead())) |
|
380 |
#endif |
|
15618
3eb521896836
7197327: 40% regression on 8 b41 comp 8 b40 on specjvm2008.mpegaudio on oob
roland
parents:
15241
diff
changeset
|
381 |
// Check whether node has become unreachable |
3eb521896836
7197327: 40% regression on 8 b41 comp 8 b40 on specjvm2008.mpegaudio on oob
roland
parents:
15241
diff
changeset
|
382 |
bool is_unreachable(PhaseIterGVN &igvn) const; |
1 | 383 |
|
384 |
// Set a required input edge, also updates corresponding output edge |
|
385 |
void add_req( Node *n ); // Append a NEW required input |
|
22844
90f76a40ed8a
8003854: PPC64 (part 115): Introduce PostallocExpand that expands nodes after register allocation
goetz
parents:
21105
diff
changeset
|
386 |
void add_req( Node *n0, Node *n1 ) { |
90f76a40ed8a
8003854: PPC64 (part 115): Introduce PostallocExpand that expands nodes after register allocation
goetz
parents:
21105
diff
changeset
|
387 |
add_req(n0); add_req(n1); } |
90f76a40ed8a
8003854: PPC64 (part 115): Introduce PostallocExpand that expands nodes after register allocation
goetz
parents:
21105
diff
changeset
|
388 |
void add_req( Node *n0, Node *n1, Node *n2 ) { |
90f76a40ed8a
8003854: PPC64 (part 115): Introduce PostallocExpand that expands nodes after register allocation
goetz
parents:
21105
diff
changeset
|
389 |
add_req(n0); add_req(n1); add_req(n2); } |
1 | 390 |
void add_req_batch( Node* n, uint m ); // Append m NEW required inputs (all n). |
391 |
void del_req( uint idx ); // Delete required edge & compact |
|
19708
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
19279
diff
changeset
|
392 |
void del_req_ordered( uint idx ); // Delete required edge & compact with preserved order |
1 | 393 |
void ins_req( uint i, Node *n ); // Insert a NEW required input |
394 |
void set_req( uint i, Node *n ) { |
|
395 |
assert( is_not_dead(n), "can not use dead node"); |
|
13393
f0344cc50a90
7187454: stack overflow in C2 compiler thread on Solaris x86
kvn
parents:
13391
diff
changeset
|
396 |
assert( i < _cnt, err_msg_res("oob: i=%d, _cnt=%d", i, _cnt)); |
1 | 397 |
assert( !VerifyHashTableKeys || _hash_lock == 0, |
398 |
"remove node from hash table before modifying it"); |
|
399 |
Node** p = &_in[i]; // cache this._in, across the del_out call |
|
400 |
if (*p != NULL) (*p)->del_out((Node *)this); |
|
401 |
(*p) = n; |
|
402 |
if (n != NULL) n->add_out((Node *)this); |
|
25913
81dbc151e91c
8040213: C2 does not put all modified nodes on IGVN worklist
thartmann
parents:
24923
diff
changeset
|
403 |
Compile::current()->record_modified_node(this); |
1 | 404 |
} |
405 |
// Light version of set_req() to init inputs after node creation. |
|
406 |
void init_req( uint i, Node *n ) { |
|
407 |
assert( i == 0 && this == n || |
|
408 |
is_not_dead(n), "can not use dead node"); |
|
409 |
assert( i < _cnt, "oob"); |
|
410 |
assert( !VerifyHashTableKeys || _hash_lock == 0, |
|
411 |
"remove node from hash table before modifying it"); |
|
412 |
assert( _in[i] == NULL, "sanity"); |
|
413 |
_in[i] = n; |
|
414 |
if (n != NULL) n->add_out((Node *)this); |
|
25913
81dbc151e91c
8040213: C2 does not put all modified nodes on IGVN worklist
thartmann
parents:
24923
diff
changeset
|
415 |
Compile::current()->record_modified_node(this); |
1 | 416 |
} |
417 |
// Find first occurrence of n among my edges: |
|
418 |
int find_edge(Node* n); |
|
419 |
int replace_edge(Node* old, Node* neww); |
|
17383 | 420 |
int replace_edges_in_range(Node* old, Node* neww, int start, int end); |
1 | 421 |
// NULL out all inputs to eliminate incoming Def-Use edges. |
422 |
// Return the number of edges between 'n' and 'this' |
|
14623
70c4c1be0a14
7092905: C2: Keep track of the number of dead nodes
bharadwaj
parents:
13969
diff
changeset
|
423 |
int disconnect_inputs(Node *n, Compile *c); |
1 | 424 |
|
425 |
// Quickly, return true if and only if I am Compile::current()->top(). |
|
426 |
bool is_top() const { |
|
427 |
assert((this == (Node*) Compile::current()->top()) == (_out == NULL), ""); |
|
428 |
return (_out == NULL); |
|
429 |
} |
|
430 |
// Reaffirm invariants for is_top. (Only from Compile::set_cached_top_node.) |
|
431 |
void setup_is_top(); |
|
432 |
||
433 |
// Strip away casting. (It is depth-limited.) |
|
434 |
Node* uncast() const; |
|
11446 | 435 |
// Return whether two Nodes are equivalent, after stripping casting. |
436 |
bool eqv_uncast(const Node* n) const { |
|
437 |
return (this->uncast() == n->uncast()); |
|
438 |
} |
|
1 | 439 |
|
28643
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
440 |
// Find out of current node that matches opcode. |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
441 |
Node* find_out_with(int opcode); |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
442 |
// Return true if the current node has an out that matches opcode. |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
443 |
bool has_out_with(int opcode); |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
444 |
// Return true if the current node has an out that matches any of the opcodes. |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
445 |
bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4); |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
446 |
|
1 | 447 |
private: |
448 |
static Node* uncast_helper(const Node* n); |
|
449 |
||
450 |
// Add an output edge to the end of the list |
|
451 |
void add_out( Node *n ) { |
|
452 |
if (is_top()) return; |
|
453 |
if( _outcnt == _outmax ) out_grow(_outcnt); |
|
454 |
_out[_outcnt++] = n; |
|
455 |
} |
|
456 |
// Delete an output edge |
|
457 |
void del_out( Node *n ) { |
|
458 |
if (is_top()) return; |
|
459 |
Node** outp = &_out[_outcnt]; |
|
460 |
// Find and remove n |
|
461 |
do { |
|
462 |
assert(outp > _out, "Missing Def-Use edge"); |
|
463 |
} while (*--outp != n); |
|
464 |
*outp = _out[--_outcnt]; |
|
465 |
// Smash the old edge so it can't be used accidentally. |
|
466 |
debug_only(_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef); |
|
467 |
// Record that a change happened here. |
|
468 |
#if OPTO_DU_ITERATOR_ASSERT |
|
469 |
debug_only(_last_del = n; ++_del_tick); |
|
470 |
#endif |
|
471 |
} |
|
472 |
||
473 |
public: |
|
474 |
// Globally replace this node by a given new node, updating all uses. |
|
475 |
void replace_by(Node* new_node); |
|
594
9f4474e5dbaf
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
375
diff
changeset
|
476 |
// Globally replace this node by a given new node, updating all uses |
9f4474e5dbaf
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
375
diff
changeset
|
477 |
// and cutting input edges of old node. |
14623
70c4c1be0a14
7092905: C2: Keep track of the number of dead nodes
bharadwaj
parents:
13969
diff
changeset
|
478 |
void subsume_by(Node* new_node, Compile* c) { |
594
9f4474e5dbaf
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
375
diff
changeset
|
479 |
replace_by(new_node); |
14623
70c4c1be0a14
7092905: C2: Keep track of the number of dead nodes
bharadwaj
parents:
13969
diff
changeset
|
480 |
disconnect_inputs(NULL, c); |
594
9f4474e5dbaf
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
375
diff
changeset
|
481 |
} |
1 | 482 |
void set_req_X( uint i, Node *n, PhaseIterGVN *igvn ); |
483 |
// Find the one non-null required input. RegionNode only |
|
484 |
Node *nonnull_req() const; |
|
485 |
// Add or remove precedence edges |
|
486 |
void add_prec( Node *n ); |
|
487 |
void rm_prec( uint i ); |
|
488 |
void set_prec( uint i, Node *n ) { |
|
489 |
assert( is_not_dead(n), "can not use dead node"); |
|
490 |
assert( i >= _cnt, "not a precedence edge"); |
|
491 |
if (_in[i] != NULL) _in[i]->del_out((Node *)this); |
|
492 |
_in[i] = n; |
|
493 |
if (n != NULL) n->add_out((Node *)this); |
|
494 |
} |
|
495 |
// Set this node's index, used by cisc_version to replace current node |
|
496 |
void set_idx(uint new_idx) { |
|
497 |
const node_idx_t* ref = &_idx; |
|
498 |
*(node_idx_t*)ref = new_idx; |
|
499 |
} |
|
500 |
// Swap input edge order. (Edge indexes i1 and i2 are usually 1 and 2.) |
|
501 |
void swap_edges(uint i1, uint i2) { |
|
502 |
debug_only(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH); |
|
503 |
// Def-Use info is unchanged |
|
504 |
Node* n1 = in(i1); |
|
505 |
Node* n2 = in(i2); |
|
506 |
_in[i1] = n2; |
|
507 |
_in[i2] = n1; |
|
508 |
// If this node is in the hash table, make sure it doesn't need a rehash. |
|
509 |
assert(check_hash == NO_HASH || check_hash == hash(), "edge swap must preserve hash code"); |
|
510 |
} |
|
511 |
||
512 |
// Iterators over input Nodes for a Node X are written as: |
|
513 |
// for( i = 0; i < X.req(); i++ ) ... X[i] ... |
|
514 |
// NOTE: Required edges can contain embedded NULL pointers. |
|
515 |
||
516 |
//----------------- Other Node Properties |
|
517 |
||
28643
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
518 |
// Generate class IDs for (some) ideal nodes so that it is possible to determine |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
519 |
// the type of a node using a non-virtual method call (the method is_<Node>() below). |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
520 |
// |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
521 |
// A class ID of an ideal node is a set of bits. In a class ID, a single bit determines |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
522 |
// the type of the node the ID represents; another subset of an ID's bits are reserved |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
523 |
// for the superclasses of the node represented by the ID. |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
524 |
// |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
525 |
// By design, if A is a supertype of B, A.is_B() returns true and B.is_A() |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
526 |
// returns false. A.is_A() returns true. |
1 | 527 |
// |
28643
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
528 |
// If two classes, A and B, have the same superclass, a different bit of A's class id |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
529 |
// is reserved for A's type than for B's type. That bit is specified by the third |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
530 |
// parameter in the macro DEFINE_CLASS_ID. |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
531 |
// |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
532 |
// By convention, classes with deeper hierarchy are declared first. Moreover, |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
533 |
// classes with the same hierarchy depth are sorted by usage frequency. |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
534 |
// |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
535 |
// The query method masks the bits to cut off bits of subclasses and then compares |
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
26166
diff
changeset
|
536 |
// the result with the class id (see the macro DEFINE_CLASS_QUERY below). |
1 | 537 |
// |
538 |
// Class_MachCall=30, ClassMask_MachCall=31 |
|
539 |
// 12 8 4 0 |
|
540 |
// 0 0 0 0 0 0 0 0 1 1 1 1 0 |
|
541 |
// | | | | |
|
542 |
// | | | Bit_Mach=2 |
|
543 |
// | | Bit_MachReturn=4 |
|
544 |
// | Bit_MachSafePoint=8 |
|
545 |
// Bit_MachCall=16 |
|
546 |
// |
|
547 |
// Class_CountedLoop=56, ClassMask_CountedLoop=63 |
|
548 |
// 12 8 4 0 |
|
549 |
// 0 0 0 0 0 0 0 1 1 1 0 0 0 |
|
550 |
// | | | |
|
551 |
// | | Bit_Region=8 |
|
552 |
// | Bit_Loop=16 |
|
553 |
// Bit_CountedLoop=32 |
|
554 |
||
555 |
#define DEFINE_CLASS_ID(cl, supcl, subn) \ |
|
556 |
Bit_##cl = (Class_##supcl == 0) ? 1 << subn : (Bit_##supcl) << (1 + subn) , \ |
|
557 |
Class_##cl = Class_##supcl + Bit_##cl , \ |
|
558 |
ClassMask_##cl = ((Bit_##cl << 1) - 1) , |
|
559 |
||
560 |
// This enum is used only for C2 ideal and mach nodes with is_<node>() methods |
|
561 |
// so that it's values fits into 16 bits. |
|
562 |
enum NodeClasses { |
|
563 |
Bit_Node = 0x0000, |
|
564 |
Class_Node = 0x0000, |
|
565 |
ClassMask_Node = 0xFFFF, |
|
566 |
||
567 |
DEFINE_CLASS_ID(Multi, Node, 0) |
|
568 |
DEFINE_CLASS_ID(SafePoint, Multi, 0) |
|
569 |
DEFINE_CLASS_ID(Call, SafePoint, 0) |
|
570 |
DEFINE_CLASS_ID(CallJava, Call, 0) |
|
571 |
DEFINE_CLASS_ID(CallStaticJava, CallJava, 0) |
|
572 |
DEFINE_CLASS_ID(CallDynamicJava, CallJava, 1) |
|
573 |
DEFINE_CLASS_ID(CallRuntime, Call, 1) |
|
574 |
DEFINE_CLASS_ID(CallLeaf, CallRuntime, 0) |
|
575 |
DEFINE_CLASS_ID(Allocate, Call, 2) |
|
576 |
DEFINE_CLASS_ID(AllocateArray, Allocate, 0) |
|
577 |
DEFINE_CLASS_ID(AbstractLock, Call, 3) |
|
578 |
DEFINE_CLASS_ID(Lock, AbstractLock, 0) |
|
579 |
DEFINE_CLASS_ID(Unlock, AbstractLock, 1) |
|
26166 | 580 |
DEFINE_CLASS_ID(ArrayCopy, Call, 4) |
1 | 581 |
DEFINE_CLASS_ID(MultiBranch, Multi, 1) |
582 |
DEFINE_CLASS_ID(PCTable, MultiBranch, 0) |
|
583 |
DEFINE_CLASS_ID(Catch, PCTable, 0) |
|
584 |
DEFINE_CLASS_ID(Jump, PCTable, 1) |
|
585 |
DEFINE_CLASS_ID(If, MultiBranch, 1) |
|
586 |
DEFINE_CLASS_ID(CountedLoopEnd, If, 0) |
|
587 |
DEFINE_CLASS_ID(NeverBranch, MultiBranch, 2) |
|
588 |
DEFINE_CLASS_ID(Start, Multi, 2) |
|
589 |
DEFINE_CLASS_ID(MemBar, Multi, 3) |
|
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11196
diff
changeset
|
590 |
DEFINE_CLASS_ID(Initialize, MemBar, 0) |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11196
diff
changeset
|
591 |
DEFINE_CLASS_ID(MemBarStoreStore, MemBar, 1) |
1 | 592 |
|
593 |
DEFINE_CLASS_ID(Mach, Node, 1) |
|
594 |
DEFINE_CLASS_ID(MachReturn, Mach, 0) |
|
595 |
DEFINE_CLASS_ID(MachSafePoint, MachReturn, 0) |
|
596 |
DEFINE_CLASS_ID(MachCall, MachSafePoint, 0) |
|
597 |
DEFINE_CLASS_ID(MachCallJava, MachCall, 0) |
|
598 |
DEFINE_CLASS_ID(MachCallStaticJava, MachCallJava, 0) |
|
599 |
DEFINE_CLASS_ID(MachCallDynamicJava, MachCallJava, 1) |
|
600 |
DEFINE_CLASS_ID(MachCallRuntime, MachCall, 1) |
|
601 |
DEFINE_CLASS_ID(MachCallLeaf, MachCallRuntime, 0) |
|
10266
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
602 |
DEFINE_CLASS_ID(MachBranch, Mach, 1) |
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
603 |
DEFINE_CLASS_ID(MachIf, MachBranch, 0) |
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
604 |
DEFINE_CLASS_ID(MachGoto, MachBranch, 1) |
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
605 |
DEFINE_CLASS_ID(MachNullCheck, MachBranch, 2) |
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
606 |
DEFINE_CLASS_ID(MachSpillCopy, Mach, 2) |
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
607 |
DEFINE_CLASS_ID(MachTemp, Mach, 3) |
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
608 |
DEFINE_CLASS_ID(MachConstantBase, Mach, 4) |
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
609 |
DEFINE_CLASS_ID(MachConstant, Mach, 5) |
28648
102bdbb42723
8068881: SIGBUS in C2 compiled method weblogic.wsee.jaxws.framework.jaxrpc.EnvironmentFactory$SimulatedWsdlDefinitions.<init>
iveresov
parents:
28643
diff
changeset
|
610 |
DEFINE_CLASS_ID(MachMerge, Mach, 6) |
1 | 611 |
|
10255 | 612 |
DEFINE_CLASS_ID(Type, Node, 2) |
1 | 613 |
DEFINE_CLASS_ID(Phi, Type, 0) |
614 |
DEFINE_CLASS_ID(ConstraintCast, Type, 1) |
|
615 |
DEFINE_CLASS_ID(CheckCastPP, Type, 2) |
|
616 |
DEFINE_CLASS_ID(CMove, Type, 3) |
|
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
213
diff
changeset
|
617 |
DEFINE_CLASS_ID(SafePointScalarObject, Type, 4) |
13969
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
618 |
DEFINE_CLASS_ID(DecodeNarrowPtr, Type, 5) |
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
619 |
DEFINE_CLASS_ID(DecodeN, DecodeNarrowPtr, 0) |
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
620 |
DEFINE_CLASS_ID(DecodeNKlass, DecodeNarrowPtr, 1) |
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
621 |
DEFINE_CLASS_ID(EncodeNarrowPtr, Type, 6) |
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
622 |
DEFINE_CLASS_ID(EncodeP, EncodeNarrowPtr, 0) |
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
623 |
DEFINE_CLASS_ID(EncodePKlass, EncodeNarrowPtr, 1) |
1 | 624 |
|
10255 | 625 |
DEFINE_CLASS_ID(Proj, Node, 3) |
626 |
DEFINE_CLASS_ID(CatchProj, Proj, 0) |
|
627 |
DEFINE_CLASS_ID(JumpProj, Proj, 1) |
|
628 |
DEFINE_CLASS_ID(IfTrue, Proj, 2) |
|
629 |
DEFINE_CLASS_ID(IfFalse, Proj, 3) |
|
630 |
DEFINE_CLASS_ID(Parm, Proj, 4) |
|
631 |
DEFINE_CLASS_ID(MachProj, Proj, 5) |
|
632 |
||
633 |
DEFINE_CLASS_ID(Mem, Node, 4) |
|
1 | 634 |
DEFINE_CLASS_ID(Load, Mem, 0) |
13104
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
635 |
DEFINE_CLASS_ID(LoadVector, Load, 0) |
1 | 636 |
DEFINE_CLASS_ID(Store, Mem, 1) |
13104
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
637 |
DEFINE_CLASS_ID(StoreVector, Store, 0) |
1 | 638 |
DEFINE_CLASS_ID(LoadStore, Mem, 2) |
639 |
||
10255 | 640 |
DEFINE_CLASS_ID(Region, Node, 5) |
641 |
DEFINE_CLASS_ID(Loop, Region, 0) |
|
642 |
DEFINE_CLASS_ID(Root, Loop, 0) |
|
643 |
DEFINE_CLASS_ID(CountedLoop, Loop, 1) |
|
644 |
||
645 |
DEFINE_CLASS_ID(Sub, Node, 6) |
|
646 |
DEFINE_CLASS_ID(Cmp, Sub, 0) |
|
647 |
DEFINE_CLASS_ID(FastLock, Cmp, 0) |
|
648 |
DEFINE_CLASS_ID(FastUnlock, Cmp, 1) |
|
649 |
||
1 | 650 |
DEFINE_CLASS_ID(MergeMem, Node, 7) |
651 |
DEFINE_CLASS_ID(Bool, Node, 8) |
|
652 |
DEFINE_CLASS_ID(AddP, Node, 9) |
|
653 |
DEFINE_CLASS_ID(BoxLock, Node, 10) |
|
654 |
DEFINE_CLASS_ID(Add, Node, 11) |
|
13104
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
655 |
DEFINE_CLASS_ID(Mul, Node, 12) |
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
656 |
DEFINE_CLASS_ID(Vector, Node, 13) |
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
657 |
DEFINE_CLASS_ID(ClearArray, Node, 14) |
1 | 658 |
|
4470
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
659 |
_max_classes = ClassMask_ClearArray |
1 | 660 |
}; |
661 |
#undef DEFINE_CLASS_ID |
|
662 |
||
663 |
// Flags are sorted by usage frequency. |
|
664 |
enum NodeFlags { |
|
24008
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
665 |
Flag_is_Copy = 0x01, // should be first bit to avoid shift |
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
666 |
Flag_rematerialize = Flag_is_Copy << 1, |
1 | 667 |
Flag_needs_anti_dependence_check = Flag_rematerialize << 1, |
24008
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
668 |
Flag_is_macro = Flag_needs_anti_dependence_check << 1, |
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
669 |
Flag_is_Con = Flag_is_macro << 1, |
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
670 |
Flag_is_cisc_alternate = Flag_is_Con << 1, |
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
671 |
Flag_is_dead_loop_safe = Flag_is_cisc_alternate << 1, |
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
672 |
Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1, |
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
673 |
Flag_avoid_back_to_back_before = Flag_may_be_short_branch << 1, |
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
674 |
Flag_avoid_back_to_back_after = Flag_avoid_back_to_back_before << 1, |
da7059252295
8038297: Avoid placing CTI immediately following cbcond instruction on T4
iveresov
parents:
22911
diff
changeset
|
675 |
Flag_has_call = Flag_avoid_back_to_back_after << 1, |
30211 | 676 |
Flag_is_reduction = Flag_has_call << 1, |
33065 | 677 |
Flag_is_scheduled = Flag_is_reduction, |
678 |
Flag_is_expensive = Flag_is_scheduled << 1, |
|
15618
3eb521896836
7197327: 40% regression on 8 b41 comp 8 b40 on specjvm2008.mpegaudio on oob
roland
parents:
15241
diff
changeset
|
679 |
_max_flags = (Flag_is_expensive << 1) - 1 // allow flags combination |
1 | 680 |
}; |
681 |
||
682 |
private: |
|
683 |
jushort _class_id; |
|
684 |
jushort _flags; |
|
685 |
||
686 |
protected: |
|
687 |
// These methods should be called from constructors only. |
|
688 |
void init_class_id(jushort c) { |
|
689 |
assert(c <= _max_classes, "invalid node class"); |
|
690 |
_class_id = c; // cast out const |
|
691 |
} |
|
692 |
void init_flags(jushort fl) { |
|
693 |
assert(fl <= _max_flags, "invalid node flag"); |
|
694 |
_flags |= fl; |
|
695 |
} |
|
696 |
void clear_flag(jushort fl) { |
|
697 |
assert(fl <= _max_flags, "invalid node flag"); |
|
698 |
_flags &= ~fl; |
|
699 |
} |
|
700 |
||
701 |
public: |
|
702 |
const jushort class_id() const { return _class_id; } |
|
703 |
||
704 |
const jushort flags() const { return _flags; } |
|
705 |
||
30211 | 706 |
void add_flag(jushort fl) { init_flags(fl); } |
707 |
||
708 |
void remove_flag(jushort fl) { clear_flag(fl); } |
|
709 |
||
1 | 710 |
// Return a dense integer opcode number |
711 |
virtual int Opcode() const; |
|
712 |
||
713 |
// Virtual inherited Node size |
|
714 |
virtual uint size_of() const; |
|
715 |
||
716 |
// Other interesting Node properties |
|
4450
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
717 |
#define DEFINE_CLASS_QUERY(type) \ |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
718 |
bool is_##type() const { \ |
1 | 719 |
return ((_class_id & ClassMask_##type) == Class_##type); \ |
4450
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
720 |
} \ |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
721 |
type##Node *as_##type() const { \ |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
722 |
assert(is_##type(), "invalid node class"); \ |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
723 |
return (type##Node*)this; \ |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
724 |
} \ |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
725 |
type##Node* isa_##type() const { \ |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
726 |
return (is_##type()) ? as_##type() : NULL; \ |
1 | 727 |
} |
728 |
||
729 |
DEFINE_CLASS_QUERY(AbstractLock) |
|
730 |
DEFINE_CLASS_QUERY(Add) |
|
731 |
DEFINE_CLASS_QUERY(AddP) |
|
732 |
DEFINE_CLASS_QUERY(Allocate) |
|
733 |
DEFINE_CLASS_QUERY(AllocateArray) |
|
26166 | 734 |
DEFINE_CLASS_QUERY(ArrayCopy) |
1 | 735 |
DEFINE_CLASS_QUERY(Bool) |
736 |
DEFINE_CLASS_QUERY(BoxLock) |
|
10255 | 737 |
DEFINE_CLASS_QUERY(Call) |
1 | 738 |
DEFINE_CLASS_QUERY(CallDynamicJava) |
739 |
DEFINE_CLASS_QUERY(CallJava) |
|
740 |
DEFINE_CLASS_QUERY(CallLeaf) |
|
741 |
DEFINE_CLASS_QUERY(CallRuntime) |
|
742 |
DEFINE_CLASS_QUERY(CallStaticJava) |
|
743 |
DEFINE_CLASS_QUERY(Catch) |
|
744 |
DEFINE_CLASS_QUERY(CatchProj) |
|
745 |
DEFINE_CLASS_QUERY(CheckCastPP) |
|
746 |
DEFINE_CLASS_QUERY(ConstraintCast) |
|
4470
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
747 |
DEFINE_CLASS_QUERY(ClearArray) |
1 | 748 |
DEFINE_CLASS_QUERY(CMove) |
749 |
DEFINE_CLASS_QUERY(Cmp) |
|
750 |
DEFINE_CLASS_QUERY(CountedLoop) |
|
751 |
DEFINE_CLASS_QUERY(CountedLoopEnd) |
|
13969
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
752 |
DEFINE_CLASS_QUERY(DecodeNarrowPtr) |
594
9f4474e5dbaf
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
375
diff
changeset
|
753 |
DEFINE_CLASS_QUERY(DecodeN) |
13969
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
754 |
DEFINE_CLASS_QUERY(DecodeNKlass) |
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
755 |
DEFINE_CLASS_QUERY(EncodeNarrowPtr) |
594
9f4474e5dbaf
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
375
diff
changeset
|
756 |
DEFINE_CLASS_QUERY(EncodeP) |
13969
d2a189b83b87
7054512: Compress class pointers after perm gen removal
roland
parents:
13895
diff
changeset
|
757 |
DEFINE_CLASS_QUERY(EncodePKlass) |
1 | 758 |
DEFINE_CLASS_QUERY(FastLock) |
759 |
DEFINE_CLASS_QUERY(FastUnlock) |
|
760 |
DEFINE_CLASS_QUERY(If) |
|
761 |
DEFINE_CLASS_QUERY(IfFalse) |
|
762 |
DEFINE_CLASS_QUERY(IfTrue) |
|
763 |
DEFINE_CLASS_QUERY(Initialize) |
|
764 |
DEFINE_CLASS_QUERY(Jump) |
|
765 |
DEFINE_CLASS_QUERY(JumpProj) |
|
766 |
DEFINE_CLASS_QUERY(Load) |
|
767 |
DEFINE_CLASS_QUERY(LoadStore) |
|
768 |
DEFINE_CLASS_QUERY(Lock) |
|
769 |
DEFINE_CLASS_QUERY(Loop) |
|
770 |
DEFINE_CLASS_QUERY(Mach) |
|
10266
2ea344c79e33
7079317: Incorrect branch's destination block in PrintoOptoAssembly output
kvn
parents:
10264
diff
changeset
|
771 |
DEFINE_CLASS_QUERY(MachBranch) |
1 | 772 |
DEFINE_CLASS_QUERY(MachCall) |
773 |
DEFINE_CLASS_QUERY(MachCallDynamicJava) |
|
774 |
DEFINE_CLASS_QUERY(MachCallJava) |
|
775 |
DEFINE_CLASS_QUERY(MachCallLeaf) |
|
776 |
DEFINE_CLASS_QUERY(MachCallRuntime) |
|
777 |
DEFINE_CLASS_QUERY(MachCallStaticJava) |
|
7433 | 778 |
DEFINE_CLASS_QUERY(MachConstantBase) |
779 |
DEFINE_CLASS_QUERY(MachConstant) |
|
10255 | 780 |
DEFINE_CLASS_QUERY(MachGoto) |
1 | 781 |
DEFINE_CLASS_QUERY(MachIf) |
782 |
DEFINE_CLASS_QUERY(MachNullCheck) |
|
10255 | 783 |
DEFINE_CLASS_QUERY(MachProj) |
1 | 784 |
DEFINE_CLASS_QUERY(MachReturn) |
785 |
DEFINE_CLASS_QUERY(MachSafePoint) |
|
786 |
DEFINE_CLASS_QUERY(MachSpillCopy) |
|
787 |
DEFINE_CLASS_QUERY(MachTemp) |
|
28648
102bdbb42723
8068881: SIGBUS in C2 compiled method weblogic.wsee.jaxws.framework.jaxrpc.EnvironmentFactory$SimulatedWsdlDefinitions.<init>
iveresov
parents:
28643
diff
changeset
|
788 |
DEFINE_CLASS_QUERY(MachMerge) |
1 | 789 |
DEFINE_CLASS_QUERY(Mem) |
790 |
DEFINE_CLASS_QUERY(MemBar) |
|
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11196
diff
changeset
|
791 |
DEFINE_CLASS_QUERY(MemBarStoreStore) |
1 | 792 |
DEFINE_CLASS_QUERY(MergeMem) |
13104
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
793 |
DEFINE_CLASS_QUERY(Mul) |
1 | 794 |
DEFINE_CLASS_QUERY(Multi) |
795 |
DEFINE_CLASS_QUERY(MultiBranch) |
|
206 | 796 |
DEFINE_CLASS_QUERY(Parm) |
1 | 797 |
DEFINE_CLASS_QUERY(PCTable) |
798 |
DEFINE_CLASS_QUERY(Phi) |
|
799 |
DEFINE_CLASS_QUERY(Proj) |
|
800 |
DEFINE_CLASS_QUERY(Region) |
|
801 |
DEFINE_CLASS_QUERY(Root) |
|
802 |
DEFINE_CLASS_QUERY(SafePoint) |
|
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
213
diff
changeset
|
803 |
DEFINE_CLASS_QUERY(SafePointScalarObject) |
1 | 804 |
DEFINE_CLASS_QUERY(Start) |
805 |
DEFINE_CLASS_QUERY(Store) |
|
806 |
DEFINE_CLASS_QUERY(Sub) |
|
807 |
DEFINE_CLASS_QUERY(Type) |
|
10255 | 808 |
DEFINE_CLASS_QUERY(Vector) |
13104
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
809 |
DEFINE_CLASS_QUERY(LoadVector) |
657b387034fb
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
11446
diff
changeset
|
810 |
DEFINE_CLASS_QUERY(StoreVector) |
1 | 811 |
DEFINE_CLASS_QUERY(Unlock) |
812 |
||
813 |
#undef DEFINE_CLASS_QUERY |
|
814 |
||
815 |
// duplicate of is_MachSpillCopy() |
|
816 |
bool is_SpillCopy () const { |
|
817 |
return ((_class_id & ClassMask_MachSpillCopy) == Class_MachSpillCopy); |
|
818 |
} |
|
819 |
||
820 |
bool is_Con () const { return (_flags & Flag_is_Con) != 0; } |
|
821 |
// The data node which is safe to leave in dead loop during IGVN optimization. |
|
822 |
bool is_dead_loop_safe() const { |
|
373
427fb4ca6a1e
6625997: CastPP, CheckCastPP and Proj nodes are not dead loop safe
kvn
parents:
366
diff
changeset
|
823 |
return is_Phi() || (is_Proj() && in(0) == NULL) || |
427fb4ca6a1e
6625997: CastPP, CheckCastPP and Proj nodes are not dead loop safe
kvn
parents:
366
diff
changeset
|
824 |
((_flags & (Flag_is_dead_loop_safe | Flag_is_Con)) != 0 && |
427fb4ca6a1e
6625997: CastPP, CheckCastPP and Proj nodes are not dead loop safe
kvn
parents:
366
diff
changeset
|
825 |
(!is_Proj() || !in(0)->is_Allocate())); |
1 | 826 |
} |
827 |
||
828 |
// is_Copy() returns copied edge index (0 or 1) |
|
829 |
uint is_Copy() const { return (_flags & Flag_is_Copy); } |
|
830 |
||
831 |
virtual bool is_CFG() const { return false; } |
|
832 |
||
833 |
// If this node is control-dependent on a test, can it be |
|
834 |
// rerouted to a dominating equivalent test? This is usually |
|
835 |
// true of non-CFG nodes, but can be false for operations which |
|
836 |
// depend for their correct sequencing on more than one test. |
|
837 |
// (In that case, hoisting to a dominating test may silently |
|
838 |
// skip some other important test.) |
|
839 |
virtual bool depends_only_on_test() const { assert(!is_CFG(), ""); return true; }; |
|
840 |
||
841 |
// When building basic blocks, I need to have a notion of block beginning |
|
842 |
// Nodes, next block selector Nodes (block enders), and next block |
|
843 |
// projections. These calls need to work on their machine equivalents. The |
|
844 |
// Ideal beginning Nodes are RootNode, RegionNode and StartNode. |
|
845 |
bool is_block_start() const { |
|
846 |
if ( is_Region() ) |
|
847 |
return this == (const Node*)in(0); |
|
848 |
else |
|
10255 | 849 |
return is_Start(); |
1 | 850 |
} |
851 |
||
852 |
// The Ideal control projection Nodes are IfTrue/IfFalse, JumpProjNode, Root, |
|
853 |
// Goto and Return. This call also returns the block ending Node. |
|
854 |
virtual const Node *is_block_proj() const; |
|
855 |
||
856 |
// The node is a "macro" node which needs to be expanded before matching |
|
857 |
bool is_macro() const { return (_flags & Flag_is_macro) != 0; } |
|
15618
3eb521896836
7197327: 40% regression on 8 b41 comp 8 b40 on specjvm2008.mpegaudio on oob
roland
parents:
15241
diff
changeset
|
858 |
// The node is expensive: the best control is set during loop opts |
3eb521896836
7197327: 40% regression on 8 b41 comp 8 b40 on specjvm2008.mpegaudio on oob
roland
parents:
15241
diff
changeset
|
859 |
bool is_expensive() const { return (_flags & Flag_is_expensive) != 0 && in(0) != NULL; } |
1 | 860 |
|
30211 | 861 |
// An arithmetic node which accumulates a data in a loop. |
862 |
// It must have the loop's phi as input and provide a def to the phi. |
|
863 |
bool is_reduction() const { return (_flags & Flag_is_reduction) != 0; } |
|
864 |
||
33065 | 865 |
// Used in lcm to mark nodes that have scheduled |
866 |
bool is_scheduled() const { return (_flags & Flag_is_scheduled) != 0; } |
|
867 |
||
1 | 868 |
//----------------- Optimization |
869 |
||
870 |
// Get the worst-case Type output for this Node. |
|
871 |
virtual const class Type *bottom_type() const; |
|
872 |
||
873 |
// If we find a better type for a node, try to record it permanently. |
|
874 |
// Return true if this node actually changed. |
|
875 |
// Be sure to do the hash_delete game in the "rehash" variant. |
|
876 |
void raise_bottom_type(const Type* new_type); |
|
877 |
||
878 |
// Get the address type with which this node uses and/or defs memory, |
|
879 |
// or NULL if none. The address type is conservatively wide. |
|
880 |
// Returns non-null for calls, membars, loads, stores, etc. |
|
881 |
// Returns TypePtr::BOTTOM if the node touches memory "broadly". |
|
882 |
virtual const class TypePtr *adr_type() const { return NULL; } |
|
883 |
||
884 |
// Return an existing node which computes the same function as this node. |
|
885 |
// The optimistic combined algorithm requires this to return a Node which |
|
886 |
// is a small number of steps away (e.g., one of my inputs). |
|
887 |
virtual Node *Identity( PhaseTransform *phase ); |
|
888 |
||
889 |
// Return the set of values this Node can take on at runtime. |
|
890 |
virtual const Type *Value( PhaseTransform *phase ) const; |
|
891 |
||
892 |
// Return a node which is more "ideal" than the current node. |
|
893 |
// The invariants on this call are subtle. If in doubt, read the |
|
894 |
// treatise in node.cpp above the default implemention AND TEST WITH |
|
895 |
// +VerifyIterativeGVN! |
|
896 |
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
|
897 |
||
898 |
// Some nodes have specific Ideal subgraph transformations only if they are |
|
899 |
// unique users of specific nodes. Such nodes should be put on IGVN worklist |
|
900 |
// for the transformations to happen. |
|
901 |
bool has_special_unique_user() const; |
|
902 |
||
366
449c27706bac
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
360
diff
changeset
|
903 |
// Skip Proj and CatchProj nodes chains. Check for Null and Top. |
449c27706bac
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
360
diff
changeset
|
904 |
Node* find_exact_control(Node* ctrl); |
449c27706bac
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
360
diff
changeset
|
905 |
|
449c27706bac
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
360
diff
changeset
|
906 |
// Check if 'this' node dominates or equal to 'sub'. |
449c27706bac
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
360
diff
changeset
|
907 |
bool dominates(Node* sub, Node_List &nlist); |
449c27706bac
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
360
diff
changeset
|
908 |
|
1 | 909 |
protected: |
910 |
bool remove_dead_region(PhaseGVN *phase, bool can_reshape); |
|
911 |
public: |
|
912 |
||
913 |
// See if there is valid pipeline info |
|
914 |
static const Pipeline *pipeline_class(); |
|
915 |
virtual const Pipeline *pipeline() const; |
|
916 |
||
917 |
// Compute the latency from the def to this instruction of the ith input node |
|
918 |
uint latency(uint i); |
|
919 |
||
920 |
// Hash & compare functions, for pessimistic value numbering |
|
921 |
||
922 |
// If the hash function returns the special sentinel value NO_HASH, |
|
923 |
// the node is guaranteed never to compare equal to any other node. |
|
2131 | 924 |
// If we accidentally generate a hash with value NO_HASH the node |
1 | 925 |
// won't go into the table and we'll lose a little optimization. |
926 |
enum { NO_HASH = 0 }; |
|
927 |
virtual uint hash() const; |
|
928 |
virtual uint cmp( const Node &n ) const; |
|
929 |
||
930 |
// Operation appears to be iteratively computed (such as an induction variable) |
|
931 |
// It is possible for this operation to return false for a loop-varying |
|
932 |
// value, if it appears (by local graph inspection) to be computed by a simple conditional. |
|
933 |
bool is_iteratively_computed(); |
|
934 |
||
935 |
// Determine if a node is Counted loop induction variable. |
|
936 |
// The method is defined in loopnode.cpp. |
|
937 |
const Node* is_loop_iv() const; |
|
938 |
||
939 |
// Return a node with opcode "opc" and same inputs as "this" if one can |
|
940 |
// be found; Otherwise return NULL; |
|
941 |
Node* find_similar(int opc); |
|
942 |
||
943 |
// Return the unique control out if only one. Null if none or more than one. |
|
30183 | 944 |
Node* unique_ctrl_out() const; |
1 | 945 |
|
30300
4b12a5b40064
8069191: moving predicate out of loops may cause array accesses to bypass null check
roland
parents:
30211
diff
changeset
|
946 |
// Set control or add control as precedence edge |
4b12a5b40064
8069191: moving predicate out of loops may cause array accesses to bypass null check
roland
parents:
30211
diff
changeset
|
947 |
void ensure_control_or_add_prec(Node* c); |
4b12a5b40064
8069191: moving predicate out of loops may cause array accesses to bypass null check
roland
parents:
30211
diff
changeset
|
948 |
|
1 | 949 |
//----------------- Code Generation |
950 |
||
951 |
// Ideal register class for Matching. Zero means unmatched instruction |
|
952 |
// (these are cloned instead of converted to machine nodes). |
|
953 |
virtual uint ideal_reg() const; |
|
954 |
||
955 |
static const uint NotAMachineReg; // must be > max. machine register |
|
956 |
||
957 |
// Do we Match on this edge index or not? Generally false for Control |
|
958 |
// and true for everything else. Weird for calls & returns. |
|
959 |
virtual uint match_edge(uint idx) const; |
|
960 |
||
961 |
// Register class output is returned in |
|
962 |
virtual const RegMask &out_RegMask() const; |
|
963 |
// Register class input is expected in |
|
964 |
virtual const RegMask &in_RegMask(uint) const; |
|
965 |
// Should we clone rather than spill this instruction? |
|
966 |
bool rematerialize() const; |
|
967 |
||
968 |
// Return JVM State Object if this Node carries debug info, or NULL otherwise |
|
969 |
virtual JVMState* jvms() const; |
|
970 |
||
971 |
// Print as assembly |
|
972 |
virtual void format( PhaseRegAlloc *, outputStream* st = tty ) const; |
|
973 |
// Emit bytes starting at parameter 'ptr' |
|
974 |
// Bump 'ptr' by the number of output bytes |
|
975 |
virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; |
|
976 |
// Size of instruction in bytes |
|
977 |
virtual uint size(PhaseRegAlloc *ra_) const; |
|
978 |
||
979 |
// Convenience function to extract an integer constant from a node. |
|
980 |
// If it is not an integer constant (either Con, CastII, or Mach), |
|
981 |
// return value_if_unknown. |
|
982 |
jint find_int_con(jint value_if_unknown) const { |
|
983 |
const TypeInt* t = find_int_type(); |
|
984 |
return (t != NULL && t->is_con()) ? t->get_con() : value_if_unknown; |
|
985 |
} |
|
986 |
// Return the constant, knowing it is an integer constant already |
|
987 |
jint get_int() const { |
|
988 |
const TypeInt* t = find_int_type(); |
|
989 |
guarantee(t != NULL, "must be con"); |
|
990 |
return t->get_con(); |
|
991 |
} |
|
992 |
// Here's where the work is done. Can produce non-constant int types too. |
|
993 |
const TypeInt* find_int_type() const; |
|
994 |
||
995 |
// Same thing for long (and intptr_t, via type.hpp): |
|
996 |
jlong get_long() const { |
|
997 |
const TypeLong* t = find_long_type(); |
|
998 |
guarantee(t != NULL, "must be con"); |
|
999 |
return t->get_con(); |
|
1000 |
} |
|
1001 |
jlong find_long_con(jint value_if_unknown) const { |
|
1002 |
const TypeLong* t = find_long_type(); |
|
1003 |
return (t != NULL && t->is_con()) ? t->get_con() : value_if_unknown; |
|
1004 |
} |
|
1005 |
const TypeLong* find_long_type() const; |
|
1006 |
||
17384
4e6ea5fa04ad
8014189: JVM crash with SEGV in ConnectionGraph::record_for_escape_analysis()
kvn
parents:
17383
diff
changeset
|
1007 |
const TypePtr* get_ptr_type() const; |
4e6ea5fa04ad
8014189: JVM crash with SEGV in ConnectionGraph::record_for_escape_analysis()
kvn
parents:
17383
diff
changeset
|
1008 |
|
1 | 1009 |
// These guys are called by code generated by ADLC: |
1010 |
intptr_t get_ptr() const; |
|
360
21d113ecbf6a
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
238
diff
changeset
|
1011 |
intptr_t get_narrowcon() const; |
1 | 1012 |
jdouble getd() const; |
1013 |
jfloat getf() const; |
|
1014 |
||
1015 |
// Nodes which are pinned into basic blocks |
|
1016 |
virtual bool pinned() const { return false; } |
|
1017 |
||
1018 |
// Nodes which use memory without consuming it, hence need antidependences |
|
1019 |
// More specifically, needs_anti_dependence_check returns true iff the node |
|
1020 |
// (a) does a load, and (b) does not perform a store (except perhaps to a |
|
1021 |
// stack slot or some other unaliased location). |
|
1022 |
bool needs_anti_dependence_check() const; |
|
1023 |
||
1024 |
// Return which operand this instruction may cisc-spill. In other words, |
|
1025 |
// return operand position that can convert from reg to memory access |
|
1026 |
virtual int cisc_operand() const { return AdlcVMDeps::Not_cisc_spillable; } |
|
1027 |
bool is_cisc_alternate() const { return (_flags & Flag_is_cisc_alternate) != 0; } |
|
1028 |
||
1029 |
//----------------- Graph walking |
|
1030 |
public: |
|
1031 |
// Walk and apply member functions recursively. |
|
1032 |
// Supplied (this) pointer is root. |
|
1033 |
void walk(NFunc pre, NFunc post, void *env); |
|
1034 |
static void nop(Node &, void*); // Dummy empty function |
|
1035 |
static void packregion( Node &n, void* ); |
|
1036 |
private: |
|
1037 |
void walk_(NFunc pre, NFunc post, void *env, VectorSet &visited); |
|
1038 |
||
1039 |
//----------------- Printing, etc |
|
1040 |
public: |
|
1041 |
#ifndef PRODUCT |
|
1042 |
Node* find(int idx) const; // Search the graph for the given idx. |
|
1043 |
Node* find_ctrl(int idx) const; // Search control ancestors for the given idx. |
|
15241
87d217c2d183
8005055: pass outputStream to more opto debug routines
kvn
parents:
14623
diff
changeset
|
1044 |
void dump() const { dump("\n"); } // Print this node. |
32084
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1045 |
void dump(const char* suffix, bool mark = false, outputStream *st = tty) const; // Print this node. |
1 | 1046 |
void dump(int depth) const; // Print this node, recursively to depth d |
1047 |
void dump_ctrl(int depth) const; // Print control nodes, to depth d |
|
32084
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1048 |
void dump_comp() const; // Print this node in compact representation. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1049 |
// Print this node in compact representation. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1050 |
void dump_comp(const char* suffix, outputStream *st = tty) const; |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1051 |
virtual void dump_req(outputStream *st = tty) const; // Print required-edge info |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1052 |
virtual void dump_prec(outputStream *st = tty) const; // Print precedence-edge info |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1053 |
virtual void dump_out(outputStream *st = tty) const; // Print the output edge info |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1054 |
virtual void dump_spec(outputStream *st) const {}; // Print per-node info |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1055 |
// Print compact per-node info |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1056 |
virtual void dump_compact_spec(outputStream *st) const { dump_spec(st); } |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1057 |
void dump_related() const; // Print related nodes (depends on node at hand). |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1058 |
// Print related nodes up to given depths for input and output nodes. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1059 |
void dump_related(uint d_in, uint d_out) const; |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1060 |
void dump_related_compact() const; // Print related nodes in compact representation. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1061 |
// Collect related nodes. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1062 |
virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const; |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1063 |
// Collect nodes starting from this node, explicitly including/excluding control and data links. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1064 |
void collect_nodes(GrowableArray<Node*> *ns, int d, bool ctrl, bool data) const; |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1065 |
|
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1066 |
// Node collectors, to be used in implementations of Node::rel(). |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1067 |
// Collect the entire data input graph. Include control inputs if requested. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1068 |
void collect_nodes_in_all_data(GrowableArray<Node*> *ns, bool ctrl) const; |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1069 |
// Collect the entire control input graph. Include data inputs if requested. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1070 |
void collect_nodes_in_all_ctrl(GrowableArray<Node*> *ns, bool data) const; |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1071 |
// Collect the entire output graph until hitting and including control nodes. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1072 |
void collect_nodes_out_all_ctrl_boundary(GrowableArray<Node*> *ns) const; |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1073 |
|
1 | 1074 |
void verify_edges(Unique_Node_List &visited); // Verify bi-directional edges |
1075 |
void verify() const; // Check Def-Use info for my subgraph |
|
1076 |
static void verify_recur(const Node *n, int verify_depth, VectorSet &old_space, VectorSet &new_space); |
|
1077 |
||
1078 |
// This call defines a class-unique string used to identify class instances |
|
1079 |
virtual const char *Name() const; |
|
1080 |
||
1081 |
void dump_format(PhaseRegAlloc *ra) const; // debug access to MachNode::format(...) |
|
1082 |
// RegMask Print Functions |
|
1083 |
void dump_in_regmask(int idx) { in_RegMask(idx).dump(); } |
|
1084 |
void dump_out_regmask() { out_RegMask().dump(); } |
|
22854
2787e48d6df9
8029025: PPC64 (part 203): opto: Move static _in_dump_cnt to Compile object.
goetz
parents:
22844
diff
changeset
|
1085 |
static bool in_dump() { return Compile::current()->_in_dump_cnt > 0; } |
1 | 1086 |
void fast_dump() const { |
1087 |
tty->print("%4d: %-17s", _idx, Name()); |
|
1088 |
for (uint i = 0; i < len(); i++) |
|
1089 |
if (in(i)) |
|
1090 |
tty->print(" %4d", in(i)->_idx); |
|
1091 |
else |
|
1092 |
tty->print(" NULL"); |
|
1093 |
tty->print("\n"); |
|
1094 |
} |
|
1095 |
#endif |
|
1096 |
#ifdef ASSERT |
|
1097 |
void verify_construction(); |
|
1098 |
bool verify_jvms(const JVMState* jvms) const; |
|
1099 |
int _debug_idx; // Unique value assigned to every node. |
|
1100 |
int debug_idx() const { return _debug_idx; } |
|
1101 |
void set_debug_idx( int debug_idx ) { _debug_idx = debug_idx; } |
|
1102 |
||
1103 |
Node* _debug_orig; // Original version of this, if any. |
|
1104 |
Node* debug_orig() const { return _debug_orig; } |
|
1105 |
void set_debug_orig(Node* orig); // _debug_orig = orig |
|
1106 |
||
1107 |
int _hash_lock; // Barrier to modifications of nodes in the hash table |
|
1108 |
void enter_hash_lock() { ++_hash_lock; assert(_hash_lock < 99, "in too many hash tables?"); } |
|
1109 |
void exit_hash_lock() { --_hash_lock; assert(_hash_lock >= 0, "mispaired hash locks"); } |
|
1110 |
||
1111 |
static void init_NodeProperty(); |
|
1112 |
||
1113 |
#if OPTO_DU_ITERATOR_ASSERT |
|
1114 |
const Node* _last_del; // The last deleted node. |
|
1115 |
uint _del_tick; // Bumped when a deletion happens.. |
|
1116 |
#endif |
|
1117 |
#endif |
|
1118 |
}; |
|
1119 |
||
32084
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1120 |
|
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1121 |
#ifndef PRODUCT |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1122 |
|
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1123 |
// Used in debugging code to avoid walking across dead or uninitialized edges. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1124 |
inline bool NotANode(const Node* n) { |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1125 |
if (n == NULL) return true; |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1126 |
if (((intptr_t)n & 1) != 0) return true; // uninitialized, etc. |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1127 |
if (*(address*)n == badAddress) return true; // kill by Node::destruct |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1128 |
return false; |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1129 |
} |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1130 |
|
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1131 |
#endif |
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1132 |
|
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1133 |
|
1 | 1134 |
//----------------------------------------------------------------------------- |
1135 |
// Iterators over DU info, and associated Node functions. |
|
1136 |
||
1137 |
#if OPTO_DU_ITERATOR_ASSERT |
|
1138 |
||
1139 |
// Common code for assertion checking on DU iterators. |
|
1140 |
class DUIterator_Common VALUE_OBJ_CLASS_SPEC { |
|
1141 |
#ifdef ASSERT |
|
1142 |
protected: |
|
1143 |
bool _vdui; // cached value of VerifyDUIterators |
|
1144 |
const Node* _node; // the node containing the _out array |
|
1145 |
uint _outcnt; // cached node->_outcnt |
|
1146 |
uint _del_tick; // cached node->_del_tick |
|
1147 |
Node* _last; // last value produced by the iterator |
|
1148 |
||
1149 |
void sample(const Node* node); // used by c'tor to set up for verifies |
|
1150 |
void verify(const Node* node, bool at_end_ok = false); |
|
1151 |
void verify_resync(); |
|
1152 |
void reset(const DUIterator_Common& that); |
|
1153 |
||
1154 |
// The VDUI_ONLY macro protects code conditionalized on VerifyDUIterators |
|
1155 |
#define I_VDUI_ONLY(i,x) { if ((i)._vdui) { x; } } |
|
1156 |
#else |
|
1157 |
#define I_VDUI_ONLY(i,x) { } |
|
1158 |
#endif //ASSERT |
|
1159 |
}; |
|
1160 |
||
1161 |
#define VDUI_ONLY(x) I_VDUI_ONLY(*this, x) |
|
1162 |
||
1163 |
// Default DU iterator. Allows appends onto the out array. |
|
1164 |
// Allows deletion from the out array only at the current point. |
|
1165 |
// Usage: |
|
1166 |
// for (DUIterator i = x->outs(); x->has_out(i); i++) { |
|
1167 |
// Node* y = x->out(i); |
|
1168 |
// ... |
|
1169 |
// } |
|
1170 |
// Compiles in product mode to a unsigned integer index, which indexes |
|
1171 |
// onto a repeatedly reloaded base pointer of x->_out. The loop predicate |
|
1172 |
// also reloads x->_outcnt. If you delete, you must perform "--i" just |
|
1173 |
// before continuing the loop. You must delete only the last-produced |
|
1174 |
// edge. You must delete only a single copy of the last-produced edge, |
|
1175 |
// or else you must delete all copies at once (the first time the edge |
|
1176 |
// is produced by the iterator). |
|
1177 |
class DUIterator : public DUIterator_Common { |
|
1178 |
friend class Node; |
|
1179 |
||
1180 |
// This is the index which provides the product-mode behavior. |
|
1181 |
// Whatever the product-mode version of the system does to the |
|
1182 |
// DUI index is done to this index. All other fields in |
|
1183 |
// this class are used only for assertion checking. |
|
1184 |
uint _idx; |
|
1185 |
||
1186 |
#ifdef ASSERT |
|
1187 |
uint _refresh_tick; // Records the refresh activity. |
|
1188 |
||
1189 |
void sample(const Node* node); // Initialize _refresh_tick etc. |
|
1190 |
void verify(const Node* node, bool at_end_ok = false); |
|
1191 |
void verify_increment(); // Verify an increment operation. |
|
1192 |
void verify_resync(); // Verify that we can back up over a deletion. |
|
1193 |
void verify_finish(); // Verify that the loop terminated properly. |
|
1194 |
void refresh(); // Resample verification info. |
|
1195 |
void reset(const DUIterator& that); // Resample after assignment. |
|
1196 |
#endif |
|
1197 |
||
1198 |
DUIterator(const Node* node, int dummy_to_avoid_conversion) |
|
1199 |
{ _idx = 0; debug_only(sample(node)); } |
|
1200 |
||
1201 |
public: |
|
1202 |
// initialize to garbage; clear _vdui to disable asserts |
|
1203 |
DUIterator() |
|
1204 |
{ /*initialize to garbage*/ debug_only(_vdui = false); } |
|
1205 |
||
1206 |
void operator++(int dummy_to_specify_postfix_op) |
|
1207 |
{ _idx++; VDUI_ONLY(verify_increment()); } |
|
1208 |
||
1209 |
void operator--() |
|
1210 |
{ VDUI_ONLY(verify_resync()); --_idx; } |
|
1211 |
||
1212 |
~DUIterator() |
|
1213 |
{ VDUI_ONLY(verify_finish()); } |
|
1214 |
||
1215 |
void operator=(const DUIterator& that) |
|
1216 |
{ _idx = that._idx; debug_only(reset(that)); } |
|
1217 |
}; |
|
1218 |
||
1219 |
DUIterator Node::outs() const |
|
1220 |
{ return DUIterator(this, 0); } |
|
1221 |
DUIterator& Node::refresh_out_pos(DUIterator& i) const |
|
1222 |
{ I_VDUI_ONLY(i, i.refresh()); return i; } |
|
1223 |
bool Node::has_out(DUIterator& i) const |
|
1224 |
{ I_VDUI_ONLY(i, i.verify(this,true));return i._idx < _outcnt; } |
|
1225 |
Node* Node::out(DUIterator& i) const |
|
1226 |
{ I_VDUI_ONLY(i, i.verify(this)); return debug_only(i._last=) _out[i._idx]; } |
|
1227 |
||
1228 |
||
1229 |
// Faster DU iterator. Disallows insertions into the out array. |
|
1230 |
// Allows deletion from the out array only at the current point. |
|
1231 |
// Usage: |
|
1232 |
// for (DUIterator_Fast imax, i = x->fast_outs(imax); i < imax; i++) { |
|
1233 |
// Node* y = x->fast_out(i); |
|
1234 |
// ... |
|
1235 |
// } |
|
1236 |
// Compiles in product mode to raw Node** pointer arithmetic, with |
|
1237 |
// no reloading of pointers from the original node x. If you delete, |
|
1238 |
// you must perform "--i; --imax" just before continuing the loop. |
|
1239 |
// If you delete multiple copies of the same edge, you must decrement |
|
1240 |
// imax, but not i, multiple times: "--i, imax -= num_edges". |
|
1241 |
class DUIterator_Fast : public DUIterator_Common { |
|
1242 |
friend class Node; |
|
1243 |
friend class DUIterator_Last; |
|
1244 |
||
1245 |
// This is the pointer which provides the product-mode behavior. |
|
1246 |
// Whatever the product-mode version of the system does to the |
|
1247 |
// DUI pointer is done to this pointer. All other fields in |
|
1248 |
// this class are used only for assertion checking. |
|
1249 |
Node** _outp; |
|
1250 |
||
1251 |
#ifdef ASSERT |
|
1252 |
void verify(const Node* node, bool at_end_ok = false); |
|
1253 |
void verify_limit(); |
|
1254 |
void verify_resync(); |
|
1255 |
void verify_relimit(uint n); |
|
1256 |
void reset(const DUIterator_Fast& that); |
|
1257 |
#endif |
|
1258 |
||
1259 |
// Note: offset must be signed, since -1 is sometimes passed |
|
1260 |
DUIterator_Fast(const Node* node, ptrdiff_t offset) |
|
1261 |
{ _outp = node->_out + offset; debug_only(sample(node)); } |
|
1262 |
||
1263 |
public: |
|
1264 |
// initialize to garbage; clear _vdui to disable asserts |
|
1265 |
DUIterator_Fast() |
|
1266 |
{ /*initialize to garbage*/ debug_only(_vdui = false); } |
|
1267 |
||
1268 |
void operator++(int dummy_to_specify_postfix_op) |
|
1269 |
{ _outp++; VDUI_ONLY(verify(_node, true)); } |
|
1270 |
||
1271 |
void operator--() |
|
1272 |
{ VDUI_ONLY(verify_resync()); --_outp; } |
|
1273 |
||
1274 |
void operator-=(uint n) // applied to the limit only |
|
1275 |
{ _outp -= n; VDUI_ONLY(verify_relimit(n)); } |
|
1276 |
||
1277 |
bool operator<(DUIterator_Fast& limit) { |
|
1278 |
I_VDUI_ONLY(*this, this->verify(_node, true)); |
|
1279 |
I_VDUI_ONLY(limit, limit.verify_limit()); |
|
1280 |
return _outp < limit._outp; |
|
1281 |
} |
|
1282 |
||
1283 |
void operator=(const DUIterator_Fast& that) |
|
1284 |
{ _outp = that._outp; debug_only(reset(that)); } |
|
1285 |
}; |
|
1286 |
||
1287 |
DUIterator_Fast Node::fast_outs(DUIterator_Fast& imax) const { |
|
1288 |
// Assign a limit pointer to the reference argument: |
|
1289 |
imax = DUIterator_Fast(this, (ptrdiff_t)_outcnt); |
|
1290 |
// Return the base pointer: |
|
1291 |
return DUIterator_Fast(this, 0); |
|
1292 |
} |
|
1293 |
Node* Node::fast_out(DUIterator_Fast& i) const { |
|
1294 |
I_VDUI_ONLY(i, i.verify(this)); |
|
1295 |
return debug_only(i._last=) *i._outp; |
|
1296 |
} |
|
1297 |
||
1298 |
||
1299 |
// Faster DU iterator. Requires each successive edge to be removed. |
|
1300 |
// Does not allow insertion of any edges. |
|
1301 |
// Usage: |
|
1302 |
// for (DUIterator_Last imin, i = x->last_outs(imin); i >= imin; i -= num_edges) { |
|
1303 |
// Node* y = x->last_out(i); |
|
1304 |
// ... |
|
1305 |
// } |
|
1306 |
// Compiles in product mode to raw Node** pointer arithmetic, with |
|
1307 |
// no reloading of pointers from the original node x. |
|
1308 |
class DUIterator_Last : private DUIterator_Fast { |
|
1309 |
friend class Node; |
|
1310 |
||
1311 |
#ifdef ASSERT |
|
1312 |
void verify(const Node* node, bool at_end_ok = false); |
|
1313 |
void verify_limit(); |
|
1314 |
void verify_step(uint num_edges); |
|
1315 |
#endif |
|
1316 |
||
1317 |
// Note: offset must be signed, since -1 is sometimes passed |
|
1318 |
DUIterator_Last(const Node* node, ptrdiff_t offset) |
|
1319 |
: DUIterator_Fast(node, offset) { } |
|
1320 |
||
1321 |
void operator++(int dummy_to_specify_postfix_op) {} // do not use |
|
1322 |
void operator<(int) {} // do not use |
|
1323 |
||
1324 |
public: |
|
1325 |
DUIterator_Last() { } |
|
1326 |
// initialize to garbage |
|
1327 |
||
1328 |
void operator--() |
|
1329 |
{ _outp--; VDUI_ONLY(verify_step(1)); } |
|
1330 |
||
1331 |
void operator-=(uint n) |
|
1332 |
{ _outp -= n; VDUI_ONLY(verify_step(n)); } |
|
1333 |
||
1334 |
bool operator>=(DUIterator_Last& limit) { |
|
1335 |
I_VDUI_ONLY(*this, this->verify(_node, true)); |
|
1336 |
I_VDUI_ONLY(limit, limit.verify_limit()); |
|
1337 |
return _outp >= limit._outp; |
|
1338 |
} |
|
1339 |
||
1340 |
void operator=(const DUIterator_Last& that) |
|
1341 |
{ DUIterator_Fast::operator=(that); } |
|
1342 |
}; |
|
1343 |
||
1344 |
DUIterator_Last Node::last_outs(DUIterator_Last& imin) const { |
|
1345 |
// Assign a limit pointer to the reference argument: |
|
1346 |
imin = DUIterator_Last(this, 0); |
|
1347 |
// Return the initial pointer: |
|
1348 |
return DUIterator_Last(this, (ptrdiff_t)_outcnt - 1); |
|
1349 |
} |
|
1350 |
Node* Node::last_out(DUIterator_Last& i) const { |
|
1351 |
I_VDUI_ONLY(i, i.verify(this)); |
|
1352 |
return debug_only(i._last=) *i._outp; |
|
1353 |
} |
|
1354 |
||
1355 |
#endif //OPTO_DU_ITERATOR_ASSERT |
|
1356 |
||
1357 |
#undef I_VDUI_ONLY |
|
1358 |
#undef VDUI_ONLY |
|
1359 |
||
4450
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1360 |
// An Iterator that truly follows the iterator pattern. Doesn't |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1361 |
// support deletion but could be made to. |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1362 |
// |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1363 |
// for (SimpleDUIterator i(n); i.has_next(); i.next()) { |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1364 |
// Node* m = i.get(); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1365 |
// |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1366 |
class SimpleDUIterator : public StackObj { |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1367 |
private: |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1368 |
Node* node; |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1369 |
DUIterator_Fast i; |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1370 |
DUIterator_Fast imax; |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1371 |
public: |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1372 |
SimpleDUIterator(Node* n): node(n), i(n->fast_outs(imax)) {} |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1373 |
bool has_next() { return i < imax; } |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1374 |
void next() { i++; } |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1375 |
Node* get() { return node->fast_out(i); } |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1376 |
}; |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1377 |
|
1 | 1378 |
|
1379 |
//----------------------------------------------------------------------------- |
|
1380 |
// Map dense integer indices to Nodes. Uses classic doubling-array trick. |
|
1381 |
// Abstractly provides an infinite array of Node*'s, initialized to NULL. |
|
1382 |
// Note that the constructor just zeros things, and since I use Arena |
|
1383 |
// allocation I do not need a destructor to reclaim storage. |
|
1384 |
class Node_Array : public ResourceObj { |
|
10547 | 1385 |
friend class VMStructs; |
1 | 1386 |
protected: |
1387 |
Arena *_a; // Arena to allocate in |
|
1388 |
uint _max; |
|
1389 |
Node **_nodes; |
|
1390 |
void grow( uint i ); // Grow array node to fit |
|
1391 |
public: |
|
1392 |
Node_Array(Arena *a) : _a(a), _max(OptoNodeListSize) { |
|
1393 |
_nodes = NEW_ARENA_ARRAY( a, Node *, OptoNodeListSize ); |
|
1394 |
for( int i = 0; i < OptoNodeListSize; i++ ) { |
|
1395 |
_nodes[i] = NULL; |
|
1396 |
} |
|
1397 |
} |
|
1398 |
||
1399 |
Node_Array(Node_Array *na) : _a(na->_a), _max(na->_max), _nodes(na->_nodes) {} |
|
1400 |
Node *operator[] ( uint i ) const // Lookup, or NULL for not mapped |
|
1401 |
{ return (i<_max) ? _nodes[i] : (Node*)NULL; } |
|
1402 |
Node *at( uint i ) const { assert(i<_max,"oob"); return _nodes[i]; } |
|
1403 |
Node **adr() { return _nodes; } |
|
1404 |
// Extend the mapping: index i maps to Node *n. |
|
1405 |
void map( uint i, Node *n ) { if( i>=_max ) grow(i); _nodes[i] = n; } |
|
1406 |
void insert( uint i, Node *n ); |
|
1407 |
void remove( uint i ); // Remove, preserving order |
|
1408 |
void sort( C_sort_func_t func); |
|
1409 |
void reset( Arena *new_a ); // Zap mapping to empty; reclaim storage |
|
1410 |
void clear(); // Set all entries to NULL, keep storage |
|
1411 |
uint Size() const { return _max; } |
|
1412 |
void dump() const; |
|
1413 |
}; |
|
1414 |
||
1415 |
class Node_List : public Node_Array { |
|
10547 | 1416 |
friend class VMStructs; |
1 | 1417 |
uint _cnt; |
1418 |
public: |
|
1419 |
Node_List() : Node_Array(Thread::current()->resource_area()), _cnt(0) {} |
|
1420 |
Node_List(Arena *a) : Node_Array(a), _cnt(0) {} |
|
22844
90f76a40ed8a
8003854: PPC64 (part 115): Introduce PostallocExpand that expands nodes after register allocation
goetz
parents:
21105
diff
changeset
|
1421 |
bool contains(const Node* n) const { |
4450
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1422 |
for (uint e = 0; e < size(); e++) { |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1423 |
if (at(e) == n) return true; |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1424 |
} |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1425 |
return false; |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
2131
diff
changeset
|
1426 |
} |
1 | 1427 |
void insert( uint i, Node *n ) { Node_Array::insert(i,n); _cnt++; } |
1428 |
void remove( uint i ) { Node_Array::remove(i); _cnt--; } |
|
1429 |
void push( Node *b ) { map(_cnt++,b); } |
|
1430 |
void yank( Node *n ); // Find and remove |
|
1431 |
Node *pop() { return _nodes[--_cnt]; } |
|
1432 |
Node *rpop() { Node *b = _nodes[0]; _nodes[0]=_nodes[--_cnt]; return b;} |
|
1433 |
void clear() { _cnt = 0; Node_Array::clear(); } // retain storage |
|
1434 |
uint size() const { return _cnt; } |
|
1435 |
void dump() const; |
|
1436 |
}; |
|
1437 |
||
1438 |
//------------------------------Unique_Node_List------------------------------- |
|
1439 |
class Unique_Node_List : public Node_List { |
|
10547 | 1440 |
friend class VMStructs; |
1 | 1441 |
VectorSet _in_worklist; |
1442 |
uint _clock_index; // Index in list where to pop from next |
|
1443 |
public: |
|
1444 |
Unique_Node_List() : Node_List(), _in_worklist(Thread::current()->resource_area()), _clock_index(0) {} |
|
1445 |
Unique_Node_List(Arena *a) : Node_List(a), _in_worklist(a), _clock_index(0) {} |
|
1446 |
||
1447 |
void remove( Node *n ); |
|
1448 |
bool member( Node *n ) { return _in_worklist.test(n->_idx) != 0; } |
|
1449 |
VectorSet &member_set(){ return _in_worklist; } |
|
1450 |
||
1451 |
void push( Node *b ) { |
|
1452 |
if( !_in_worklist.test_set(b->_idx) ) |
|
1453 |
Node_List::push(b); |
|
1454 |
} |
|
1455 |
Node *pop() { |
|
1456 |
if( _clock_index >= size() ) _clock_index = 0; |
|
1457 |
Node *b = at(_clock_index); |
|
1432
44f076e3d2a4
6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents:
955
diff
changeset
|
1458 |
map( _clock_index, Node_List::pop()); |
44f076e3d2a4
6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents:
955
diff
changeset
|
1459 |
if (size() != 0) _clock_index++; // Always start from 0 |
1 | 1460 |
_in_worklist >>= b->_idx; |
1461 |
return b; |
|
1462 |
} |
|
1463 |
Node *remove( uint i ) { |
|
1464 |
Node *b = Node_List::at(i); |
|
1465 |
_in_worklist >>= b->_idx; |
|
1466 |
map(i,Node_List::pop()); |
|
1467 |
return b; |
|
1468 |
} |
|
1469 |
void yank( Node *n ) { _in_worklist >>= n->_idx; Node_List::yank(n); } |
|
1470 |
void clear() { |
|
1471 |
_in_worklist.Clear(); // Discards storage but grows automatically |
|
1472 |
Node_List::clear(); |
|
1473 |
_clock_index = 0; |
|
1474 |
} |
|
1475 |
||
1476 |
// Used after parsing to remove useless nodes before Iterative GVN |
|
1477 |
void remove_useless_nodes(VectorSet &useful); |
|
1478 |
||
1479 |
#ifndef PRODUCT |
|
1480 |
void print_set() const { _in_worklist.print(); } |
|
1481 |
#endif |
|
1482 |
}; |
|
1483 |
||
1484 |
// Inline definition of Compile::record_for_igvn must be deferred to this point. |
|
1485 |
inline void Compile::record_for_igvn(Node* n) { |
|
1486 |
_for_igvn->push(n); |
|
1487 |
} |
|
1488 |
||
1489 |
//------------------------------Node_Stack------------------------------------- |
|
1490 |
class Node_Stack { |
|
10547 | 1491 |
friend class VMStructs; |
1 | 1492 |
protected: |
1493 |
struct INode { |
|
1494 |
Node *node; // Processed node |
|
1495 |
uint indx; // Index of next node's child |
|
1496 |
}; |
|
1497 |
INode *_inode_top; // tos, stack grows up |
|
1498 |
INode *_inode_max; // End of _inodes == _inodes + _max |
|
1499 |
INode *_inodes; // Array storage for the stack |
|
1500 |
Arena *_a; // Arena to allocate in |
|
1501 |
void grow(); |
|
1502 |
public: |
|
1503 |
Node_Stack(int size) { |
|
1504 |
size_t max = (size > OptoNodeListSize) ? size : OptoNodeListSize; |
|
1505 |
_a = Thread::current()->resource_area(); |
|
1506 |
_inodes = NEW_ARENA_ARRAY( _a, INode, max ); |
|
1507 |
_inode_max = _inodes + max; |
|
1508 |
_inode_top = _inodes - 1; // stack is empty |
|
1509 |
} |
|
1510 |
||
1511 |
Node_Stack(Arena *a, int size) : _a(a) { |
|
1512 |
size_t max = (size > OptoNodeListSize) ? size : OptoNodeListSize; |
|
1513 |
_inodes = NEW_ARENA_ARRAY( _a, INode, max ); |
|
1514 |
_inode_max = _inodes + max; |
|
1515 |
_inode_top = _inodes - 1; // stack is empty |
|
1516 |
} |
|
1517 |
||
1518 |
void pop() { |
|
1519 |
assert(_inode_top >= _inodes, "node stack underflow"); |
|
1520 |
--_inode_top; |
|
1521 |
} |
|
1522 |
void push(Node *n, uint i) { |
|
1523 |
++_inode_top; |
|
1524 |
if (_inode_top >= _inode_max) grow(); |
|
1525 |
INode *top = _inode_top; // optimization |
|
1526 |
top->node = n; |
|
1527 |
top->indx = i; |
|
1528 |
} |
|
1529 |
Node *node() const { |
|
1530 |
return _inode_top->node; |
|
1531 |
} |
|
1532 |
Node* node_at(uint i) const { |
|
1533 |
assert(_inodes + i <= _inode_top, "in range"); |
|
1534 |
return _inodes[i].node; |
|
1535 |
} |
|
1536 |
uint index() const { |
|
1537 |
return _inode_top->indx; |
|
1538 |
} |
|
955 | 1539 |
uint index_at(uint i) const { |
1540 |
assert(_inodes + i <= _inode_top, "in range"); |
|
1541 |
return _inodes[i].indx; |
|
1542 |
} |
|
1 | 1543 |
void set_node(Node *n) { |
1544 |
_inode_top->node = n; |
|
1545 |
} |
|
1546 |
void set_index(uint i) { |
|
1547 |
_inode_top->indx = i; |
|
1548 |
} |
|
1549 |
uint size_max() const { return (uint)pointer_delta(_inode_max, _inodes, sizeof(INode)); } // Max size |
|
213 | 1550 |
uint size() const { return (uint)pointer_delta((_inode_top+1), _inodes, sizeof(INode)); } // Current size |
1 | 1551 |
bool is_nonempty() const { return (_inode_top >= _inodes); } |
1552 |
bool is_empty() const { return (_inode_top < _inodes); } |
|
1553 |
void clear() { _inode_top = _inodes - 1; } // retain storage |
|
10011
e8b38f7b9959
7044738: Loop unroll optimization causes incorrect result
kvn
parents:
7433
diff
changeset
|
1554 |
|
e8b38f7b9959
7044738: Loop unroll optimization causes incorrect result
kvn
parents:
7433
diff
changeset
|
1555 |
// Node_Stack is used to map nodes. |
e8b38f7b9959
7044738: Loop unroll optimization causes incorrect result
kvn
parents:
7433
diff
changeset
|
1556 |
Node* find(uint idx) const; |
1 | 1557 |
}; |
1558 |
||
1559 |
||
1560 |
//-----------------------------Node_Notes-------------------------------------- |
|
1561 |
// Debugging or profiling annotations loosely and sparsely associated |
|
1562 |
// with some nodes. See Compile::node_notes_at for the accessor. |
|
1563 |
class Node_Notes VALUE_OBJ_CLASS_SPEC { |
|
10547 | 1564 |
friend class VMStructs; |
1 | 1565 |
JVMState* _jvms; |
1566 |
||
1567 |
public: |
|
1568 |
Node_Notes(JVMState* jvms = NULL) { |
|
1569 |
_jvms = jvms; |
|
1570 |
} |
|
1571 |
||
1572 |
JVMState* jvms() { return _jvms; } |
|
1573 |
void set_jvms(JVMState* x) { _jvms = x; } |
|
1574 |
||
1575 |
// True if there is nothing here. |
|
1576 |
bool is_clear() { |
|
1577 |
return (_jvms == NULL); |
|
1578 |
} |
|
1579 |
||
1580 |
// Make there be nothing here. |
|
1581 |
void clear() { |
|
1582 |
_jvms = NULL; |
|
1583 |
} |
|
1584 |
||
1585 |
// Make a new, clean node notes. |
|
1586 |
static Node_Notes* make(Compile* C) { |
|
1587 |
Node_Notes* nn = NEW_ARENA_ARRAY(C->comp_arena(), Node_Notes, 1); |
|
1588 |
nn->clear(); |
|
1589 |
return nn; |
|
1590 |
} |
|
1591 |
||
1592 |
Node_Notes* clone(Compile* C) { |
|
1593 |
Node_Notes* nn = NEW_ARENA_ARRAY(C->comp_arena(), Node_Notes, 1); |
|
1594 |
(*nn) = (*this); |
|
1595 |
return nn; |
|
1596 |
} |
|
1597 |
||
1598 |
// Absorb any information from source. |
|
1599 |
bool update_from(Node_Notes* source) { |
|
1600 |
bool changed = false; |
|
1601 |
if (source != NULL) { |
|
1602 |
if (source->jvms() != NULL) { |
|
1603 |
set_jvms(source->jvms()); |
|
1604 |
changed = true; |
|
1605 |
} |
|
1606 |
} |
|
1607 |
return changed; |
|
1608 |
} |
|
1609 |
}; |
|
1610 |
||
1611 |
// Inlined accessors for Compile::node_nodes that require the preceding class: |
|
1612 |
inline Node_Notes* |
|
1613 |
Compile::locate_node_notes(GrowableArray<Node_Notes*>* arr, |
|
1614 |
int idx, bool can_grow) { |
|
1615 |
assert(idx >= 0, "oob"); |
|
1616 |
int block_idx = (idx >> _log2_node_notes_block_size); |
|
1617 |
int grow_by = (block_idx - (arr == NULL? 0: arr->length())); |
|
1618 |
if (grow_by >= 0) { |
|
1619 |
if (!can_grow) return NULL; |
|
1620 |
grow_node_notes(arr, grow_by + 1); |
|
1621 |
} |
|
1622 |
// (Every element of arr is a sub-array of length _node_notes_block_size.) |
|
1623 |
return arr->at(block_idx) + (idx & (_node_notes_block_size-1)); |
|
1624 |
} |
|
1625 |
||
1626 |
inline bool |
|
1627 |
Compile::set_node_notes_at(int idx, Node_Notes* value) { |
|
1628 |
if (value == NULL || value->is_clear()) |
|
1629 |
return false; // nothing to write => write nothing |
|
1630 |
Node_Notes* loc = locate_node_notes(_node_note_array, idx, true); |
|
1631 |
assert(loc != NULL, ""); |
|
1632 |
return loc->update_from(value); |
|
1633 |
} |
|
1634 |
||
1635 |
||
1636 |
//------------------------------TypeNode--------------------------------------- |
|
1637 |
// Node with a Type constant. |
|
1638 |
class TypeNode : public Node { |
|
1639 |
protected: |
|
1640 |
virtual uint hash() const; // Check the type |
|
1641 |
virtual uint cmp( const Node &n ) const; |
|
1642 |
virtual uint size_of() const; // Size is bigger |
|
1643 |
const Type* const _type; |
|
1644 |
public: |
|
1645 |
void set_type(const Type* t) { |
|
1646 |
assert(t != NULL, "sanity"); |
|
1647 |
debug_only(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH); |
|
1648 |
*(const Type**)&_type = t; // cast away const-ness |
|
1649 |
// If this node is in the hash table, make sure it doesn't need a rehash. |
|
1650 |
assert(check_hash == NO_HASH || check_hash == hash(), "type change must preserve hash code"); |
|
1651 |
} |
|
1652 |
const Type* type() const { assert(_type != NULL, "sanity"); return _type; }; |
|
1653 |
TypeNode( const Type *t, uint required ) : Node(required), _type(t) { |
|
1654 |
init_class_id(Class_Type); |
|
1655 |
} |
|
1656 |
virtual const Type *Value( PhaseTransform *phase ) const; |
|
1657 |
virtual const Type *bottom_type() const; |
|
1658 |
virtual uint ideal_reg() const; |
|
1659 |
#ifndef PRODUCT |
|
1660 |
virtual void dump_spec(outputStream *st) const; |
|
32084
7743e6943cdf
8004073: Implement C2 Ideal node specific dump() method
mhaupt
parents:
30300
diff
changeset
|
1661 |
virtual void dump_compact_spec(outputStream *st) const; |
1 | 1662 |
#endif |
1663 |
}; |
|
7397 | 1664 |
|
1665 |
#endif // SHARE_VM_OPTO_NODE_HPP |