Mercurial > hg > truffle
annotate src/share/vm/opto/cfgnode.hpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
400
diff
changeset
|
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
400
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
400
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
400
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 // Portions of code courtesy of Clifford Click | |
26 | |
27 // Optimization - Graph Style | |
28 | |
29 class Matcher; | |
30 class Node; | |
31 class RegionNode; | |
32 class TypeNode; | |
33 class PhiNode; | |
34 class GotoNode; | |
35 class MultiNode; | |
36 class MultiBranchNode; | |
37 class IfNode; | |
38 class PCTableNode; | |
39 class JumpNode; | |
40 class CatchNode; | |
41 class NeverBranchNode; | |
42 class ProjNode; | |
43 class CProjNode; | |
44 class IfTrueNode; | |
45 class IfFalseNode; | |
46 class CatchProjNode; | |
47 class JProjNode; | |
48 class JumpProjNode; | |
49 class SCMemProjNode; | |
50 class PhaseIdealLoop; | |
51 | |
52 //------------------------------RegionNode------------------------------------- | |
53 // The class of RegionNodes, which can be mapped to basic blocks in the | |
54 // program. Their inputs point to Control sources. PhiNodes (described | |
55 // below) have an input point to a RegionNode. Merged data inputs to PhiNodes | |
56 // correspond 1-to-1 with RegionNode inputs. The zero input of a PhiNode is | |
57 // the RegionNode, and the zero input of the RegionNode is itself. | |
58 class RegionNode : public Node { | |
59 public: | |
60 // Node layout (parallels PhiNode): | |
61 enum { Region, // Generally points to self. | |
62 Control // Control arcs are [1..len) | |
63 }; | |
64 | |
65 RegionNode( uint required ) : Node(required) { | |
66 init_class_id(Class_Region); | |
67 init_req(0,this); | |
68 } | |
69 | |
70 Node* is_copy() const { | |
71 const Node* r = _in[Region]; | |
72 if (r == NULL) | |
73 return nonnull_req(); | |
74 return NULL; // not a copy! | |
75 } | |
76 PhiNode* has_phi() const; // returns an arbitrary phi user, or NULL | |
77 PhiNode* has_unique_phi() const; // returns the unique phi user, or NULL | |
78 // Is this region node unreachable from root? | |
79 bool is_unreachable_region(PhaseGVN *phase) const; | |
80 virtual int Opcode() const; | |
81 virtual bool pinned() const { return (const Node *)in(0) == this; } | |
82 virtual bool is_CFG () const { return true; } | |
83 virtual uint hash() const { return NO_HASH; } // CFG nodes do not hash | |
84 virtual bool depends_only_on_test() const { return false; } | |
85 virtual const Type *bottom_type() const { return Type::CONTROL; } | |
86 virtual const Type *Value( PhaseTransform *phase ) const; | |
87 virtual Node *Identity( PhaseTransform *phase ); | |
88 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |
89 virtual const RegMask &out_RegMask() const; | |
90 }; | |
91 | |
92 //------------------------------JProjNode-------------------------------------- | |
93 // jump projection for node that produces multiple control-flow paths | |
94 class JProjNode : public ProjNode { | |
95 public: | |
96 JProjNode( Node* ctrl, uint idx ) : ProjNode(ctrl,idx) {} | |
97 virtual int Opcode() const; | |
98 virtual bool is_CFG() const { return true; } | |
99 virtual uint hash() const { return NO_HASH; } // CFG nodes do not hash | |
100 virtual const Node* is_block_proj() const { return in(0); } | |
101 virtual const RegMask& out_RegMask() const; | |
102 virtual uint ideal_reg() const { return 0; } | |
103 }; | |
104 | |
105 //------------------------------PhiNode---------------------------------------- | |
106 // PhiNodes merge values from different Control paths. Slot 0 points to the | |
107 // controlling RegionNode. Other slots map 1-for-1 with incoming control flow | |
108 // paths to the RegionNode. For speed reasons (to avoid another pass) we | |
109 // can turn PhiNodes into copys in-place by NULL'ing out their RegionNode | |
110 // input in slot 0. | |
111 class PhiNode : public TypeNode { | |
112 const TypePtr* const _adr_type; // non-null only for Type::MEMORY nodes. | |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
113 const int _inst_id; // Instance id of the memory slice. |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
114 const int _inst_index; // Alias index of the instance memory slice. |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
115 // Array elements references have the same alias_idx but different offset. |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
116 const int _inst_offset; // Offset of the instance memory slice. |
0 | 117 // Size is bigger to hold the _adr_type field. |
118 virtual uint hash() const; // Check the type | |
119 virtual uint cmp( const Node &n ) const; | |
120 virtual uint size_of() const { return sizeof(*this); } | |
121 | |
122 // Determine if CMoveNode::is_cmove_id can be used at this join point. | |
123 Node* is_cmove_id(PhaseTransform* phase, int true_path); | |
124 | |
125 public: | |
126 // Node layout (parallels RegionNode): | |
127 enum { Region, // Control input is the Phi's region. | |
128 Input // Input values are [1..len) | |
129 }; | |
130 | |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
131 PhiNode( Node *r, const Type *t, const TypePtr* at = NULL, |
223 | 132 const int iid = TypeOopPtr::InstanceTop, |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
133 const int iidx = Compile::AliasIdxTop, |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
134 const int ioffs = Type::OffsetTop ) |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
135 : TypeNode(t,r->req()), |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
136 _adr_type(at), |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
137 _inst_id(iid), |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
138 _inst_index(iidx), |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
139 _inst_offset(ioffs) |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
140 { |
0 | 141 init_class_id(Class_Phi); |
142 init_req(0, r); | |
143 verify_adr_type(); | |
144 } | |
145 // create a new phi with in edges matching r and set (initially) to x | |
146 static PhiNode* make( Node* r, Node* x ); | |
147 // extra type arguments override the new phi's bottom_type and adr_type | |
148 static PhiNode* make( Node* r, Node* x, const Type *t, const TypePtr* at = NULL ); | |
149 // create a new phi with narrowed memory type | |
150 PhiNode* slice_memory(const TypePtr* adr_type) const; | |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
64
diff
changeset
|
151 PhiNode* split_out_instance(const TypePtr* at, PhaseIterGVN *igvn) const; |
0 | 152 // like make(r, x), but does not initialize the in edges to x |
153 static PhiNode* make_blank( Node* r, Node* x ); | |
154 | |
155 // Accessors | |
156 RegionNode* region() const { Node* r = in(Region); assert(!r || r->is_Region(), ""); return (RegionNode*)r; } | |
157 | |
158 Node* is_copy() const { | |
159 // The node is a real phi if _in[0] is a Region node. | |
160 DEBUG_ONLY(const Node* r = _in[Region];) | |
161 assert(r != NULL && r->is_Region(), "Not valid control"); | |
162 return NULL; // not a copy! | |
163 } | |
164 | |
400
cc80376deb0c
6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents:
235
diff
changeset
|
165 bool is_tripcount() const; |
cc80376deb0c
6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents:
235
diff
changeset
|
166 |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
167 // Determine a unique non-trivial input, if any. |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
168 // Ignore casts if it helps. Return NULL on failure. |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
169 Node* unique_input(PhaseTransform *phase); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
170 |
0 | 171 // Check for a simple dead loop. |
172 enum LoopSafety { Safe = 0, Unsafe, UnsafeLoop }; | |
173 LoopSafety simple_data_loop_check(Node *in) const; | |
174 // Is it unsafe data loop? It becomes a dead loop if this phi node removed. | |
175 bool is_unsafe_data_reference(Node *in) const; | |
176 int is_diamond_phi() const; | |
177 virtual int Opcode() const; | |
178 virtual bool pinned() const { return in(0) != 0; } | |
179 virtual const TypePtr *adr_type() const { verify_adr_type(true); return _adr_type; } | |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
180 |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
181 const int inst_id() const { return _inst_id; } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
182 const int inst_index() const { return _inst_index; } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
183 const int inst_offset() const { return _inst_offset; } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
184 bool is_same_inst_field(const Type* tp, int id, int index, int offset) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
185 return type()->basic_type() == tp->basic_type() && |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
186 inst_id() == id && |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
187 inst_index() == index && |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
188 inst_offset() == offset && |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
189 type()->higher_equal(tp); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
190 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
17
diff
changeset
|
191 |
0 | 192 virtual const Type *Value( PhaseTransform *phase ) const; |
193 virtual Node *Identity( PhaseTransform *phase ); | |
194 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |
195 virtual const RegMask &out_RegMask() const; | |
196 virtual const RegMask &in_RegMask(uint) const; | |
197 #ifndef PRODUCT | |
198 virtual void dump_spec(outputStream *st) const; | |
199 #endif | |
200 #ifdef ASSERT | |
201 void verify_adr_type(VectorSet& visited, const TypePtr* at) const; | |
202 void verify_adr_type(bool recursive = false) const; | |
203 #else //ASSERT | |
204 void verify_adr_type(bool recursive = false) const {} | |
205 #endif //ASSERT | |
206 }; | |
207 | |
208 //------------------------------GotoNode--------------------------------------- | |
209 // GotoNodes perform direct branches. | |
210 class GotoNode : public Node { | |
211 public: | |
212 GotoNode( Node *control ) : Node(control) { | |
213 init_flags(Flag_is_Goto); | |
214 } | |
215 virtual int Opcode() const; | |
216 virtual bool pinned() const { return true; } | |
217 virtual bool is_CFG() const { return true; } | |
218 virtual uint hash() const { return NO_HASH; } // CFG nodes do not hash | |
219 virtual const Node *is_block_proj() const { return this; } | |
220 virtual bool depends_only_on_test() const { return false; } | |
221 virtual const Type *bottom_type() const { return Type::CONTROL; } | |
222 virtual const Type *Value( PhaseTransform *phase ) const; | |
223 virtual Node *Identity( PhaseTransform *phase ); | |
224 virtual const RegMask &out_RegMask() const; | |
225 }; | |
226 | |
227 //------------------------------CProjNode-------------------------------------- | |
228 // control projection for node that produces multiple control-flow paths | |
229 class CProjNode : public ProjNode { | |
230 public: | |
231 CProjNode( Node *ctrl, uint idx ) : ProjNode(ctrl,idx) {} | |
232 virtual int Opcode() const; | |
233 virtual bool is_CFG() const { return true; } | |
234 virtual uint hash() const { return NO_HASH; } // CFG nodes do not hash | |
235 virtual const Node *is_block_proj() const { return in(0); } | |
236 virtual const RegMask &out_RegMask() const; | |
237 virtual uint ideal_reg() const { return 0; } | |
238 }; | |
239 | |
240 //---------------------------MultiBranchNode----------------------------------- | |
241 // This class defines a MultiBranchNode, a MultiNode which yields multiple | |
242 // control values. These are distinguished from other types of MultiNodes | |
243 // which yield multiple values, but control is always and only projection #0. | |
244 class MultiBranchNode : public MultiNode { | |
245 public: | |
246 MultiBranchNode( uint required ) : MultiNode(required) { | |
247 init_class_id(Class_MultiBranch); | |
248 } | |
127 | 249 // returns required number of users to be well formed. |
250 virtual int required_outcnt() const = 0; | |
0 | 251 }; |
252 | |
253 //------------------------------IfNode----------------------------------------- | |
254 // Output selected Control, based on a boolean test | |
255 class IfNode : public MultiBranchNode { | |
256 // Size is bigger to hold the probability field. However, _prob does not | |
257 // change the semantics so it does not appear in the hash & cmp functions. | |
258 virtual uint size_of() const { return sizeof(*this); } | |
259 public: | |
260 | |
261 // Degrees of branch prediction probability by order of magnitude: | |
262 // PROB_UNLIKELY_1e(N) is a 1 in 1eN chance. | |
263 // PROB_LIKELY_1e(N) is a 1 - PROB_UNLIKELY_1e(N) | |
264 #define PROB_UNLIKELY_MAG(N) (1e- ## N ## f) | |
265 #define PROB_LIKELY_MAG(N) (1.0f-PROB_UNLIKELY_MAG(N)) | |
266 | |
267 // Maximum and minimum branch prediction probabilties | |
268 // 1 in 1,000,000 (magnitude 6) | |
269 // | |
270 // Although PROB_NEVER == PROB_MIN and PROB_ALWAYS == PROB_MAX | |
271 // they are used to distinguish different situations: | |
272 // | |
273 // The name PROB_MAX (PROB_MIN) is for probabilities which correspond to | |
274 // very likely (unlikely) but with a concrete possibility of a rare | |
275 // contrary case. These constants would be used for pinning | |
276 // measurements, and as measures for assertions that have high | |
277 // confidence, but some evidence of occasional failure. | |
278 // | |
279 // The name PROB_ALWAYS (PROB_NEVER) is to stand for situations for which | |
280 // there is no evidence at all that the contrary case has ever occurred. | |
281 | |
282 #define PROB_NEVER PROB_UNLIKELY_MAG(6) | |
283 #define PROB_ALWAYS PROB_LIKELY_MAG(6) | |
284 | |
285 #define PROB_MIN PROB_UNLIKELY_MAG(6) | |
286 #define PROB_MAX PROB_LIKELY_MAG(6) | |
287 | |
288 // Static branch prediction probabilities | |
289 // 1 in 10 (magnitude 1) | |
290 #define PROB_STATIC_INFREQUENT PROB_UNLIKELY_MAG(1) | |
291 #define PROB_STATIC_FREQUENT PROB_LIKELY_MAG(1) | |
292 | |
293 // Fair probability 50/50 | |
294 #define PROB_FAIR (0.5f) | |
295 | |
296 // Unknown probability sentinel | |
297 #define PROB_UNKNOWN (-1.0f) | |
298 | |
299 // Probability "constructors", to distinguish as a probability any manifest | |
300 // constant without a names | |
301 #define PROB_LIKELY(x) ((float) (x)) | |
302 #define PROB_UNLIKELY(x) (1.0f - (float)(x)) | |
303 | |
304 // Other probabilities in use, but without a unique name, are documented | |
305 // here for lack of a better place: | |
306 // | |
307 // 1 in 1000 probabilities (magnitude 3): | |
308 // threshold for converting to conditional move | |
309 // likelihood of null check failure if a null HAS been seen before | |
310 // likelihood of slow path taken in library calls | |
311 // | |
312 // 1 in 10,000 probabilities (magnitude 4): | |
313 // threshold for making an uncommon trap probability more extreme | |
314 // threshold for for making a null check implicit | |
315 // likelihood of needing a gc if eden top moves during an allocation | |
316 // likelihood of a predicted call failure | |
317 // | |
318 // 1 in 100,000 probabilities (magnitude 5): | |
319 // threshold for ignoring counts when estimating path frequency | |
320 // likelihood of FP clipping failure | |
321 // likelihood of catching an exception from a try block | |
322 // likelihood of null check failure if a null has NOT been seen before | |
323 // | |
324 // Magic manifest probabilities such as 0.83, 0.7, ... can be found in | |
325 // gen_subtype_check() and catch_inline_exceptions(). | |
326 | |
327 float _prob; // Probability of true path being taken. | |
328 float _fcnt; // Frequency counter | |
329 IfNode( Node *control, Node *b, float p, float fcnt ) | |
330 : MultiBranchNode(2), _prob(p), _fcnt(fcnt) { | |
331 init_class_id(Class_If); | |
332 init_req(0,control); | |
333 init_req(1,b); | |
334 } | |
335 virtual int Opcode() const; | |
336 virtual bool pinned() const { return true; } | |
337 virtual const Type *bottom_type() const { return TypeTuple::IFBOTH; } | |
338 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |
339 virtual const Type *Value( PhaseTransform *phase ) const; | |
127 | 340 virtual int required_outcnt() const { return 2; } |
0 | 341 virtual const RegMask &out_RegMask() const; |
342 void dominated_by(Node* prev_dom, PhaseIterGVN* igvn); | |
343 int is_range_check(Node* &range, Node* &index, jint &offset); | |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
344 Node* fold_compares(PhaseGVN* phase); |
0 | 345 static Node* up_one_dom(Node* curr, bool linear_only = false); |
346 | |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
347 // Takes the type of val and filters it through the test represented |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
348 // by if_proj and returns a more refined type if one is produced. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
349 // Returns NULL is it couldn't improve the type. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
350 static const TypeInt* filtered_int_type(PhaseGVN* phase, Node* val, Node* if_proj); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
351 |
0 | 352 #ifndef PRODUCT |
353 virtual void dump_spec(outputStream *st) const; | |
354 #endif | |
355 }; | |
356 | |
357 class IfTrueNode : public CProjNode { | |
358 public: | |
359 IfTrueNode( IfNode *ifnode ) : CProjNode(ifnode,1) { | |
360 init_class_id(Class_IfTrue); | |
361 } | |
362 virtual int Opcode() const; | |
363 virtual Node *Identity( PhaseTransform *phase ); | |
364 }; | |
365 | |
366 class IfFalseNode : public CProjNode { | |
367 public: | |
368 IfFalseNode( IfNode *ifnode ) : CProjNode(ifnode,0) { | |
369 init_class_id(Class_IfFalse); | |
370 } | |
371 virtual int Opcode() const; | |
372 virtual Node *Identity( PhaseTransform *phase ); | |
373 }; | |
374 | |
375 | |
376 //------------------------------PCTableNode------------------------------------ | |
377 // Build an indirect branch table. Given a control and a table index, | |
378 // control is passed to the Projection matching the table index. Used to | |
379 // implement switch statements and exception-handling capabilities. | |
380 // Undefined behavior if passed-in index is not inside the table. | |
381 class PCTableNode : public MultiBranchNode { | |
382 virtual uint hash() const; // Target count; table size | |
383 virtual uint cmp( const Node &n ) const; | |
384 virtual uint size_of() const { return sizeof(*this); } | |
385 | |
386 public: | |
387 const uint _size; // Number of targets | |
388 | |
389 PCTableNode( Node *ctrl, Node *idx, uint size ) : MultiBranchNode(2), _size(size) { | |
390 init_class_id(Class_PCTable); | |
391 init_req(0, ctrl); | |
392 init_req(1, idx); | |
393 } | |
394 virtual int Opcode() const; | |
395 virtual const Type *Value( PhaseTransform *phase ) const; | |
396 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |
397 virtual const Type *bottom_type() const; | |
398 virtual bool pinned() const { return true; } | |
127 | 399 virtual int required_outcnt() const { return _size; } |
0 | 400 }; |
401 | |
402 //------------------------------JumpNode--------------------------------------- | |
403 // Indirect branch. Uses PCTable above to implement a switch statement. | |
404 // It emits as a table load and local branch. | |
405 class JumpNode : public PCTableNode { | |
406 public: | |
407 JumpNode( Node* control, Node* switch_val, uint size) : PCTableNode(control, switch_val, size) { | |
408 init_class_id(Class_Jump); | |
409 } | |
410 virtual int Opcode() const; | |
411 virtual const RegMask& out_RegMask() const; | |
412 virtual const Node* is_block_proj() const { return this; } | |
413 }; | |
414 | |
415 class JumpProjNode : public JProjNode { | |
416 virtual uint hash() const; | |
417 virtual uint cmp( const Node &n ) const; | |
418 virtual uint size_of() const { return sizeof(*this); } | |
419 | |
420 private: | |
421 const int _dest_bci; | |
422 const uint _proj_no; | |
423 const int _switch_val; | |
424 public: | |
425 JumpProjNode(Node* jumpnode, uint proj_no, int dest_bci, int switch_val) | |
426 : JProjNode(jumpnode, proj_no), _dest_bci(dest_bci), _proj_no(proj_no), _switch_val(switch_val) { | |
427 init_class_id(Class_JumpProj); | |
428 } | |
429 | |
430 virtual int Opcode() const; | |
431 virtual const Type* bottom_type() const { return Type::CONTROL; } | |
432 int dest_bci() const { return _dest_bci; } | |
433 int switch_val() const { return _switch_val; } | |
434 uint proj_no() const { return _proj_no; } | |
435 #ifndef PRODUCT | |
436 virtual void dump_spec(outputStream *st) const; | |
437 #endif | |
438 }; | |
439 | |
440 //------------------------------CatchNode-------------------------------------- | |
441 // Helper node to fork exceptions. "Catch" catches any exceptions thrown by | |
442 // a just-prior call. Looks like a PCTableNode but emits no code - just the | |
443 // table. The table lookup and branch is implemented by RethrowNode. | |
444 class CatchNode : public PCTableNode { | |
445 public: | |
446 CatchNode( Node *ctrl, Node *idx, uint size ) : PCTableNode(ctrl,idx,size){ | |
447 init_class_id(Class_Catch); | |
448 } | |
449 virtual int Opcode() const; | |
450 virtual const Type *Value( PhaseTransform *phase ) const; | |
451 }; | |
452 | |
453 // CatchProjNode controls which exception handler is targetted after a call. | |
454 // It is passed in the bci of the target handler, or no_handler_bci in case | |
455 // the projection doesn't lead to an exception handler. | |
456 class CatchProjNode : public CProjNode { | |
457 virtual uint hash() const; | |
458 virtual uint cmp( const Node &n ) const; | |
459 virtual uint size_of() const { return sizeof(*this); } | |
460 | |
461 private: | |
462 const int _handler_bci; | |
463 | |
464 public: | |
465 enum { | |
466 fall_through_index = 0, // the fall through projection index | |
467 catch_all_index = 1, // the projection index for catch-alls | |
468 no_handler_bci = -1 // the bci for fall through or catch-all projs | |
469 }; | |
470 | |
471 CatchProjNode(Node* catchnode, uint proj_no, int handler_bci) | |
472 : CProjNode(catchnode, proj_no), _handler_bci(handler_bci) { | |
473 init_class_id(Class_CatchProj); | |
474 assert(proj_no != fall_through_index || handler_bci < 0, "fall through case must have bci < 0"); | |
475 } | |
476 | |
477 virtual int Opcode() const; | |
478 virtual Node *Identity( PhaseTransform *phase ); | |
479 virtual const Type *bottom_type() const { return Type::CONTROL; } | |
480 int handler_bci() const { return _handler_bci; } | |
481 bool is_handler_proj() const { return _handler_bci >= 0; } | |
482 #ifndef PRODUCT | |
483 virtual void dump_spec(outputStream *st) const; | |
484 #endif | |
485 }; | |
486 | |
487 | |
488 //---------------------------------CreateExNode-------------------------------- | |
489 // Helper node to create the exception coming back from a call | |
490 class CreateExNode : public TypeNode { | |
491 public: | |
492 CreateExNode(const Type* t, Node* control, Node* i_o) : TypeNode(t, 2) { | |
493 init_req(0, control); | |
494 init_req(1, i_o); | |
495 } | |
496 virtual int Opcode() const; | |
497 virtual Node *Identity( PhaseTransform *phase ); | |
498 virtual bool pinned() const { return true; } | |
499 uint match_edge(uint idx) const { return 0; } | |
500 virtual uint ideal_reg() const { return Op_RegP; } | |
501 }; | |
502 | |
503 //------------------------------NeverBranchNode------------------------------- | |
504 // The never-taken branch. Used to give the appearance of exiting infinite | |
505 // loops to those algorithms that like all paths to be reachable. Encodes | |
506 // empty. | |
507 class NeverBranchNode : public MultiBranchNode { | |
508 public: | |
509 NeverBranchNode( Node *ctrl ) : MultiBranchNode(1) { init_req(0,ctrl); } | |
510 virtual int Opcode() const; | |
511 virtual bool pinned() const { return true; }; | |
512 virtual const Type *bottom_type() const { return TypeTuple::IFBOTH; } | |
127 | 513 virtual const Type *Value( PhaseTransform *phase ) const; |
514 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |
515 virtual int required_outcnt() const { return 2; } | |
0 | 516 virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { } |
517 virtual uint size(PhaseRegAlloc *ra_) const { return 0; } | |
518 #ifndef PRODUCT | |
519 virtual void format( PhaseRegAlloc *, outputStream *st ) const; | |
520 #endif | |
521 }; |