Mercurial > hg > graal-compiler
annotate src/share/vm/opto/callnode.cpp @ 8804:91bf0bdae37b
8008217: CDS: Class data sharing limits the malloc heap on Solaris
Summary: In 64bit VM move CDS archive address to 32G on all platforms using new flag SharedBaseAddress. In 32bit VM set CDS archive address to 3Gb on Linux and let other OSs pick the address.
Reviewed-by: kvn, dcubed, zgu, hseigel
author | coleenp |
---|---|
date | Wed, 20 Mar 2013 08:04:54 -0400 |
parents | a7114d3d712e |
children | 6f3fd5150b67 |
rev | line source |
---|---|
0 | 1 /* |
5948
ee138854b3a6
7147744: CTW: assert(false) failed: infinite EA connection graph build
kvn
parents:
4790
diff
changeset
|
2 * Copyright (c) 1997, 2012, 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:
1080
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1080
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:
1080
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "ci/bcEscapeAnalyzer.hpp" | |
27 #include "compiler/oopMap.hpp" | |
7473 | 28 #include "opto/callGenerator.hpp" |
1972 | 29 #include "opto/callnode.hpp" |
30 #include "opto/escape.hpp" | |
31 #include "opto/locknode.hpp" | |
32 #include "opto/machnode.hpp" | |
33 #include "opto/matcher.hpp" | |
34 #include "opto/parse.hpp" | |
35 #include "opto/regalloc.hpp" | |
36 #include "opto/regmask.hpp" | |
37 #include "opto/rootnode.hpp" | |
38 #include "opto/runtime.hpp" | |
39 | |
0 | 40 // Portions of code courtesy of Clifford Click |
41 | |
42 // Optimization - Graph Style | |
43 | |
44 //============================================================================= | |
45 uint StartNode::size_of() const { return sizeof(*this); } | |
46 uint StartNode::cmp( const Node &n ) const | |
47 { return _domain == ((StartNode&)n)._domain; } | |
48 const Type *StartNode::bottom_type() const { return _domain; } | |
49 const Type *StartNode::Value(PhaseTransform *phase) const { return _domain; } | |
50 #ifndef PRODUCT | |
51 void StartNode::dump_spec(outputStream *st) const { st->print(" #"); _domain->dump_on(st);} | |
52 #endif | |
53 | |
54 //------------------------------Ideal------------------------------------------ | |
55 Node *StartNode::Ideal(PhaseGVN *phase, bool can_reshape){ | |
56 return remove_dead_region(phase, can_reshape) ? this : NULL; | |
57 } | |
58 | |
59 //------------------------------calling_convention----------------------------- | |
60 void StartNode::calling_convention( BasicType* sig_bt, VMRegPair *parm_regs, uint argcnt ) const { | |
61 Matcher::calling_convention( sig_bt, parm_regs, argcnt, false ); | |
62 } | |
63 | |
64 //------------------------------Registers-------------------------------------- | |
65 const RegMask &StartNode::in_RegMask(uint) const { | |
66 return RegMask::Empty; | |
67 } | |
68 | |
69 //------------------------------match------------------------------------------ | |
70 // Construct projections for incoming parameters, and their RegMask info | |
71 Node *StartNode::match( const ProjNode *proj, const Matcher *match ) { | |
72 switch (proj->_con) { | |
73 case TypeFunc::Control: | |
74 case TypeFunc::I_O: | |
75 case TypeFunc::Memory: | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
76 return new (match->C) MachProjNode(this,proj->_con,RegMask::Empty,MachProjNode::unmatched_proj); |
0 | 77 case TypeFunc::FramePtr: |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
78 return new (match->C) MachProjNode(this,proj->_con,Matcher::c_frame_ptr_mask, Op_RegP); |
0 | 79 case TypeFunc::ReturnAdr: |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
80 return new (match->C) MachProjNode(this,proj->_con,match->_return_addr_mask,Op_RegP); |
0 | 81 case TypeFunc::Parms: |
82 default: { | |
83 uint parm_num = proj->_con - TypeFunc::Parms; | |
84 const Type *t = _domain->field_at(proj->_con); | |
85 if (t->base() == Type::Half) // 2nd half of Longs and Doubles | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
86 return new (match->C) ConNode(Type::TOP); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
87 uint ideal_reg = t->ideal_reg(); |
0 | 88 RegMask &rm = match->_calling_convention_mask[parm_num]; |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
89 return new (match->C) MachProjNode(this,proj->_con,rm,ideal_reg); |
0 | 90 } |
91 } | |
92 return NULL; | |
93 } | |
94 | |
95 //------------------------------StartOSRNode---------------------------------- | |
96 // The method start node for an on stack replacement adapter | |
97 | |
98 //------------------------------osr_domain----------------------------- | |
99 const TypeTuple *StartOSRNode::osr_domain() { | |
100 const Type **fields = TypeTuple::fields(2); | |
101 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // address of osr buffer | |
102 | |
103 return TypeTuple::make(TypeFunc::Parms+1, fields); | |
104 } | |
105 | |
106 //============================================================================= | |
107 const char * const ParmNode::names[TypeFunc::Parms+1] = { | |
108 "Control", "I_O", "Memory", "FramePtr", "ReturnAdr", "Parms" | |
109 }; | |
110 | |
111 #ifndef PRODUCT | |
112 void ParmNode::dump_spec(outputStream *st) const { | |
113 if( _con < TypeFunc::Parms ) { | |
114 st->print(names[_con]); | |
115 } else { | |
116 st->print("Parm%d: ",_con-TypeFunc::Parms); | |
117 // Verbose and WizardMode dump bottom_type for all nodes | |
118 if( !Verbose && !WizardMode ) bottom_type()->dump_on(st); | |
119 } | |
120 } | |
121 #endif | |
122 | |
123 uint ParmNode::ideal_reg() const { | |
124 switch( _con ) { | |
125 case TypeFunc::Control : // fall through | |
126 case TypeFunc::I_O : // fall through | |
127 case TypeFunc::Memory : return 0; | |
128 case TypeFunc::FramePtr : // fall through | |
129 case TypeFunc::ReturnAdr: return Op_RegP; | |
130 default : assert( _con > TypeFunc::Parms, "" ); | |
131 // fall through | |
132 case TypeFunc::Parms : { | |
133 // Type of argument being passed | |
134 const Type *t = in(0)->as_Start()->_domain->field_at(_con); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
135 return t->ideal_reg(); |
0 | 136 } |
137 } | |
138 ShouldNotReachHere(); | |
139 return 0; | |
140 } | |
141 | |
142 //============================================================================= | |
143 ReturnNode::ReturnNode(uint edges, Node *cntrl, Node *i_o, Node *memory, Node *frameptr, Node *retadr ) : Node(edges) { | |
144 init_req(TypeFunc::Control,cntrl); | |
145 init_req(TypeFunc::I_O,i_o); | |
146 init_req(TypeFunc::Memory,memory); | |
147 init_req(TypeFunc::FramePtr,frameptr); | |
148 init_req(TypeFunc::ReturnAdr,retadr); | |
149 } | |
150 | |
151 Node *ReturnNode::Ideal(PhaseGVN *phase, bool can_reshape){ | |
152 return remove_dead_region(phase, can_reshape) ? this : NULL; | |
153 } | |
154 | |
155 const Type *ReturnNode::Value( PhaseTransform *phase ) const { | |
156 return ( phase->type(in(TypeFunc::Control)) == Type::TOP) | |
157 ? Type::TOP | |
158 : Type::BOTTOM; | |
159 } | |
160 | |
161 // Do we Match on this edge index or not? No edges on return nodes | |
162 uint ReturnNode::match_edge(uint idx) const { | |
163 return 0; | |
164 } | |
165 | |
166 | |
167 #ifndef PRODUCT | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
168 void ReturnNode::dump_req(outputStream *st) const { |
0 | 169 // Dump the required inputs, enclosed in '(' and ')' |
170 uint i; // Exit value of loop | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
171 for (i = 0; i < req(); i++) { // For all required inputs |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
172 if (i == TypeFunc::Parms) st->print("returns"); |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
173 if (in(i)) st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
174 else st->print("_ "); |
0 | 175 } |
176 } | |
177 #endif | |
178 | |
179 //============================================================================= | |
180 RethrowNode::RethrowNode( | |
181 Node* cntrl, | |
182 Node* i_o, | |
183 Node* memory, | |
184 Node* frameptr, | |
185 Node* ret_adr, | |
186 Node* exception | |
187 ) : Node(TypeFunc::Parms + 1) { | |
188 init_req(TypeFunc::Control , cntrl ); | |
189 init_req(TypeFunc::I_O , i_o ); | |
190 init_req(TypeFunc::Memory , memory ); | |
191 init_req(TypeFunc::FramePtr , frameptr ); | |
192 init_req(TypeFunc::ReturnAdr, ret_adr); | |
193 init_req(TypeFunc::Parms , exception); | |
194 } | |
195 | |
196 Node *RethrowNode::Ideal(PhaseGVN *phase, bool can_reshape){ | |
197 return remove_dead_region(phase, can_reshape) ? this : NULL; | |
198 } | |
199 | |
200 const Type *RethrowNode::Value( PhaseTransform *phase ) const { | |
201 return (phase->type(in(TypeFunc::Control)) == Type::TOP) | |
202 ? Type::TOP | |
203 : Type::BOTTOM; | |
204 } | |
205 | |
206 uint RethrowNode::match_edge(uint idx) const { | |
207 return 0; | |
208 } | |
209 | |
210 #ifndef PRODUCT | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
211 void RethrowNode::dump_req(outputStream *st) const { |
0 | 212 // Dump the required inputs, enclosed in '(' and ')' |
213 uint i; // Exit value of loop | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
214 for (i = 0; i < req(); i++) { // For all required inputs |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
215 if (i == TypeFunc::Parms) st->print("exception"); |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
216 if (in(i)) st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
217 else st->print("_ "); |
0 | 218 } |
219 } | |
220 #endif | |
221 | |
222 //============================================================================= | |
223 // Do we Match on this edge index or not? Match only target address & method | |
224 uint TailCallNode::match_edge(uint idx) const { | |
225 return TypeFunc::Parms <= idx && idx <= TypeFunc::Parms+1; | |
226 } | |
227 | |
228 //============================================================================= | |
229 // Do we Match on this edge index or not? Match only target address & oop | |
230 uint TailJumpNode::match_edge(uint idx) const { | |
231 return TypeFunc::Parms <= idx && idx <= TypeFunc::Parms+1; | |
232 } | |
233 | |
234 //============================================================================= | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5948
diff
changeset
|
235 JVMState::JVMState(ciMethod* method, JVMState* caller) : |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5948
diff
changeset
|
236 _method(method) { |
0 | 237 assert(method != NULL, "must be valid call site"); |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
704
diff
changeset
|
238 _reexecute = Reexecute_Undefined; |
0 | 239 debug_only(_bci = -99); // random garbage value |
240 debug_only(_map = (SafePointNode*)-1); | |
241 _caller = caller; | |
242 _depth = 1 + (caller == NULL ? 0 : caller->depth()); | |
243 _locoff = TypeFunc::Parms; | |
244 _stkoff = _locoff + _method->max_locals(); | |
245 _monoff = _stkoff + _method->max_stack(); | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
246 _scloff = _monoff; |
0 | 247 _endoff = _monoff; |
248 _sp = 0; | |
249 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5948
diff
changeset
|
250 JVMState::JVMState(int stack_size) : |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5948
diff
changeset
|
251 _method(NULL) { |
0 | 252 _bci = InvocationEntryBci; |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
704
diff
changeset
|
253 _reexecute = Reexecute_Undefined; |
0 | 254 debug_only(_map = (SafePointNode*)-1); |
255 _caller = NULL; | |
256 _depth = 1; | |
257 _locoff = TypeFunc::Parms; | |
258 _stkoff = _locoff; | |
259 _monoff = _stkoff + stack_size; | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
260 _scloff = _monoff; |
0 | 261 _endoff = _monoff; |
262 _sp = 0; | |
263 } | |
264 | |
265 //--------------------------------of_depth------------------------------------- | |
266 JVMState* JVMState::of_depth(int d) const { | |
267 const JVMState* jvmp = this; | |
268 assert(0 < d && (uint)d <= depth(), "oob"); | |
269 for (int skip = depth() - d; skip > 0; skip--) { | |
270 jvmp = jvmp->caller(); | |
271 } | |
272 assert(jvmp->depth() == (uint)d, "found the right one"); | |
273 return (JVMState*)jvmp; | |
274 } | |
275 | |
276 //-----------------------------same_calls_as----------------------------------- | |
277 bool JVMState::same_calls_as(const JVMState* that) const { | |
278 if (this == that) return true; | |
279 if (this->depth() != that->depth()) return false; | |
280 const JVMState* p = this; | |
281 const JVMState* q = that; | |
282 for (;;) { | |
283 if (p->_method != q->_method) return false; | |
284 if (p->_method == NULL) return true; // bci is irrelevant | |
285 if (p->_bci != q->_bci) return false; | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
704
diff
changeset
|
286 if (p->_reexecute != q->_reexecute) return false; |
0 | 287 p = p->caller(); |
288 q = q->caller(); | |
289 if (p == q) return true; | |
290 assert(p != NULL && q != NULL, "depth check ensures we don't run off end"); | |
291 } | |
292 } | |
293 | |
294 //------------------------------debug_start------------------------------------ | |
295 uint JVMState::debug_start() const { | |
296 debug_only(JVMState* jvmroot = of_depth(1)); | |
297 assert(jvmroot->locoff() <= this->locoff(), "youngest JVMState must be last"); | |
298 return of_depth(1)->locoff(); | |
299 } | |
300 | |
301 //-------------------------------debug_end------------------------------------- | |
302 uint JVMState::debug_end() const { | |
303 debug_only(JVMState* jvmroot = of_depth(1)); | |
304 assert(jvmroot->endoff() <= this->endoff(), "youngest JVMState must be last"); | |
305 return endoff(); | |
306 } | |
307 | |
308 //------------------------------debug_depth------------------------------------ | |
309 uint JVMState::debug_depth() const { | |
310 uint total = 0; | |
311 for (const JVMState* jvmp = this; jvmp != NULL; jvmp = jvmp->caller()) { | |
312 total += jvmp->debug_size(); | |
313 } | |
314 return total; | |
315 } | |
316 | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
317 #ifndef PRODUCT |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
318 |
0 | 319 //------------------------------format_helper---------------------------------- |
320 // Given an allocation (a Chaitin object) and a Node decide if the Node carries | |
321 // any defined value or not. If it does, print out the register or constant. | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
322 static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, const char *msg, uint i, GrowableArray<SafePointScalarObjectNode*> *scobjs ) { |
0 | 323 if (n == NULL) { st->print(" NULL"); return; } |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
324 if (n->is_SafePointScalarObject()) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
325 // Scalar replacement. |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
326 SafePointScalarObjectNode* spobj = n->as_SafePointScalarObject(); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
327 scobjs->append_if_missing(spobj); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
328 int sco_n = scobjs->find(spobj); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
329 assert(sco_n >= 0, ""); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
330 st->print(" %s%d]=#ScObj" INT32_FORMAT, msg, i, sco_n); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
331 return; |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
332 } |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
333 if (regalloc->node_regs_max_index() > 0 && |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
334 OptoReg::is_valid(regalloc->get_reg_first(n))) { // Check for undefined |
0 | 335 char buf[50]; |
336 regalloc->dump_register(n,buf); | |
337 st->print(" %s%d]=%s",msg,i,buf); | |
338 } else { // No register, but might be constant | |
339 const Type *t = n->bottom_type(); | |
340 switch (t->base()) { | |
341 case Type::Int: | |
342 st->print(" %s%d]=#"INT32_FORMAT,msg,i,t->is_int()->get_con()); | |
343 break; | |
344 case Type::AnyPtr: | |
345 assert( t == TypePtr::NULL_PTR, "" ); | |
346 st->print(" %s%d]=#NULL",msg,i); | |
347 break; | |
348 case Type::AryPtr: | |
349 case Type::InstPtr: | |
350 st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->isa_oopptr()->const_oop()); | |
351 break; | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
352 case Type::KlassPtr: |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
353 st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->make_ptr()->isa_klassptr()->klass()); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
354 break; |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
355 case Type::MetadataPtr: |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
356 st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->make_ptr()->isa_metadataptr()->metadata()); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
357 break; |
331
cecd8eb4e0ca
6706829: Compressed Oops: add debug info for narrow oops
kvn
parents:
305
diff
changeset
|
358 case Type::NarrowOop: |
cecd8eb4e0ca
6706829: Compressed Oops: add debug info for narrow oops
kvn
parents:
305
diff
changeset
|
359 st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->make_ptr()->isa_oopptr()->const_oop()); |
cecd8eb4e0ca
6706829: Compressed Oops: add debug info for narrow oops
kvn
parents:
305
diff
changeset
|
360 break; |
0 | 361 case Type::RawPtr: |
362 st->print(" %s%d]=#Raw" INTPTR_FORMAT,msg,i,t->is_rawptr()); | |
363 break; | |
364 case Type::DoubleCon: | |
365 st->print(" %s%d]=#%fD",msg,i,t->is_double_constant()->_d); | |
366 break; | |
367 case Type::FloatCon: | |
368 st->print(" %s%d]=#%fF",msg,i,t->is_float_constant()->_f); | |
369 break; | |
370 case Type::Long: | |
371 st->print(" %s%d]=#"INT64_FORMAT,msg,i,t->is_long()->get_con()); | |
372 break; | |
373 case Type::Half: | |
374 case Type::Top: | |
375 st->print(" %s%d]=_",msg,i); | |
376 break; | |
377 default: ShouldNotReachHere(); | |
378 } | |
379 } | |
380 } | |
381 | |
382 //------------------------------format----------------------------------------- | |
383 void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const { | |
384 st->print(" #"); | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
385 if (_method) { |
0 | 386 _method->print_short_name(st); |
387 st->print(" @ bci:%d ",_bci); | |
388 } else { | |
389 st->print_cr(" runtime stub "); | |
390 return; | |
391 } | |
392 if (n->is_MachSafePoint()) { | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
393 GrowableArray<SafePointScalarObjectNode*> scobjs; |
0 | 394 MachSafePointNode *mcall = n->as_MachSafePoint(); |
395 uint i; | |
396 // Print locals | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
397 for (i = 0; i < (uint)loc_size(); i++) |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
398 format_helper(regalloc, st, mcall->local(this, i), "L[", i, &scobjs); |
0 | 399 // Print stack |
400 for (i = 0; i < (uint)stk_size(); i++) { | |
401 if ((uint)(_stkoff + i) >= mcall->len()) | |
402 st->print(" oob "); | |
403 else | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
404 format_helper(regalloc, st, mcall->stack(this, i), "STK[", i, &scobjs); |
0 | 405 } |
406 for (i = 0; (int)i < nof_monitors(); i++) { | |
407 Node *box = mcall->monitor_box(this, i); | |
408 Node *obj = mcall->monitor_obj(this, i); | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
409 if (regalloc->node_regs_max_index() > 0 && |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
410 OptoReg::is_valid(regalloc->get_reg_first(box))) { |
4777 | 411 box = BoxLockNode::box_node(box); |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
412 format_helper(regalloc, st, box, "MON-BOX[", i, &scobjs); |
0 | 413 } else { |
4777 | 414 OptoReg::Name box_reg = BoxLockNode::reg(box); |
0 | 415 st->print(" MON-BOX%d=%s+%d", |
416 i, | |
417 OptoReg::regname(OptoReg::c_frame_pointer), | |
418 regalloc->reg2offset(box_reg)); | |
419 } | |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
420 const char* obj_msg = "MON-OBJ["; |
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
421 if (EliminateLocks) { |
4777 | 422 if (BoxLockNode::box_node(box)->is_eliminated()) |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
423 obj_msg = "MON-OBJ(LOCK ELIMINATED)["; |
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
424 } |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
425 format_helper(regalloc, st, obj, obj_msg, i, &scobjs); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
426 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
427 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
428 for (i = 0; i < (uint)scobjs.length(); i++) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
429 // Scalar replaced objects. |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
430 st->print_cr(""); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
431 st->print(" # ScObj" INT32_FORMAT " ", i); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
432 SafePointScalarObjectNode* spobj = scobjs.at(i); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
433 ciKlass* cik = spobj->bottom_type()->is_oopptr()->klass(); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
434 assert(cik->is_instance_klass() || |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
435 cik->is_array_klass(), "Not supported allocation."); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
436 ciInstanceKlass *iklass = NULL; |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
437 if (cik->is_instance_klass()) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
438 cik->print_name_on(st); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
439 iklass = cik->as_instance_klass(); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
440 } else if (cik->is_type_array_klass()) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
441 cik->as_array_klass()->base_element_type()->print_name_on(st); |
1040
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
442 st->print("[%d]", spobj->n_fields()); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
443 } else if (cik->is_obj_array_klass()) { |
1040
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
444 ciKlass* cie = cik->as_obj_array_klass()->base_element_klass(); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
445 if (cie->is_instance_klass()) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
446 cie->print_name_on(st); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
447 } else if (cie->is_type_array_klass()) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
448 cie->as_array_klass()->base_element_type()->print_name_on(st); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
449 } else { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
450 ShouldNotReachHere(); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
451 } |
1040
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
452 st->print("[%d]", spobj->n_fields()); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
453 int ndim = cik->as_array_klass()->dimension() - 1; |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
454 while (ndim-- > 0) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
455 st->print("[]"); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
456 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
457 } |
1040
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
931
diff
changeset
|
458 st->print("={"); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
459 uint nf = spobj->n_fields(); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
460 if (nf > 0) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
461 uint first_ind = spobj->first_index(); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
462 Node* fld_node = mcall->in(first_ind); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
463 ciField* cifield; |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
464 if (iklass != NULL) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
465 st->print(" ["); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
466 cifield = iklass->nonstatic_field_at(0); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
467 cifield->print_name_on(st); |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
468 format_helper(regalloc, st, fld_node, ":", 0, &scobjs); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
469 } else { |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
470 format_helper(regalloc, st, fld_node, "[", 0, &scobjs); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
471 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
472 for (uint j = 1; j < nf; j++) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
473 fld_node = mcall->in(first_ind+j); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
474 if (iklass != NULL) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
475 st->print(", ["); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
476 cifield = iklass->nonstatic_field_at(j); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
477 cifield->print_name_on(st); |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
478 format_helper(regalloc, st, fld_node, ":", j, &scobjs); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
479 } else { |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
480 format_helper(regalloc, st, fld_node, ", [", j, &scobjs); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
481 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
482 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
483 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
484 st->print(" }"); |
0 | 485 } |
486 } | |
487 st->print_cr(""); | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
488 if (caller() != NULL) caller()->format(regalloc, n, st); |
0 | 489 } |
490 | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
491 |
0 | 492 void JVMState::dump_spec(outputStream *st) const { |
493 if (_method != NULL) { | |
494 bool printed = false; | |
495 if (!Verbose) { | |
496 // The JVMS dumps make really, really long lines. | |
497 // Take out the most boring parts, which are the package prefixes. | |
498 char buf[500]; | |
499 stringStream namest(buf, sizeof(buf)); | |
500 _method->print_short_name(&namest); | |
501 if (namest.count() < sizeof(buf)) { | |
502 const char* name = namest.base(); | |
503 if (name[0] == ' ') ++name; | |
504 const char* endcn = strchr(name, ':'); // end of class name | |
505 if (endcn == NULL) endcn = strchr(name, '('); | |
506 if (endcn == NULL) endcn = name + strlen(name); | |
507 while (endcn > name && endcn[-1] != '.' && endcn[-1] != '/') | |
508 --endcn; | |
509 st->print(" %s", endcn); | |
510 printed = true; | |
511 } | |
512 } | |
513 if (!printed) | |
514 _method->print_short_name(st); | |
515 st->print(" @ bci:%d",_bci); | |
931
72088be4b386
6873116: Modify reexecute implementation to use pcDesc to record the reexecute bit
cfang
parents:
903
diff
changeset
|
516 if(_reexecute == Reexecute_True) |
72088be4b386
6873116: Modify reexecute implementation to use pcDesc to record the reexecute bit
cfang
parents:
903
diff
changeset
|
517 st->print(" reexecute"); |
0 | 518 } else { |
519 st->print(" runtime stub"); | |
520 } | |
521 if (caller() != NULL) caller()->dump_spec(st); | |
522 } | |
523 | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
524 |
0 | 525 void JVMState::dump_on(outputStream* st) const { |
526 if (_map && !((uintptr_t)_map & 1)) { | |
527 if (_map->len() > _map->req()) { // _map->has_exceptions() | |
528 Node* ex = _map->in(_map->req()); // _map->next_exception() | |
529 // skip the first one; it's already being printed | |
530 while (ex != NULL && ex->len() > ex->req()) { | |
531 ex = ex->in(ex->req()); // ex->next_exception() | |
532 ex->dump(1); | |
533 } | |
534 } | |
535 _map->dump(2); | |
536 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5948
diff
changeset
|
537 st->print("JVMS depth=%d loc=%d stk=%d arg=%d mon=%d scalar=%d end=%d mondepth=%d sp=%d bci=%d reexecute=%s method=", |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5948
diff
changeset
|
538 depth(), locoff(), stkoff(), argoff(), monoff(), scloff(), endoff(), monitor_depth(), sp(), bci(), should_reexecute()?"true":"false"); |
0 | 539 if (_method == NULL) { |
540 st->print_cr("(none)"); | |
541 } else { | |
542 _method->print_name(st); | |
543 st->cr(); | |
544 if (bci() >= 0 && bci() < _method->code_size()) { | |
545 st->print(" bc: "); | |
546 _method->print_codes_on(bci(), bci()+1, st); | |
547 } | |
548 } | |
549 if (caller() != NULL) { | |
550 caller()->dump_on(st); | |
551 } | |
552 } | |
553 | |
554 // Extra way to dump a jvms from the debugger, | |
555 // to avoid a bug with C++ member function calls. | |
556 void dump_jvms(JVMState* jvms) { | |
557 jvms->dump(); | |
558 } | |
559 #endif | |
560 | |
561 //--------------------------clone_shallow-------------------------------------- | |
562 JVMState* JVMState::clone_shallow(Compile* C) const { | |
563 JVMState* n = has_method() ? new (C) JVMState(_method, _caller) : new (C) JVMState(0); | |
564 n->set_bci(_bci); | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
704
diff
changeset
|
565 n->_reexecute = _reexecute; |
0 | 566 n->set_locoff(_locoff); |
567 n->set_stkoff(_stkoff); | |
568 n->set_monoff(_monoff); | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
569 n->set_scloff(_scloff); |
0 | 570 n->set_endoff(_endoff); |
571 n->set_sp(_sp); | |
572 n->set_map(_map); | |
573 return n; | |
574 } | |
575 | |
576 //---------------------------clone_deep---------------------------------------- | |
577 JVMState* JVMState::clone_deep(Compile* C) const { | |
578 JVMState* n = clone_shallow(C); | |
579 for (JVMState* p = n; p->_caller != NULL; p = p->_caller) { | |
580 p->_caller = p->_caller->clone_shallow(C); | |
581 } | |
582 assert(n->depth() == depth(), "sanity"); | |
583 assert(n->debug_depth() == debug_depth(), "sanity"); | |
584 return n; | |
585 } | |
586 | |
587 //============================================================================= | |
588 uint CallNode::cmp( const Node &n ) const | |
589 { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } | |
590 #ifndef PRODUCT | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
591 void CallNode::dump_req(outputStream *st) const { |
0 | 592 // Dump the required inputs, enclosed in '(' and ')' |
593 uint i; // Exit value of loop | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
594 for (i = 0; i < req(); i++) { // For all required inputs |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
595 if (i == TypeFunc::Parms) st->print("("); |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
596 if (in(i)) st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
597 else st->print("_ "); |
0 | 598 } |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
599 st->print(")"); |
0 | 600 } |
601 | |
602 void CallNode::dump_spec(outputStream *st) const { | |
603 st->print(" "); | |
604 tf()->dump_on(st); | |
605 if (_cnt != COUNT_UNKNOWN) st->print(" C=%f",_cnt); | |
606 if (jvms() != NULL) jvms()->dump_spec(st); | |
607 } | |
608 #endif | |
609 | |
610 const Type *CallNode::bottom_type() const { return tf()->range(); } | |
611 const Type *CallNode::Value(PhaseTransform *phase) const { | |
612 if (phase->type(in(0)) == Type::TOP) return Type::TOP; | |
613 return tf()->range(); | |
614 } | |
615 | |
616 //------------------------------calling_convention----------------------------- | |
617 void CallNode::calling_convention( BasicType* sig_bt, VMRegPair *parm_regs, uint argcnt ) const { | |
618 // Use the standard compiler calling convention | |
619 Matcher::calling_convention( sig_bt, parm_regs, argcnt, true ); | |
620 } | |
621 | |
622 | |
623 //------------------------------match------------------------------------------ | |
624 // Construct projections for control, I/O, memory-fields, ..., and | |
625 // return result(s) along with their RegMask info | |
626 Node *CallNode::match( const ProjNode *proj, const Matcher *match ) { | |
627 switch (proj->_con) { | |
628 case TypeFunc::Control: | |
629 case TypeFunc::I_O: | |
630 case TypeFunc::Memory: | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
631 return new (match->C) MachProjNode(this,proj->_con,RegMask::Empty,MachProjNode::unmatched_proj); |
0 | 632 |
633 case TypeFunc::Parms+1: // For LONG & DOUBLE returns | |
634 assert(tf()->_range->field_at(TypeFunc::Parms+1) == Type::HALF, ""); | |
635 // 2nd half of doubles and longs | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
636 return new (match->C) MachProjNode(this,proj->_con, RegMask::Empty, (uint)OptoReg::Bad); |
0 | 637 |
638 case TypeFunc::Parms: { // Normal returns | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
639 uint ideal_reg = tf()->range()->field_at(TypeFunc::Parms)->ideal_reg(); |
0 | 640 OptoRegPair regs = is_CallRuntime() |
641 ? match->c_return_value(ideal_reg,true) // Calls into C runtime | |
642 : match-> return_value(ideal_reg,true); // Calls into compiled Java code | |
643 RegMask rm = RegMask(regs.first()); | |
644 if( OptoReg::is_valid(regs.second()) ) | |
645 rm.Insert( regs.second() ); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
646 return new (match->C) MachProjNode(this,proj->_con,rm,ideal_reg); |
0 | 647 } |
648 | |
649 case TypeFunc::ReturnAdr: | |
650 case TypeFunc::FramePtr: | |
651 default: | |
652 ShouldNotReachHere(); | |
653 } | |
654 return NULL; | |
655 } | |
656 | |
657 // Do we Match on this edge index or not? Match no edges | |
658 uint CallNode::match_edge(uint idx) const { | |
659 return 0; | |
660 } | |
661 | |
65 | 662 // |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
66
diff
changeset
|
663 // Determine whether the call could modify the field of the specified |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
66
diff
changeset
|
664 // instance at the specified offset. |
65 | 665 // |
666 bool CallNode::may_modify(const TypePtr *addr_t, PhaseTransform *phase) { | |
667 const TypeOopPtr *adrInst_t = addr_t->isa_oopptr(); | |
668 | |
247 | 669 // If not an OopPtr or not an instance type, assume the worst. |
670 // Note: currently this method is called only for instance types. | |
671 if (adrInst_t == NULL || !adrInst_t->is_known_instance()) { | |
65 | 672 return true; |
673 } | |
247 | 674 // The instance_id is set only for scalar-replaceable allocations which |
675 // are not passed as arguments according to Escape Analysis. | |
65 | 676 return false; |
677 } | |
678 | |
679 // Does this call have a direct reference to n other than debug information? | |
680 bool CallNode::has_non_debug_use(Node *n) { | |
681 const TypeTuple * d = tf()->domain(); | |
682 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { | |
683 Node *arg = in(i); | |
684 if (arg == n) { | |
685 return true; | |
686 } | |
687 } | |
688 return false; | |
689 } | |
690 | |
691 // Returns the unique CheckCastPP of a call | |
692 // or 'this' if there are several CheckCastPP | |
693 // or returns NULL if there is no one. | |
694 Node *CallNode::result_cast() { | |
695 Node *cast = NULL; | |
696 | |
697 Node *p = proj_out(TypeFunc::Parms); | |
698 if (p == NULL) | |
699 return NULL; | |
700 | |
701 for (DUIterator_Fast imax, i = p->fast_outs(imax); i < imax; i++) { | |
702 Node *use = p->fast_out(i); | |
703 if (use->is_CheckCastPP()) { | |
704 if (cast != NULL) { | |
705 return this; // more than 1 CheckCastPP | |
706 } | |
707 cast = use; | |
708 } | |
709 } | |
710 return cast; | |
711 } | |
712 | |
713 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
714 void CallNode::extract_projections(CallProjections* projs, bool separate_io_proj) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
715 projs->fallthrough_proj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
716 projs->fallthrough_catchproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
717 projs->fallthrough_ioproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
718 projs->catchall_ioproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
719 projs->catchall_catchproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
720 projs->fallthrough_memproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
721 projs->catchall_memproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
722 projs->resproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
723 projs->exobj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
724 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
725 for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
726 ProjNode *pn = fast_out(i)->as_Proj(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
727 if (pn->outcnt() == 0) continue; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
728 switch (pn->_con) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
729 case TypeFunc::Control: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
730 { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
731 // For Control (fallthrough) and I_O (catch_all_index) we have CatchProj -> Catch -> Proj |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
732 projs->fallthrough_proj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
733 DUIterator_Fast jmax, j = pn->fast_outs(jmax); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
734 const Node *cn = pn->fast_out(j); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
735 if (cn->is_Catch()) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
736 ProjNode *cpn = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
737 for (DUIterator_Fast kmax, k = cn->fast_outs(kmax); k < kmax; k++) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
738 cpn = cn->fast_out(k)->as_Proj(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
739 assert(cpn->is_CatchProj(), "must be a CatchProjNode"); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
740 if (cpn->_con == CatchProjNode::fall_through_index) |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
741 projs->fallthrough_catchproj = cpn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
742 else { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
743 assert(cpn->_con == CatchProjNode::catch_all_index, "must be correct index."); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
744 projs->catchall_catchproj = cpn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
745 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
746 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
747 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
748 break; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
749 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
750 case TypeFunc::I_O: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
751 if (pn->_is_io_use) |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
752 projs->catchall_ioproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
753 else |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
754 projs->fallthrough_ioproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
755 for (DUIterator j = pn->outs(); pn->has_out(j); j++) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
756 Node* e = pn->out(j); |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
6804
diff
changeset
|
757 if (e->Opcode() == Op_CreateEx && e->in(0)->is_CatchProj() && e->outcnt() > 0) { |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
758 assert(projs->exobj == NULL, "only one"); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
759 projs->exobj = e; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
760 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
761 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
762 break; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
763 case TypeFunc::Memory: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
764 if (pn->_is_io_use) |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
765 projs->catchall_memproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
766 else |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
767 projs->fallthrough_memproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
768 break; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
769 case TypeFunc::Parms: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
770 projs->resproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
771 break; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
772 default: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
773 assert(false, "unexpected projection from allocation node."); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
774 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
775 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
776 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
777 // The resproj may not exist because the result couuld be ignored |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
778 // and the exception object may not exist if an exception handler |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
779 // swallows the exception but all the other must exist and be found. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
780 assert(projs->fallthrough_proj != NULL, "must be found"); |
7473 | 781 assert(Compile::current()->inlining_incrementally() || projs->fallthrough_catchproj != NULL, "must be found"); |
782 assert(Compile::current()->inlining_incrementally() || projs->fallthrough_memproj != NULL, "must be found"); | |
783 assert(Compile::current()->inlining_incrementally() || projs->fallthrough_ioproj != NULL, "must be found"); | |
784 assert(Compile::current()->inlining_incrementally() || projs->catchall_catchproj != NULL, "must be found"); | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
785 if (separate_io_proj) { |
7473 | 786 assert(Compile::current()->inlining_incrementally() || projs->catchall_memproj != NULL, "must be found"); |
787 assert(Compile::current()->inlining_incrementally() || projs->catchall_ioproj != NULL, "must be found"); | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
788 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
789 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
790 |
7473 | 791 Node *CallNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
792 CallGenerator* cg = generator(); | |
793 if (can_reshape && cg != NULL && cg->is_mh_late_inline() && !cg->already_attempted()) { | |
794 // Check whether this MH handle call becomes a candidate for inlining | |
795 ciMethod* callee = cg->method(); | |
796 vmIntrinsics::ID iid = callee->intrinsic_id(); | |
797 if (iid == vmIntrinsics::_invokeBasic) { | |
798 if (in(TypeFunc::Parms)->Opcode() == Op_ConP) { | |
799 phase->C->prepend_late_inline(cg); | |
800 set_generator(NULL); | |
801 } | |
802 } else { | |
803 assert(callee->has_member_arg(), "wrong type of call?"); | |
804 if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) { | |
805 phase->C->prepend_late_inline(cg); | |
806 set_generator(NULL); | |
807 } | |
808 } | |
809 } | |
810 return SafePointNode::Ideal(phase, can_reshape); | |
811 } | |
812 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
813 |
0 | 814 //============================================================================= |
815 uint CallJavaNode::size_of() const { return sizeof(*this); } | |
816 uint CallJavaNode::cmp( const Node &n ) const { | |
817 CallJavaNode &call = (CallJavaNode&)n; | |
818 return CallNode::cmp(call) && _method == call._method; | |
819 } | |
820 #ifndef PRODUCT | |
821 void CallJavaNode::dump_spec(outputStream *st) const { | |
822 if( _method ) _method->print_short_name(st); | |
823 CallNode::dump_spec(st); | |
824 } | |
825 #endif | |
826 | |
827 //============================================================================= | |
828 uint CallStaticJavaNode::size_of() const { return sizeof(*this); } | |
829 uint CallStaticJavaNode::cmp( const Node &n ) const { | |
830 CallStaticJavaNode &call = (CallStaticJavaNode&)n; | |
831 return CallJavaNode::cmp(call); | |
832 } | |
833 | |
834 //----------------------------uncommon_trap_request---------------------------- | |
835 // If this is an uncommon trap, return the request code, else zero. | |
836 int CallStaticJavaNode::uncommon_trap_request() const { | |
837 if (_name != NULL && !strcmp(_name, "uncommon_trap")) { | |
838 return extract_uncommon_trap_request(this); | |
839 } | |
840 return 0; | |
841 } | |
842 int CallStaticJavaNode::extract_uncommon_trap_request(const Node* call) { | |
843 #ifndef PRODUCT | |
844 if (!(call->req() > TypeFunc::Parms && | |
845 call->in(TypeFunc::Parms) != NULL && | |
846 call->in(TypeFunc::Parms)->is_Con())) { | |
847 assert(_in_dump_cnt != 0, "OK if dumping"); | |
848 tty->print("[bad uncommon trap]"); | |
849 return 0; | |
850 } | |
851 #endif | |
852 return call->in(TypeFunc::Parms)->bottom_type()->is_int()->get_con(); | |
853 } | |
854 | |
855 #ifndef PRODUCT | |
856 void CallStaticJavaNode::dump_spec(outputStream *st) const { | |
857 st->print("# Static "); | |
858 if (_name != NULL) { | |
859 st->print("%s", _name); | |
860 int trap_req = uncommon_trap_request(); | |
861 if (trap_req != 0) { | |
862 char buf[100]; | |
863 st->print("(%s)", | |
864 Deoptimization::format_trap_request(buf, sizeof(buf), | |
865 trap_req)); | |
866 } | |
867 st->print(" "); | |
868 } | |
869 CallJavaNode::dump_spec(st); | |
870 } | |
871 #endif | |
872 | |
873 //============================================================================= | |
874 uint CallDynamicJavaNode::size_of() const { return sizeof(*this); } | |
875 uint CallDynamicJavaNode::cmp( const Node &n ) const { | |
876 CallDynamicJavaNode &call = (CallDynamicJavaNode&)n; | |
877 return CallJavaNode::cmp(call); | |
878 } | |
879 #ifndef PRODUCT | |
880 void CallDynamicJavaNode::dump_spec(outputStream *st) const { | |
881 st->print("# Dynamic "); | |
882 CallJavaNode::dump_spec(st); | |
883 } | |
884 #endif | |
885 | |
886 //============================================================================= | |
887 uint CallRuntimeNode::size_of() const { return sizeof(*this); } | |
888 uint CallRuntimeNode::cmp( const Node &n ) const { | |
889 CallRuntimeNode &call = (CallRuntimeNode&)n; | |
890 return CallNode::cmp(call) && !strcmp(_name,call._name); | |
891 } | |
892 #ifndef PRODUCT | |
893 void CallRuntimeNode::dump_spec(outputStream *st) const { | |
894 st->print("# "); | |
895 st->print(_name); | |
896 CallNode::dump_spec(st); | |
897 } | |
898 #endif | |
899 | |
900 //------------------------------calling_convention----------------------------- | |
901 void CallRuntimeNode::calling_convention( BasicType* sig_bt, VMRegPair *parm_regs, uint argcnt ) const { | |
902 Matcher::c_calling_convention( sig_bt, parm_regs, argcnt ); | |
903 } | |
904 | |
905 //============================================================================= | |
906 //------------------------------calling_convention----------------------------- | |
907 | |
908 | |
909 //============================================================================= | |
910 #ifndef PRODUCT | |
911 void CallLeafNode::dump_spec(outputStream *st) const { | |
912 st->print("# "); | |
913 st->print(_name); | |
914 CallNode::dump_spec(st); | |
915 } | |
916 #endif | |
917 | |
918 //============================================================================= | |
919 | |
920 void SafePointNode::set_local(JVMState* jvms, uint idx, Node *c) { | |
921 assert(verify_jvms(jvms), "jvms must match"); | |
922 int loc = jvms->locoff() + idx; | |
923 if (in(loc)->is_top() && idx > 0 && !c->is_top() ) { | |
924 // If current local idx is top then local idx - 1 could | |
925 // be a long/double that needs to be killed since top could | |
926 // represent the 2nd half ofthe long/double. | |
927 uint ideal = in(loc -1)->ideal_reg(); | |
928 if (ideal == Op_RegD || ideal == Op_RegL) { | |
929 // set other (low index) half to top | |
930 set_req(loc - 1, in(loc)); | |
931 } | |
932 } | |
933 set_req(loc, c); | |
934 } | |
935 | |
936 uint SafePointNode::size_of() const { return sizeof(*this); } | |
937 uint SafePointNode::cmp( const Node &n ) const { | |
938 return (&n == this); // Always fail except on self | |
939 } | |
940 | |
941 //-------------------------set_next_exception---------------------------------- | |
942 void SafePointNode::set_next_exception(SafePointNode* n) { | |
943 assert(n == NULL || n->Opcode() == Op_SafePoint, "correct value for next_exception"); | |
944 if (len() == req()) { | |
945 if (n != NULL) add_prec(n); | |
946 } else { | |
947 set_prec(req(), n); | |
948 } | |
949 } | |
950 | |
951 | |
952 //----------------------------next_exception----------------------------------- | |
953 SafePointNode* SafePointNode::next_exception() const { | |
954 if (len() == req()) { | |
955 return NULL; | |
956 } else { | |
957 Node* n = in(req()); | |
958 assert(n == NULL || n->Opcode() == Op_SafePoint, "no other uses of prec edges"); | |
959 return (SafePointNode*) n; | |
960 } | |
961 } | |
962 | |
963 | |
964 //------------------------------Ideal------------------------------------------ | |
965 // Skip over any collapsed Regions | |
966 Node *SafePointNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
305 | 967 return remove_dead_region(phase, can_reshape) ? this : NULL; |
0 | 968 } |
969 | |
970 //------------------------------Identity--------------------------------------- | |
971 // Remove obviously duplicate safepoints | |
972 Node *SafePointNode::Identity( PhaseTransform *phase ) { | |
973 | |
974 // If you have back to back safepoints, remove one | |
975 if( in(TypeFunc::Control)->is_SafePoint() ) | |
976 return in(TypeFunc::Control); | |
977 | |
978 if( in(0)->is_Proj() ) { | |
979 Node *n0 = in(0)->in(0); | |
980 // Check if he is a call projection (except Leaf Call) | |
981 if( n0->is_Catch() ) { | |
982 n0 = n0->in(0)->in(0); | |
983 assert( n0->is_Call(), "expect a call here" ); | |
984 } | |
985 if( n0->is_Call() && n0->as_Call()->guaranteed_safepoint() ) { | |
986 // Useless Safepoint, so remove it | |
987 return in(TypeFunc::Control); | |
988 } | |
989 } | |
990 | |
991 return this; | |
992 } | |
993 | |
994 //------------------------------Value------------------------------------------ | |
995 const Type *SafePointNode::Value( PhaseTransform *phase ) const { | |
996 if( phase->type(in(0)) == Type::TOP ) return Type::TOP; | |
997 if( phase->eqv( in(0), this ) ) return Type::TOP; // Dead infinite loop | |
998 return Type::CONTROL; | |
999 } | |
1000 | |
1001 #ifndef PRODUCT | |
1002 void SafePointNode::dump_spec(outputStream *st) const { | |
1003 st->print(" SafePoint "); | |
1004 } | |
1005 #endif | |
1006 | |
1007 const RegMask &SafePointNode::in_RegMask(uint idx) const { | |
1008 if( idx < TypeFunc::Parms ) return RegMask::Empty; | |
1009 // Values outside the domain represent debug info | |
1010 return *(Compile::current()->matcher()->idealreg2debugmask[in(idx)->ideal_reg()]); | |
1011 } | |
1012 const RegMask &SafePointNode::out_RegMask() const { | |
1013 return RegMask::Empty; | |
1014 } | |
1015 | |
1016 | |
1017 void SafePointNode::grow_stack(JVMState* jvms, uint grow_by) { | |
1018 assert((int)grow_by > 0, "sanity"); | |
1019 int monoff = jvms->monoff(); | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1020 int scloff = jvms->scloff(); |
0 | 1021 int endoff = jvms->endoff(); |
1022 assert(endoff == (int)req(), "no other states or debug info after me"); | |
1023 Node* top = Compile::current()->top(); | |
1024 for (uint i = 0; i < grow_by; i++) { | |
1025 ins_req(monoff, top); | |
1026 } | |
1027 jvms->set_monoff(monoff + grow_by); | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1028 jvms->set_scloff(scloff + grow_by); |
0 | 1029 jvms->set_endoff(endoff + grow_by); |
1030 } | |
1031 | |
1032 void SafePointNode::push_monitor(const FastLockNode *lock) { | |
1033 // Add a LockNode, which points to both the original BoxLockNode (the | |
1034 // stack space for the monitor) and the Object being locked. | |
1035 const int MonitorEdges = 2; | |
1036 assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct MonitorEdges"); | |
1037 assert(req() == jvms()->endoff(), "correct sizing"); | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1038 int nextmon = jvms()->scloff(); |
0 | 1039 if (GenerateSynchronizationCode) { |
1040 add_req(lock->box_node()); | |
1041 add_req(lock->obj_node()); | |
1042 } else { | |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
1043 Node* top = Compile::current()->top(); |
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
1044 add_req(top); |
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
1045 add_req(top); |
0 | 1046 } |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1047 jvms()->set_scloff(nextmon+MonitorEdges); |
0 | 1048 jvms()->set_endoff(req()); |
1049 } | |
1050 | |
1051 void SafePointNode::pop_monitor() { | |
1052 // Delete last monitor from debug info | |
1053 debug_only(int num_before_pop = jvms()->nof_monitors()); | |
1054 const int MonitorEdges = (1<<JVMState::logMonitorEdges); | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1055 int scloff = jvms()->scloff(); |
0 | 1056 int endoff = jvms()->endoff(); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1057 int new_scloff = scloff - MonitorEdges; |
0 | 1058 int new_endoff = endoff - MonitorEdges; |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1059 jvms()->set_scloff(new_scloff); |
0 | 1060 jvms()->set_endoff(new_endoff); |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1061 while (scloff > new_scloff) del_req(--scloff); |
0 | 1062 assert(jvms()->nof_monitors() == num_before_pop-1, ""); |
1063 } | |
1064 | |
1065 Node *SafePointNode::peek_monitor_box() const { | |
1066 int mon = jvms()->nof_monitors() - 1; | |
1067 assert(mon >= 0, "most have a monitor"); | |
1068 return monitor_box(jvms(), mon); | |
1069 } | |
1070 | |
1071 Node *SafePointNode::peek_monitor_obj() const { | |
1072 int mon = jvms()->nof_monitors() - 1; | |
1073 assert(mon >= 0, "most have a monitor"); | |
1074 return monitor_obj(jvms(), mon); | |
1075 } | |
1076 | |
1077 // Do we Match on this edge index or not? Match no edges | |
1078 uint SafePointNode::match_edge(uint idx) const { | |
1079 if( !needs_polling_address_input() ) | |
1080 return 0; | |
1081 | |
1082 return (TypeFunc::Parms == idx); | |
1083 } | |
1084 | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1085 //============== SafePointScalarObjectNode ============== |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1086 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1087 SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp, |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1088 #ifdef ASSERT |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1089 AllocateNode* alloc, |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1090 #endif |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1091 uint first_index, |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1092 uint n_fields) : |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1093 TypeNode(tp, 1), // 1 control input -- seems required. Get from root. |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1094 #ifdef ASSERT |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1095 _alloc(alloc), |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1096 #endif |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1097 _first_index(first_index), |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1098 _n_fields(n_fields) |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1099 { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1100 init_class_id(Class_SafePointScalarObject); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1101 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1102 |
4115 | 1103 // Do not allow value-numbering for SafePointScalarObject node. |
1104 uint SafePointScalarObjectNode::hash() const { return NO_HASH; } | |
1105 uint SafePointScalarObjectNode::cmp( const Node &n ) const { | |
1106 return (&n == this); // Always fail except on self | |
1107 } | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1108 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1109 uint SafePointScalarObjectNode::ideal_reg() const { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1110 return 0; // No matching to machine instruction |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1111 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1112 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1113 const RegMask &SafePointScalarObjectNode::in_RegMask(uint idx) const { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1114 return *(Compile::current()->matcher()->idealreg2debugmask[in(idx)->ideal_reg()]); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1115 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1116 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1117 const RegMask &SafePointScalarObjectNode::out_RegMask() const { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1118 return RegMask::Empty; |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1119 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1120 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1121 uint SafePointScalarObjectNode::match_edge(uint idx) const { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1122 return 0; |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1123 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1124 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1125 SafePointScalarObjectNode* |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1126 SafePointScalarObjectNode::clone(int jvms_adj, Dict* sosn_map) const { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1127 void* cached = (*sosn_map)[(void*)this]; |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1128 if (cached != NULL) { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1129 return (SafePointScalarObjectNode*)cached; |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1130 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1131 SafePointScalarObjectNode* res = (SafePointScalarObjectNode*)Node::clone(); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1132 res->_first_index += jvms_adj; |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1133 sosn_map->Insert((void*)this, (void*)res); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1134 return res; |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1135 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1136 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1137 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1138 #ifndef PRODUCT |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1139 void SafePointScalarObjectNode::dump_spec(outputStream *st) const { |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1140 st->print(" # fields@[%d..%d]", first_index(), |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1141 first_index() + n_fields() - 1); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1142 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1143 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1144 #endif |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1145 |
0 | 1146 //============================================================================= |
1147 uint AllocateNode::size_of() const { return sizeof(*this); } | |
1148 | |
1149 AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype, | |
1150 Node *ctrl, Node *mem, Node *abio, | |
1151 Node *size, Node *klass_node, Node *initial_test) | |
1152 : CallNode(atype, NULL, TypeRawPtr::BOTTOM) | |
1153 { | |
1154 init_class_id(Class_Allocate); | |
1155 init_flags(Flag_is_macro); | |
39
76256d272075
6667612: (Escape Analysis) disable loop cloning if it has a scalar replaceable allocation
kvn
parents:
0
diff
changeset
|
1156 _is_scalar_replaceable = false; |
0 | 1157 Node *topnode = C->top(); |
1158 | |
1159 init_req( TypeFunc::Control , ctrl ); | |
1160 init_req( TypeFunc::I_O , abio ); | |
1161 init_req( TypeFunc::Memory , mem ); | |
1162 init_req( TypeFunc::ReturnAdr, topnode ); | |
1163 init_req( TypeFunc::FramePtr , topnode ); | |
1164 init_req( AllocSize , size); | |
1165 init_req( KlassNode , klass_node); | |
1166 init_req( InitialTest , initial_test); | |
1167 init_req( ALength , topnode); | |
1168 C->add_macro_node(this); | |
1169 } | |
1170 | |
1171 //============================================================================= | |
1172 uint AllocateArrayNode::size_of() const { return sizeof(*this); } | |
1173 | |
704
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1174 Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1175 if (remove_dead_region(phase, can_reshape)) return this; |
4115 | 1176 // Don't bother trying to transform a dead node |
1177 if (in(0) && in(0)->is_top()) return NULL; | |
704
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1178 |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1179 const Type* type = phase->type(Ideal_length()); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1180 if (type->isa_int() && type->is_int()->_hi < 0) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1181 if (can_reshape) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1182 PhaseIterGVN *igvn = phase->is_IterGVN(); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1183 // Unreachable fall through path (negative array length), |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1184 // the allocation can only throw so disconnect it. |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1185 Node* proj = proj_out(TypeFunc::Control); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1186 Node* catchproj = NULL; |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1187 if (proj != NULL) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1188 for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1189 Node *cn = proj->fast_out(i); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1190 if (cn->is_Catch()) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1191 catchproj = cn->as_Multi()->proj_out(CatchProjNode::fall_through_index); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1192 break; |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1193 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1194 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1195 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1196 if (catchproj != NULL && catchproj->outcnt() > 0 && |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1197 (catchproj->outcnt() > 1 || |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1198 catchproj->unique_out()->Opcode() != Op_Halt)) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1199 assert(catchproj->is_CatchProj(), "must be a CatchProjNode"); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1200 Node* nproj = catchproj->clone(); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1201 igvn->register_new_node_with_optimizer(nproj); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1202 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1203 Node *frame = new (phase->C) ParmNode( phase->C->start(), TypeFunc::FramePtr ); |
704
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1204 frame = phase->transform(frame); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1205 // Halt & Catch Fire |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1206 Node *halt = new (phase->C) HaltNode( nproj, frame ); |
704
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1207 phase->C->root()->add_req(halt); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1208 phase->transform(halt); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1209 |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1210 igvn->replace_node(catchproj, phase->C->top()); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1211 return this; |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1212 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1213 } else { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1214 // Can't correct it during regular GVN so register for IGVN |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1215 phase->C->record_for_igvn(this); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1216 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1217 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1218 return NULL; |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1219 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1220 |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1221 // Retrieve the length from the AllocateArrayNode. Narrow the type with a |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1222 // CastII, if appropriate. If we are not allowed to create new nodes, and |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1223 // a CastII is appropriate, return NULL. |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1224 Node *AllocateArrayNode::make_ideal_length(const TypeOopPtr* oop_type, PhaseTransform *phase, bool allow_new_nodes) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1225 Node *length = in(AllocateNode::ALength); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1226 assert(length != NULL, "length is not null"); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1227 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1228 const TypeInt* length_type = phase->find_int_type(length); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1229 const TypeAryPtr* ary_type = oop_type->isa_aryptr(); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1230 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1231 if (ary_type != NULL && length_type != NULL) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1232 const TypeInt* narrow_length_type = ary_type->narrow_size_type(length_type); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1233 if (narrow_length_type != length_type) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1234 // Assert one of: |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1235 // - the narrow_length is 0 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1236 // - the narrow_length is not wider than length |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1237 assert(narrow_length_type == TypeInt::ZERO || |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1238 (narrow_length_type->_hi <= length_type->_hi && |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1239 narrow_length_type->_lo >= length_type->_lo), |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1240 "narrow type must be narrower than length type"); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1241 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1242 // Return NULL if new nodes are not allowed |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1243 if (!allow_new_nodes) return NULL; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1244 // Create a cast which is control dependent on the initialization to |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1245 // propagate the fact that the array length must be positive. |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1246 length = new (phase->C) CastIINode(length, narrow_length_type); |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1247 length->set_req(0, initialization()->proj_out(0)); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1248 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1249 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1250 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1251 return length; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1252 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1253 |
0 | 1254 //============================================================================= |
1255 uint LockNode::size_of() const { return sizeof(*this); } | |
1256 | |
1257 // Redundant lock elimination | |
1258 // | |
1259 // There are various patterns of locking where we release and | |
1260 // immediately reacquire a lock in a piece of code where no operations | |
1261 // occur in between that would be observable. In those cases we can | |
1262 // skip releasing and reacquiring the lock without violating any | |
1263 // fairness requirements. Doing this around a loop could cause a lock | |
1264 // to be held for a very long time so we concentrate on non-looping | |
1265 // control flow. We also require that the operations are fully | |
1266 // redundant meaning that we don't introduce new lock operations on | |
1267 // some paths so to be able to eliminate it on others ala PRE. This | |
1268 // would probably require some more extensive graph manipulation to | |
1269 // guarantee that the memory edges were all handled correctly. | |
1270 // | |
1271 // Assuming p is a simple predicate which can't trap in any way and s | |
1272 // is a synchronized method consider this code: | |
1273 // | |
1274 // s(); | |
1275 // if (p) | |
1276 // s(); | |
1277 // else | |
1278 // s(); | |
1279 // s(); | |
1280 // | |
1281 // 1. The unlocks of the first call to s can be eliminated if the | |
1282 // locks inside the then and else branches are eliminated. | |
1283 // | |
1284 // 2. The unlocks of the then and else branches can be eliminated if | |
1285 // the lock of the final call to s is eliminated. | |
1286 // | |
1287 // Either of these cases subsumes the simple case of sequential control flow | |
1288 // | |
1289 // Addtionally we can eliminate versions without the else case: | |
1290 // | |
1291 // s(); | |
1292 // if (p) | |
1293 // s(); | |
1294 // s(); | |
1295 // | |
1296 // 3. In this case we eliminate the unlock of the first s, the lock | |
1297 // and unlock in the then case and the lock in the final s. | |
1298 // | |
1299 // Note also that in all these cases the then/else pieces don't have | |
1300 // to be trivial as long as they begin and end with synchronization | |
1301 // operations. | |
1302 // | |
1303 // s(); | |
1304 // if (p) | |
1305 // s(); | |
1306 // f(); | |
1307 // s(); | |
1308 // s(); | |
1309 // | |
1310 // The code will work properly for this case, leaving in the unlock | |
1311 // before the call to f and the relock after it. | |
1312 // | |
1313 // A potentially interesting case which isn't handled here is when the | |
1314 // locking is partially redundant. | |
1315 // | |
1316 // s(); | |
1317 // if (p) | |
1318 // s(); | |
1319 // | |
1320 // This could be eliminated putting unlocking on the else case and | |
1321 // eliminating the first unlock and the lock in the then side. | |
1322 // Alternatively the unlock could be moved out of the then side so it | |
1323 // was after the merge and the first unlock and second lock | |
1324 // eliminated. This might require less manipulation of the memory | |
1325 // state to get correct. | |
1326 // | |
1327 // Additionally we might allow work between a unlock and lock before | |
1328 // giving up eliminating the locks. The current code disallows any | |
1329 // conditional control flow between these operations. A formulation | |
1330 // similar to partial redundancy elimination computing the | |
1331 // availability of unlocking and the anticipatability of locking at a | |
1332 // program point would allow detection of fully redundant locking with | |
1333 // some amount of work in between. I'm not sure how often I really | |
1334 // think that would occur though. Most of the cases I've seen | |
1335 // indicate it's likely non-trivial work would occur in between. | |
1336 // There may be other more complicated constructs where we could | |
1337 // eliminate locking but I haven't seen any others appear as hot or | |
1338 // interesting. | |
1339 // | |
1340 // Locking and unlocking have a canonical form in ideal that looks | |
1341 // roughly like this: | |
1342 // | |
1343 // <obj> | |
1344 // | \\------+ | |
1345 // | \ \ | |
1346 // | BoxLock \ | |
1347 // | | | \ | |
1348 // | | \ \ | |
1349 // | | FastLock | |
1350 // | | / | |
1351 // | | / | |
1352 // | | | | |
1353 // | |
1354 // Lock | |
1355 // | | |
1356 // Proj #0 | |
1357 // | | |
1358 // MembarAcquire | |
1359 // | | |
1360 // Proj #0 | |
1361 // | |
1362 // MembarRelease | |
1363 // | | |
1364 // Proj #0 | |
1365 // | | |
1366 // Unlock | |
1367 // | | |
1368 // Proj #0 | |
1369 // | |
1370 // | |
1371 // This code proceeds by processing Lock nodes during PhaseIterGVN | |
1372 // and searching back through its control for the proper code | |
1373 // patterns. Once it finds a set of lock and unlock operations to | |
1374 // eliminate they are marked as eliminatable which causes the | |
1375 // expansion of the Lock and Unlock macro nodes to make the operation a NOP | |
1376 // | |
1377 //============================================================================= | |
1378 | |
1379 // | |
1380 // Utility function to skip over uninteresting control nodes. Nodes skipped are: | |
1381 // - copy regions. (These may not have been optimized away yet.) | |
1382 // - eliminated locking nodes | |
1383 // | |
1384 static Node *next_control(Node *ctrl) { | |
1385 if (ctrl == NULL) | |
1386 return NULL; | |
1387 while (1) { | |
1388 if (ctrl->is_Region()) { | |
1389 RegionNode *r = ctrl->as_Region(); | |
1390 Node *n = r->is_copy(); | |
1391 if (n == NULL) | |
1392 break; // hit a region, return it | |
1393 else | |
1394 ctrl = n; | |
1395 } else if (ctrl->is_Proj()) { | |
1396 Node *in0 = ctrl->in(0); | |
1397 if (in0->is_AbstractLock() && in0->as_AbstractLock()->is_eliminated()) { | |
1398 ctrl = in0->in(0); | |
1399 } else { | |
1400 break; | |
1401 } | |
1402 } else { | |
1403 break; // found an interesting control | |
1404 } | |
1405 } | |
1406 return ctrl; | |
1407 } | |
1408 // | |
1409 // Given a control, see if it's the control projection of an Unlock which | |
1410 // operating on the same object as lock. | |
1411 // | |
1412 bool AbstractLockNode::find_matching_unlock(const Node* ctrl, LockNode* lock, | |
1413 GrowableArray<AbstractLockNode*> &lock_ops) { | |
1414 ProjNode *ctrl_proj = (ctrl->is_Proj()) ? ctrl->as_Proj() : NULL; | |
1415 if (ctrl_proj != NULL && ctrl_proj->_con == TypeFunc::Control) { | |
1416 Node *n = ctrl_proj->in(0); | |
1417 if (n != NULL && n->is_Unlock()) { | |
1418 UnlockNode *unlock = n->as_Unlock(); | |
4778 | 1419 if (lock->obj_node()->eqv_uncast(unlock->obj_node()) && |
4777 | 1420 BoxLockNode::same_slot(lock->box_node(), unlock->box_node()) && |
1421 !unlock->is_eliminated()) { | |
0 | 1422 lock_ops.append(unlock); |
1423 return true; | |
1424 } | |
1425 } | |
1426 } | |
1427 return false; | |
1428 } | |
1429 | |
1430 // | |
1431 // Find the lock matching an unlock. Returns null if a safepoint | |
1432 // or complicated control is encountered first. | |
1433 LockNode *AbstractLockNode::find_matching_lock(UnlockNode* unlock) { | |
1434 LockNode *lock_result = NULL; | |
1435 // find the matching lock, or an intervening safepoint | |
1436 Node *ctrl = next_control(unlock->in(0)); | |
1437 while (1) { | |
1438 assert(ctrl != NULL, "invalid control graph"); | |
1439 assert(!ctrl->is_Start(), "missing lock for unlock"); | |
1440 if (ctrl->is_top()) break; // dead control path | |
1441 if (ctrl->is_Proj()) ctrl = ctrl->in(0); | |
1442 if (ctrl->is_SafePoint()) { | |
1443 break; // found a safepoint (may be the lock we are searching for) | |
1444 } else if (ctrl->is_Region()) { | |
1445 // Check for a simple diamond pattern. Punt on anything more complicated | |
1446 if (ctrl->req() == 3 && ctrl->in(1) != NULL && ctrl->in(2) != NULL) { | |
1447 Node *in1 = next_control(ctrl->in(1)); | |
1448 Node *in2 = next_control(ctrl->in(2)); | |
1449 if (((in1->is_IfTrue() && in2->is_IfFalse()) || | |
1450 (in2->is_IfTrue() && in1->is_IfFalse())) && (in1->in(0) == in2->in(0))) { | |
1451 ctrl = next_control(in1->in(0)->in(0)); | |
1452 } else { | |
1453 break; | |
1454 } | |
1455 } else { | |
1456 break; | |
1457 } | |
1458 } else { | |
1459 ctrl = next_control(ctrl->in(0)); // keep searching | |
1460 } | |
1461 } | |
1462 if (ctrl->is_Lock()) { | |
1463 LockNode *lock = ctrl->as_Lock(); | |
4778 | 1464 if (lock->obj_node()->eqv_uncast(unlock->obj_node()) && |
4777 | 1465 BoxLockNode::same_slot(lock->box_node(), unlock->box_node())) { |
0 | 1466 lock_result = lock; |
1467 } | |
1468 } | |
1469 return lock_result; | |
1470 } | |
1471 | |
1472 // This code corresponds to case 3 above. | |
1473 | |
1474 bool AbstractLockNode::find_lock_and_unlock_through_if(Node* node, LockNode* lock, | |
1475 GrowableArray<AbstractLockNode*> &lock_ops) { | |
1476 Node* if_node = node->in(0); | |
1477 bool if_true = node->is_IfTrue(); | |
1478 | |
1479 if (if_node->is_If() && if_node->outcnt() == 2 && (if_true || node->is_IfFalse())) { | |
1480 Node *lock_ctrl = next_control(if_node->in(0)); | |
1481 if (find_matching_unlock(lock_ctrl, lock, lock_ops)) { | |
1482 Node* lock1_node = NULL; | |
1483 ProjNode* proj = if_node->as_If()->proj_out(!if_true); | |
1484 if (if_true) { | |
1485 if (proj->is_IfFalse() && proj->outcnt() == 1) { | |
1486 lock1_node = proj->unique_out(); | |
1487 } | |
1488 } else { | |
1489 if (proj->is_IfTrue() && proj->outcnt() == 1) { | |
1490 lock1_node = proj->unique_out(); | |
1491 } | |
1492 } | |
1493 if (lock1_node != NULL && lock1_node->is_Lock()) { | |
1494 LockNode *lock1 = lock1_node->as_Lock(); | |
4778 | 1495 if (lock->obj_node()->eqv_uncast(lock1->obj_node()) && |
4777 | 1496 BoxLockNode::same_slot(lock->box_node(), lock1->box_node()) && |
1497 !lock1->is_eliminated()) { | |
0 | 1498 lock_ops.append(lock1); |
1499 return true; | |
1500 } | |
1501 } | |
1502 } | |
1503 } | |
1504 | |
1505 lock_ops.trunc_to(0); | |
1506 return false; | |
1507 } | |
1508 | |
1509 bool AbstractLockNode::find_unlocks_for_region(const RegionNode* region, LockNode* lock, | |
1510 GrowableArray<AbstractLockNode*> &lock_ops) { | |
1511 // check each control merging at this point for a matching unlock. | |
1512 // in(0) should be self edge so skip it. | |
1513 for (int i = 1; i < (int)region->req(); i++) { | |
1514 Node *in_node = next_control(region->in(i)); | |
1515 if (in_node != NULL) { | |
1516 if (find_matching_unlock(in_node, lock, lock_ops)) { | |
1517 // found a match so keep on checking. | |
1518 continue; | |
1519 } else if (find_lock_and_unlock_through_if(in_node, lock, lock_ops)) { | |
1520 continue; | |
1521 } | |
1522 | |
1523 // If we fall through to here then it was some kind of node we | |
1524 // don't understand or there wasn't a matching unlock, so give | |
1525 // up trying to merge locks. | |
1526 lock_ops.trunc_to(0); | |
1527 return false; | |
1528 } | |
1529 } | |
1530 return true; | |
1531 | |
1532 } | |
1533 | |
1534 #ifndef PRODUCT | |
1535 // | |
1536 // Create a counter which counts the number of times this lock is acquired | |
1537 // | |
1538 void AbstractLockNode::create_lock_counter(JVMState* state) { | |
1539 _counter = OptoRuntime::new_named_counter(state, NamedCounter::LockCounter); | |
1540 } | |
1541 | |
4777 | 1542 void AbstractLockNode::set_eliminated_lock_counter() { |
0 | 1543 if (_counter) { |
1544 // Update the counter to indicate that this lock was eliminated. | |
1545 // The counter update code will stay around even though the | |
1546 // optimizer will eliminate the lock operation itself. | |
1547 _counter->set_tag(NamedCounter::EliminatedLockCounter); | |
1548 } | |
4777 | 1549 } |
0 | 1550 #endif |
1551 | |
1552 //============================================================================= | |
1553 Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
1554 | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1555 // perform any generic optimizations first (returns 'this' or NULL) |
0 | 1556 Node *result = SafePointNode::Ideal(phase, can_reshape); |
4115 | 1557 if (result != NULL) return result; |
1558 // Don't bother trying to transform a dead node | |
1559 if (in(0) && in(0)->is_top()) return NULL; | |
0 | 1560 |
1561 // Now see if we can optimize away this lock. We don't actually | |
1562 // remove the locking here, we simply set the _eliminate flag which | |
1563 // prevents macro expansion from expanding the lock. Since we don't | |
1564 // modify the graph, the value returned from this function is the | |
1565 // one computed above. | |
4777 | 1566 if (can_reshape && EliminateLocks && !is_non_esc_obj()) { |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1567 // |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1568 // If we are locking an unescaped object, the lock/unlock is unnecessary |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1569 // |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
1570 ConnectionGraph *cgr = phase->C->congraph(); |
5948
ee138854b3a6
7147744: CTW: assert(false) failed: infinite EA connection graph build
kvn
parents:
4790
diff
changeset
|
1571 if (cgr != NULL && cgr->not_global_escape(obj_node())) { |
4777 | 1572 assert(!is_eliminated() || is_coarsened(), "sanity"); |
1573 // The lock could be marked eliminated by lock coarsening | |
1574 // code during first IGVN before EA. Replace coarsened flag | |
1575 // to eliminate all associated locks/unlocks. | |
1576 this->set_non_esc_obj(); | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1577 return result; |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1578 } |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1579 |
0 | 1580 // |
1581 // Try lock coarsening | |
1582 // | |
1583 PhaseIterGVN* iter = phase->is_IterGVN(); | |
4115 | 1584 if (iter != NULL && !is_eliminated()) { |
0 | 1585 |
1586 GrowableArray<AbstractLockNode*> lock_ops; | |
1587 | |
1588 Node *ctrl = next_control(in(0)); | |
1589 | |
1590 // now search back for a matching Unlock | |
1591 if (find_matching_unlock(ctrl, this, lock_ops)) { | |
1592 // found an unlock directly preceding this lock. This is the | |
1593 // case of single unlock directly control dependent on a | |
1594 // single lock which is the trivial version of case 1 or 2. | |
1595 } else if (ctrl->is_Region() ) { | |
1596 if (find_unlocks_for_region(ctrl->as_Region(), this, lock_ops)) { | |
1597 // found lock preceded by multiple unlocks along all paths | |
1598 // joining at this point which is case 3 in description above. | |
1599 } | |
1600 } else { | |
1601 // see if this lock comes from either half of an if and the | |
1602 // predecessors merges unlocks and the other half of the if | |
1603 // performs a lock. | |
1604 if (find_lock_and_unlock_through_if(ctrl, this, lock_ops)) { | |
1605 // found unlock splitting to an if with locks on both branches. | |
1606 } | |
1607 } | |
1608 | |
1609 if (lock_ops.length() > 0) { | |
1610 // add ourselves to the list of locks to be eliminated. | |
1611 lock_ops.append(this); | |
1612 | |
1613 #ifndef PRODUCT | |
1614 if (PrintEliminateLocks) { | |
1615 int locks = 0; | |
1616 int unlocks = 0; | |
1617 for (int i = 0; i < lock_ops.length(); i++) { | |
1618 AbstractLockNode* lock = lock_ops.at(i); | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1619 if (lock->Opcode() == Op_Lock) |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1620 locks++; |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1621 else |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1622 unlocks++; |
0 | 1623 if (Verbose) { |
1624 lock->dump(1); | |
1625 } | |
1626 } | |
1627 tty->print_cr("***Eliminated %d unlocks and %d locks", unlocks, locks); | |
1628 } | |
1629 #endif | |
1630 | |
1631 // for each of the identified locks, mark them | |
1632 // as eliminatable | |
1633 for (int i = 0; i < lock_ops.length(); i++) { | |
1634 AbstractLockNode* lock = lock_ops.at(i); | |
1635 | |
4777 | 1636 // Mark it eliminated by coarsening and update any counters |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
1637 lock->set_coarsened(); |
0 | 1638 } |
4115 | 1639 } else if (ctrl->is_Region() && |
0 | 1640 iter->_worklist.member(ctrl)) { |
1641 // We weren't able to find any opportunities but the region this | |
1642 // lock is control dependent on hasn't been processed yet so put | |
1643 // this lock back on the worklist so we can check again once any | |
1644 // region simplification has occurred. | |
1645 iter->_worklist.push(this); | |
1646 } | |
1647 } | |
1648 } | |
1649 | |
1650 return result; | |
1651 } | |
1652 | |
1653 //============================================================================= | |
4777 | 1654 bool LockNode::is_nested_lock_region() { |
4790
b0ff910edfc9
7128355: assert(!nocreate) failed: Cannot build a phi for a block already parsed
kvn
parents:
4778
diff
changeset
|
1655 BoxLockNode* box = box_node()->as_BoxLock(); |
b0ff910edfc9
7128355: assert(!nocreate) failed: Cannot build a phi for a block already parsed
kvn
parents:
4778
diff
changeset
|
1656 int stk_slot = box->stack_slot(); |
b0ff910edfc9
7128355: assert(!nocreate) failed: Cannot build a phi for a block already parsed
kvn
parents:
4778
diff
changeset
|
1657 if (stk_slot <= 0) |
4777 | 1658 return false; // External lock or it is not Box (Phi node). |
1659 | |
1660 // Ignore complex cases: merged locks or multiple locks. | |
1661 Node* obj = obj_node(); | |
1662 LockNode* unique_lock = NULL; | |
4790
b0ff910edfc9
7128355: assert(!nocreate) failed: Cannot build a phi for a block already parsed
kvn
parents:
4778
diff
changeset
|
1663 if (!box->is_simple_lock_region(&unique_lock, obj) || |
4777 | 1664 (unique_lock != this)) { |
1665 return false; | |
1666 } | |
1667 | |
1668 // Look for external lock for the same object. | |
1669 SafePointNode* sfn = this->as_SafePoint(); | |
1670 JVMState* youngest_jvms = sfn->jvms(); | |
1671 int max_depth = youngest_jvms->depth(); | |
1672 for (int depth = 1; depth <= max_depth; depth++) { | |
1673 JVMState* jvms = youngest_jvms->of_depth(depth); | |
1674 int num_mon = jvms->nof_monitors(); | |
1675 // Loop over monitors | |
1676 for (int idx = 0; idx < num_mon; idx++) { | |
1677 Node* obj_node = sfn->monitor_obj(jvms, idx); | |
4790
b0ff910edfc9
7128355: assert(!nocreate) failed: Cannot build a phi for a block already parsed
kvn
parents:
4778
diff
changeset
|
1678 BoxLockNode* box_node = sfn->monitor_box(jvms, idx)->as_BoxLock(); |
4778 | 1679 if ((box_node->stack_slot() < stk_slot) && obj_node->eqv_uncast(obj)) { |
4777 | 1680 return true; |
1681 } | |
1682 } | |
1683 } | |
1684 return false; | |
1685 } | |
1686 | |
1687 //============================================================================= | |
0 | 1688 uint UnlockNode::size_of() const { return sizeof(*this); } |
1689 | |
1690 //============================================================================= | |
1691 Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
1692 | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1693 // perform any generic optimizations first (returns 'this' or NULL) |
4115 | 1694 Node *result = SafePointNode::Ideal(phase, can_reshape); |
1695 if (result != NULL) return result; | |
1696 // Don't bother trying to transform a dead node | |
1697 if (in(0) && in(0)->is_top()) return NULL; | |
0 | 1698 |
1699 // Now see if we can optimize away this unlock. We don't actually | |
1700 // remove the unlocking here, we simply set the _eliminate flag which | |
1701 // prevents macro expansion from expanding the unlock. Since we don't | |
1702 // modify the graph, the value returned from this function is the | |
1703 // one computed above. | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1704 // Escape state is defined after Parse phase. |
4777 | 1705 if (can_reshape && EliminateLocks && !is_non_esc_obj()) { |
0 | 1706 // |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1707 // If we are unlocking an unescaped object, the lock/unlock is unnecessary. |
0 | 1708 // |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
1709 ConnectionGraph *cgr = phase->C->congraph(); |
5948
ee138854b3a6
7147744: CTW: assert(false) failed: infinite EA connection graph build
kvn
parents:
4790
diff
changeset
|
1710 if (cgr != NULL && cgr->not_global_escape(obj_node())) { |
4777 | 1711 assert(!is_eliminated() || is_coarsened(), "sanity"); |
1712 // The lock could be marked eliminated by lock coarsening | |
1713 // code during first IGVN before EA. Replace coarsened flag | |
1714 // to eliminate all associated locks/unlocks. | |
1715 this->set_non_esc_obj(); | |
0 | 1716 } |
1717 } | |
1718 return result; | |
1719 } |