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