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