Mercurial > hg > truffle
annotate src/share/vm/opto/callnode.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 55fb97c4c58d |
children | abec000618bf |
rev | line source |
---|---|
0 | 1 /* |
17467
55fb97c4c58d
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents:
12158
diff
changeset
|
2 * Copyright (c) 1997, 2013, 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) { |
12158
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
461 uint first_ind = spobj->first_index(mcall->jvms()); |
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
|
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 { |
10278 | 526 bool print_map = _map && !((uintptr_t)_map & 1) && |
527 ((caller() == NULL) || (caller()->map() != _map)); | |
528 if (print_map) { | |
0 | 529 if (_map->len() > _map->req()) { // _map->has_exceptions() |
530 Node* ex = _map->in(_map->req()); // _map->next_exception() | |
531 // skip the first one; it's already being printed | |
532 while (ex != NULL && ex->len() > ex->req()) { | |
533 ex = ex->in(ex->req()); // ex->next_exception() | |
534 ex->dump(1); | |
535 } | |
536 } | |
10278 | 537 _map->dump(Verbose ? 2 : 1); |
538 } | |
539 if (caller() != NULL) { | |
540 caller()->dump_on(st); | |
0 | 541 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5948
diff
changeset
|
542 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
|
543 depth(), locoff(), stkoff(), argoff(), monoff(), scloff(), endoff(), monitor_depth(), sp(), bci(), should_reexecute()?"true":"false"); |
0 | 544 if (_method == NULL) { |
545 st->print_cr("(none)"); | |
546 } else { | |
547 _method->print_name(st); | |
548 st->cr(); | |
549 if (bci() >= 0 && bci() < _method->code_size()) { | |
550 st->print(" bc: "); | |
551 _method->print_codes_on(bci(), bci()+1, st); | |
552 } | |
553 } | |
554 } | |
555 | |
556 // Extra way to dump a jvms from the debugger, | |
557 // to avoid a bug with C++ member function calls. | |
558 void dump_jvms(JVMState* jvms) { | |
559 jvms->dump(); | |
560 } | |
561 #endif | |
562 | |
563 //--------------------------clone_shallow-------------------------------------- | |
564 JVMState* JVMState::clone_shallow(Compile* C) const { | |
565 JVMState* n = has_method() ? new (C) JVMState(_method, _caller) : new (C) JVMState(0); | |
566 n->set_bci(_bci); | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
704
diff
changeset
|
567 n->_reexecute = _reexecute; |
0 | 568 n->set_locoff(_locoff); |
569 n->set_stkoff(_stkoff); | |
570 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
|
571 n->set_scloff(_scloff); |
0 | 572 n->set_endoff(_endoff); |
573 n->set_sp(_sp); | |
574 n->set_map(_map); | |
575 return n; | |
576 } | |
577 | |
578 //---------------------------clone_deep---------------------------------------- | |
579 JVMState* JVMState::clone_deep(Compile* C) const { | |
580 JVMState* n = clone_shallow(C); | |
581 for (JVMState* p = n; p->_caller != NULL; p = p->_caller) { | |
582 p->_caller = p->_caller->clone_shallow(C); | |
583 } | |
584 assert(n->depth() == depth(), "sanity"); | |
585 assert(n->debug_depth() == debug_depth(), "sanity"); | |
586 return n; | |
587 } | |
588 | |
10278 | 589 /** |
590 * Reset map for all callers | |
591 */ | |
592 void JVMState::set_map_deep(SafePointNode* map) { | |
593 for (JVMState* p = this; p->_caller != NULL; p = p->_caller) { | |
594 p->set_map(map); | |
595 } | |
596 } | |
597 | |
0 | 598 //============================================================================= |
599 uint CallNode::cmp( const Node &n ) const | |
600 { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } | |
601 #ifndef PRODUCT | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
602 void CallNode::dump_req(outputStream *st) const { |
0 | 603 // Dump the required inputs, enclosed in '(' and ')' |
604 uint i; // Exit value of loop | |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
605 for (i = 0; i < req(); i++) { // For all required inputs |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
606 if (i == TypeFunc::Parms) st->print("("); |
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
607 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
|
608 else st->print("_ "); |
0 | 609 } |
7636
a7114d3d712e
8005055: pass outputStream to more opto debug routines
kvn
parents:
7473
diff
changeset
|
610 st->print(")"); |
0 | 611 } |
612 | |
613 void CallNode::dump_spec(outputStream *st) const { | |
614 st->print(" "); | |
615 tf()->dump_on(st); | |
616 if (_cnt != COUNT_UNKNOWN) st->print(" C=%f",_cnt); | |
617 if (jvms() != NULL) jvms()->dump_spec(st); | |
618 } | |
619 #endif | |
620 | |
621 const Type *CallNode::bottom_type() const { return tf()->range(); } | |
622 const Type *CallNode::Value(PhaseTransform *phase) const { | |
623 if (phase->type(in(0)) == Type::TOP) return Type::TOP; | |
624 return tf()->range(); | |
625 } | |
626 | |
627 //------------------------------calling_convention----------------------------- | |
628 void CallNode::calling_convention( BasicType* sig_bt, VMRegPair *parm_regs, uint argcnt ) const { | |
629 // Use the standard compiler calling convention | |
630 Matcher::calling_convention( sig_bt, parm_regs, argcnt, true ); | |
631 } | |
632 | |
633 | |
634 //------------------------------match------------------------------------------ | |
635 // Construct projections for control, I/O, memory-fields, ..., and | |
636 // return result(s) along with their RegMask info | |
637 Node *CallNode::match( const ProjNode *proj, const Matcher *match ) { | |
638 switch (proj->_con) { | |
639 case TypeFunc::Control: | |
640 case TypeFunc::I_O: | |
641 case TypeFunc::Memory: | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
642 return new (match->C) MachProjNode(this,proj->_con,RegMask::Empty,MachProjNode::unmatched_proj); |
0 | 643 |
644 case TypeFunc::Parms+1: // For LONG & DOUBLE returns | |
645 assert(tf()->_range->field_at(TypeFunc::Parms+1) == Type::HALF, ""); | |
646 // 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
|
647 return new (match->C) MachProjNode(this,proj->_con, RegMask::Empty, (uint)OptoReg::Bad); |
0 | 648 |
649 case TypeFunc::Parms: { // Normal returns | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
650 uint ideal_reg = tf()->range()->field_at(TypeFunc::Parms)->ideal_reg(); |
0 | 651 OptoRegPair regs = is_CallRuntime() |
652 ? match->c_return_value(ideal_reg,true) // Calls into C runtime | |
653 : match-> return_value(ideal_reg,true); // Calls into compiled Java code | |
654 RegMask rm = RegMask(regs.first()); | |
655 if( OptoReg::is_valid(regs.second()) ) | |
656 rm.Insert( regs.second() ); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
657 return new (match->C) MachProjNode(this,proj->_con,rm,ideal_reg); |
0 | 658 } |
659 | |
660 case TypeFunc::ReturnAdr: | |
661 case TypeFunc::FramePtr: | |
662 default: | |
663 ShouldNotReachHere(); | |
664 } | |
665 return NULL; | |
666 } | |
667 | |
668 // Do we Match on this edge index or not? Match no edges | |
669 uint CallNode::match_edge(uint idx) const { | |
670 return 0; | |
671 } | |
672 | |
65 | 673 // |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
66
diff
changeset
|
674 // 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
|
675 // instance at the specified offset. |
65 | 676 // |
10278 | 677 bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) { |
678 assert((t_oop != NULL), "sanity"); | |
679 if (t_oop->is_known_instance()) { | |
680 // The instance_id is set only for scalar-replaceable allocations which | |
681 // are not passed as arguments according to Escape Analysis. | |
682 return false; | |
65 | 683 } |
10278 | 684 if (t_oop->is_ptr_to_boxed_value()) { |
685 ciKlass* boxing_klass = t_oop->klass(); | |
686 if (is_CallStaticJava() && as_CallStaticJava()->is_boxing_method()) { | |
687 // Skip unrelated boxing methods. | |
688 Node* proj = proj_out(TypeFunc::Parms); | |
689 if ((proj == NULL) || (phase->type(proj)->is_instptr()->klass() != boxing_klass)) { | |
690 return false; | |
691 } | |
692 } | |
693 if (is_CallJava() && as_CallJava()->method() != NULL) { | |
694 ciMethod* meth = as_CallJava()->method(); | |
695 if (meth->is_accessor()) { | |
696 return false; | |
697 } | |
698 // May modify (by reflection) if an boxing object is passed | |
699 // as argument or returned. | |
700 if (returns_pointer() && (proj_out(TypeFunc::Parms) != NULL)) { | |
701 Node* proj = proj_out(TypeFunc::Parms); | |
702 const TypeInstPtr* inst_t = phase->type(proj)->isa_instptr(); | |
703 if ((inst_t != NULL) && (!inst_t->klass_is_exact() || | |
704 (inst_t->klass() == boxing_klass))) { | |
705 return true; | |
706 } | |
707 } | |
708 const TypeTuple* d = tf()->domain(); | |
709 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { | |
710 const TypeInstPtr* inst_t = d->field_at(i)->isa_instptr(); | |
711 if ((inst_t != NULL) && (!inst_t->klass_is_exact() || | |
712 (inst_t->klass() == boxing_klass))) { | |
713 return true; | |
714 } | |
715 } | |
716 return false; | |
717 } | |
718 } | |
719 return true; | |
65 | 720 } |
721 | |
722 // Does this call have a direct reference to n other than debug information? | |
723 bool CallNode::has_non_debug_use(Node *n) { | |
724 const TypeTuple * d = tf()->domain(); | |
725 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { | |
726 Node *arg = in(i); | |
727 if (arg == n) { | |
728 return true; | |
729 } | |
730 } | |
731 return false; | |
732 } | |
733 | |
734 // Returns the unique CheckCastPP of a call | |
735 // or 'this' if there are several CheckCastPP | |
736 // or returns NULL if there is no one. | |
737 Node *CallNode::result_cast() { | |
738 Node *cast = NULL; | |
739 | |
740 Node *p = proj_out(TypeFunc::Parms); | |
741 if (p == NULL) | |
742 return NULL; | |
743 | |
744 for (DUIterator_Fast imax, i = p->fast_outs(imax); i < imax; i++) { | |
745 Node *use = p->fast_out(i); | |
746 if (use->is_CheckCastPP()) { | |
747 if (cast != NULL) { | |
748 return this; // more than 1 CheckCastPP | |
749 } | |
750 cast = use; | |
751 } | |
752 } | |
753 return cast; | |
754 } | |
755 | |
756 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
757 void CallNode::extract_projections(CallProjections* projs, bool separate_io_proj) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
758 projs->fallthrough_proj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
759 projs->fallthrough_catchproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
760 projs->fallthrough_ioproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
761 projs->catchall_ioproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
762 projs->catchall_catchproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
763 projs->fallthrough_memproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
764 projs->catchall_memproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
765 projs->resproj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
766 projs->exobj = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
767 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
768 for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
769 ProjNode *pn = fast_out(i)->as_Proj(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
770 if (pn->outcnt() == 0) continue; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
771 switch (pn->_con) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
772 case TypeFunc::Control: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
773 { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
774 // 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
|
775 projs->fallthrough_proj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
776 DUIterator_Fast jmax, j = pn->fast_outs(jmax); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
777 const Node *cn = pn->fast_out(j); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
778 if (cn->is_Catch()) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
779 ProjNode *cpn = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
780 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
|
781 cpn = cn->fast_out(k)->as_Proj(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
782 assert(cpn->is_CatchProj(), "must be a CatchProjNode"); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
783 if (cpn->_con == CatchProjNode::fall_through_index) |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
784 projs->fallthrough_catchproj = cpn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
785 else { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
786 assert(cpn->_con == CatchProjNode::catch_all_index, "must be correct index."); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
787 projs->catchall_catchproj = cpn; |
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 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
791 break; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
792 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
793 case TypeFunc::I_O: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
794 if (pn->_is_io_use) |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
795 projs->catchall_ioproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
796 else |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
797 projs->fallthrough_ioproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
798 for (DUIterator j = pn->outs(); pn->has_out(j); j++) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
799 Node* e = pn->out(j); |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
6804
diff
changeset
|
800 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
|
801 assert(projs->exobj == NULL, "only one"); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
802 projs->exobj = e; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
803 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
804 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
805 break; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
806 case TypeFunc::Memory: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
807 if (pn->_is_io_use) |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
808 projs->catchall_memproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
809 else |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
810 projs->fallthrough_memproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
811 break; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
812 case TypeFunc::Parms: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
813 projs->resproj = pn; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
814 break; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
815 default: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
816 assert(false, "unexpected projection from allocation node."); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
817 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
818 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
819 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
820 // The resproj may not exist because the result couuld be ignored |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
821 // and the exception object may not exist if an exception handler |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
822 // 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
|
823 assert(projs->fallthrough_proj != NULL, "must be found"); |
7473 | 824 assert(Compile::current()->inlining_incrementally() || projs->fallthrough_catchproj != NULL, "must be found"); |
825 assert(Compile::current()->inlining_incrementally() || projs->fallthrough_memproj != NULL, "must be found"); | |
826 assert(Compile::current()->inlining_incrementally() || projs->fallthrough_ioproj != NULL, "must be found"); | |
827 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
|
828 if (separate_io_proj) { |
7473 | 829 assert(Compile::current()->inlining_incrementally() || projs->catchall_memproj != NULL, "must be found"); |
830 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
|
831 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
832 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
833 |
7473 | 834 Node *CallNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
835 CallGenerator* cg = generator(); | |
836 if (can_reshape && cg != NULL && cg->is_mh_late_inline() && !cg->already_attempted()) { | |
837 // Check whether this MH handle call becomes a candidate for inlining | |
838 ciMethod* callee = cg->method(); | |
839 vmIntrinsics::ID iid = callee->intrinsic_id(); | |
840 if (iid == vmIntrinsics::_invokeBasic) { | |
841 if (in(TypeFunc::Parms)->Opcode() == Op_ConP) { | |
842 phase->C->prepend_late_inline(cg); | |
843 set_generator(NULL); | |
844 } | |
845 } else { | |
846 assert(callee->has_member_arg(), "wrong type of call?"); | |
847 if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) { | |
848 phase->C->prepend_late_inline(cg); | |
849 set_generator(NULL); | |
850 } | |
851 } | |
852 } | |
853 return SafePointNode::Ideal(phase, can_reshape); | |
854 } | |
855 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1040
diff
changeset
|
856 |
0 | 857 //============================================================================= |
858 uint CallJavaNode::size_of() const { return sizeof(*this); } | |
859 uint CallJavaNode::cmp( const Node &n ) const { | |
860 CallJavaNode &call = (CallJavaNode&)n; | |
861 return CallNode::cmp(call) && _method == call._method; | |
862 } | |
863 #ifndef PRODUCT | |
864 void CallJavaNode::dump_spec(outputStream *st) const { | |
865 if( _method ) _method->print_short_name(st); | |
866 CallNode::dump_spec(st); | |
867 } | |
868 #endif | |
869 | |
870 //============================================================================= | |
871 uint CallStaticJavaNode::size_of() const { return sizeof(*this); } | |
872 uint CallStaticJavaNode::cmp( const Node &n ) const { | |
873 CallStaticJavaNode &call = (CallStaticJavaNode&)n; | |
874 return CallJavaNode::cmp(call); | |
875 } | |
876 | |
877 //----------------------------uncommon_trap_request---------------------------- | |
878 // If this is an uncommon trap, return the request code, else zero. | |
879 int CallStaticJavaNode::uncommon_trap_request() const { | |
880 if (_name != NULL && !strcmp(_name, "uncommon_trap")) { | |
881 return extract_uncommon_trap_request(this); | |
882 } | |
883 return 0; | |
884 } | |
885 int CallStaticJavaNode::extract_uncommon_trap_request(const Node* call) { | |
886 #ifndef PRODUCT | |
887 if (!(call->req() > TypeFunc::Parms && | |
888 call->in(TypeFunc::Parms) != NULL && | |
889 call->in(TypeFunc::Parms)->is_Con())) { | |
890 assert(_in_dump_cnt != 0, "OK if dumping"); | |
891 tty->print("[bad uncommon trap]"); | |
892 return 0; | |
893 } | |
894 #endif | |
895 return call->in(TypeFunc::Parms)->bottom_type()->is_int()->get_con(); | |
896 } | |
897 | |
898 #ifndef PRODUCT | |
899 void CallStaticJavaNode::dump_spec(outputStream *st) const { | |
900 st->print("# Static "); | |
901 if (_name != NULL) { | |
902 st->print("%s", _name); | |
903 int trap_req = uncommon_trap_request(); | |
904 if (trap_req != 0) { | |
905 char buf[100]; | |
906 st->print("(%s)", | |
907 Deoptimization::format_trap_request(buf, sizeof(buf), | |
908 trap_req)); | |
909 } | |
910 st->print(" "); | |
911 } | |
912 CallJavaNode::dump_spec(st); | |
913 } | |
914 #endif | |
915 | |
916 //============================================================================= | |
917 uint CallDynamicJavaNode::size_of() const { return sizeof(*this); } | |
918 uint CallDynamicJavaNode::cmp( const Node &n ) const { | |
919 CallDynamicJavaNode &call = (CallDynamicJavaNode&)n; | |
920 return CallJavaNode::cmp(call); | |
921 } | |
922 #ifndef PRODUCT | |
923 void CallDynamicJavaNode::dump_spec(outputStream *st) const { | |
924 st->print("# Dynamic "); | |
925 CallJavaNode::dump_spec(st); | |
926 } | |
927 #endif | |
928 | |
929 //============================================================================= | |
930 uint CallRuntimeNode::size_of() const { return sizeof(*this); } | |
931 uint CallRuntimeNode::cmp( const Node &n ) const { | |
932 CallRuntimeNode &call = (CallRuntimeNode&)n; | |
933 return CallNode::cmp(call) && !strcmp(_name,call._name); | |
934 } | |
935 #ifndef PRODUCT | |
936 void CallRuntimeNode::dump_spec(outputStream *st) const { | |
937 st->print("# "); | |
938 st->print(_name); | |
939 CallNode::dump_spec(st); | |
940 } | |
941 #endif | |
942 | |
943 //------------------------------calling_convention----------------------------- | |
944 void CallRuntimeNode::calling_convention( BasicType* sig_bt, VMRegPair *parm_regs, uint argcnt ) const { | |
945 Matcher::c_calling_convention( sig_bt, parm_regs, argcnt ); | |
946 } | |
947 | |
948 //============================================================================= | |
949 //------------------------------calling_convention----------------------------- | |
950 | |
951 | |
952 //============================================================================= | |
953 #ifndef PRODUCT | |
954 void CallLeafNode::dump_spec(outputStream *st) const { | |
955 st->print("# "); | |
956 st->print(_name); | |
957 CallNode::dump_spec(st); | |
958 } | |
959 #endif | |
960 | |
961 //============================================================================= | |
962 | |
963 void SafePointNode::set_local(JVMState* jvms, uint idx, Node *c) { | |
964 assert(verify_jvms(jvms), "jvms must match"); | |
965 int loc = jvms->locoff() + idx; | |
966 if (in(loc)->is_top() && idx > 0 && !c->is_top() ) { | |
967 // If current local idx is top then local idx - 1 could | |
968 // be a long/double that needs to be killed since top could | |
969 // represent the 2nd half ofthe long/double. | |
970 uint ideal = in(loc -1)->ideal_reg(); | |
971 if (ideal == Op_RegD || ideal == Op_RegL) { | |
972 // set other (low index) half to top | |
973 set_req(loc - 1, in(loc)); | |
974 } | |
975 } | |
976 set_req(loc, c); | |
977 } | |
978 | |
979 uint SafePointNode::size_of() const { return sizeof(*this); } | |
980 uint SafePointNode::cmp( const Node &n ) const { | |
981 return (&n == this); // Always fail except on self | |
982 } | |
983 | |
984 //-------------------------set_next_exception---------------------------------- | |
985 void SafePointNode::set_next_exception(SafePointNode* n) { | |
986 assert(n == NULL || n->Opcode() == Op_SafePoint, "correct value for next_exception"); | |
987 if (len() == req()) { | |
988 if (n != NULL) add_prec(n); | |
989 } else { | |
990 set_prec(req(), n); | |
991 } | |
992 } | |
993 | |
994 | |
995 //----------------------------next_exception----------------------------------- | |
996 SafePointNode* SafePointNode::next_exception() const { | |
997 if (len() == req()) { | |
998 return NULL; | |
999 } else { | |
1000 Node* n = in(req()); | |
1001 assert(n == NULL || n->Opcode() == Op_SafePoint, "no other uses of prec edges"); | |
1002 return (SafePointNode*) n; | |
1003 } | |
1004 } | |
1005 | |
1006 | |
1007 //------------------------------Ideal------------------------------------------ | |
1008 // Skip over any collapsed Regions | |
1009 Node *SafePointNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
305 | 1010 return remove_dead_region(phase, can_reshape) ? this : NULL; |
0 | 1011 } |
1012 | |
1013 //------------------------------Identity--------------------------------------- | |
1014 // Remove obviously duplicate safepoints | |
1015 Node *SafePointNode::Identity( PhaseTransform *phase ) { | |
1016 | |
1017 // If you have back to back safepoints, remove one | |
1018 if( in(TypeFunc::Control)->is_SafePoint() ) | |
1019 return in(TypeFunc::Control); | |
1020 | |
1021 if( in(0)->is_Proj() ) { | |
1022 Node *n0 = in(0)->in(0); | |
1023 // Check if he is a call projection (except Leaf Call) | |
1024 if( n0->is_Catch() ) { | |
1025 n0 = n0->in(0)->in(0); | |
1026 assert( n0->is_Call(), "expect a call here" ); | |
1027 } | |
1028 if( n0->is_Call() && n0->as_Call()->guaranteed_safepoint() ) { | |
1029 // Useless Safepoint, so remove it | |
1030 return in(TypeFunc::Control); | |
1031 } | |
1032 } | |
1033 | |
1034 return this; | |
1035 } | |
1036 | |
1037 //------------------------------Value------------------------------------------ | |
1038 const Type *SafePointNode::Value( PhaseTransform *phase ) const { | |
1039 if( phase->type(in(0)) == Type::TOP ) return Type::TOP; | |
1040 if( phase->eqv( in(0), this ) ) return Type::TOP; // Dead infinite loop | |
1041 return Type::CONTROL; | |
1042 } | |
1043 | |
1044 #ifndef PRODUCT | |
1045 void SafePointNode::dump_spec(outputStream *st) const { | |
1046 st->print(" SafePoint "); | |
1047 } | |
1048 #endif | |
1049 | |
1050 const RegMask &SafePointNode::in_RegMask(uint idx) const { | |
1051 if( idx < TypeFunc::Parms ) return RegMask::Empty; | |
1052 // Values outside the domain represent debug info | |
1053 return *(Compile::current()->matcher()->idealreg2debugmask[in(idx)->ideal_reg()]); | |
1054 } | |
1055 const RegMask &SafePointNode::out_RegMask() const { | |
1056 return RegMask::Empty; | |
1057 } | |
1058 | |
1059 | |
1060 void SafePointNode::grow_stack(JVMState* jvms, uint grow_by) { | |
1061 assert((int)grow_by > 0, "sanity"); | |
1062 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
|
1063 int scloff = jvms->scloff(); |
0 | 1064 int endoff = jvms->endoff(); |
1065 assert(endoff == (int)req(), "no other states or debug info after me"); | |
1066 Node* top = Compile::current()->top(); | |
1067 for (uint i = 0; i < grow_by; i++) { | |
1068 ins_req(monoff, top); | |
1069 } | |
1070 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
|
1071 jvms->set_scloff(scloff + grow_by); |
0 | 1072 jvms->set_endoff(endoff + grow_by); |
1073 } | |
1074 | |
1075 void SafePointNode::push_monitor(const FastLockNode *lock) { | |
1076 // Add a LockNode, which points to both the original BoxLockNode (the | |
1077 // stack space for the monitor) and the Object being locked. | |
1078 const int MonitorEdges = 2; | |
1079 assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct MonitorEdges"); | |
1080 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
|
1081 int nextmon = jvms()->scloff(); |
0 | 1082 if (GenerateSynchronizationCode) { |
12158
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
1083 ins_req(nextmon, lock->box_node()); |
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
1084 ins_req(nextmon+1, lock->obj_node()); |
0 | 1085 } else { |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
1086 Node* top = Compile::current()->top(); |
12158
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
1087 ins_req(nextmon, top); |
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
1088 ins_req(nextmon, top); |
0 | 1089 } |
12158
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
1090 jvms()->set_scloff(nextmon + MonitorEdges); |
0 | 1091 jvms()->set_endoff(req()); |
1092 } | |
1093 | |
1094 void SafePointNode::pop_monitor() { | |
1095 // Delete last monitor from debug info | |
1096 debug_only(int num_before_pop = jvms()->nof_monitors()); | |
12158
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
1097 const int MonitorEdges = 2; |
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
1098 assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct 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
|
1099 int scloff = jvms()->scloff(); |
0 | 1100 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
|
1101 int new_scloff = scloff - MonitorEdges; |
0 | 1102 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
|
1103 jvms()->set_scloff(new_scloff); |
0 | 1104 jvms()->set_endoff(new_endoff); |
12158
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
1105 while (scloff > new_scloff) del_req_ordered(--scloff); |
0 | 1106 assert(jvms()->nof_monitors() == num_before_pop-1, ""); |
1107 } | |
1108 | |
1109 Node *SafePointNode::peek_monitor_box() const { | |
1110 int mon = jvms()->nof_monitors() - 1; | |
1111 assert(mon >= 0, "most have a monitor"); | |
1112 return monitor_box(jvms(), mon); | |
1113 } | |
1114 | |
1115 Node *SafePointNode::peek_monitor_obj() const { | |
1116 int mon = jvms()->nof_monitors() - 1; | |
1117 assert(mon >= 0, "most have a monitor"); | |
1118 return monitor_obj(jvms(), mon); | |
1119 } | |
1120 | |
1121 // Do we Match on this edge index or not? Match no edges | |
1122 uint SafePointNode::match_edge(uint idx) const { | |
1123 if( !needs_polling_address_input() ) | |
1124 return 0; | |
1125 | |
1126 return (TypeFunc::Parms == idx); | |
1127 } | |
1128 | |
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
|
1129 //============== 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
|
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::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
|
1132 #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
|
1133 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
|
1134 #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
|
1135 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
|
1136 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
|
1137 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
|
1138 #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
|
1139 _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
|
1140 #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
|
1141 _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
|
1142 _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
|
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 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
|
1145 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1146 |
4115 | 1147 // Do not allow value-numbering for SafePointScalarObject node. |
1148 uint SafePointScalarObjectNode::hash() const { return NO_HASH; } | |
1149 uint SafePointScalarObjectNode::cmp( const Node &n ) const { | |
1150 return (&n == this); // Always fail except on self | |
1151 } | |
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
|
1152 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1153 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
|
1154 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
|
1155 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1156 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1157 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
|
1158 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
|
1159 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1160 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1161 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
|
1162 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
|
1163 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1164 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1165 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
|
1166 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
|
1167 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1168 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1169 SafePointScalarObjectNode* |
12158
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
10278
diff
changeset
|
1170 SafePointScalarObjectNode::clone(Dict* sosn_map) const { |
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
|
1171 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
|
1172 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
|
1173 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
|
1174 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1175 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
|
1176 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
|
1177 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
|
1178 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1179 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1180 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1181 #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
|
1182 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
|
1183 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
|
1184 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
|
1185 } |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1186 |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
39
diff
changeset
|
1187 #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
|
1188 |
0 | 1189 //============================================================================= |
1190 uint AllocateNode::size_of() const { return sizeof(*this); } | |
1191 | |
1192 AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype, | |
1193 Node *ctrl, Node *mem, Node *abio, | |
1194 Node *size, Node *klass_node, Node *initial_test) | |
1195 : CallNode(atype, NULL, TypeRawPtr::BOTTOM) | |
1196 { | |
1197 init_class_id(Class_Allocate); | |
1198 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
|
1199 _is_scalar_replaceable = false; |
10278 | 1200 _is_non_escaping = false; |
0 | 1201 Node *topnode = C->top(); |
1202 | |
1203 init_req( TypeFunc::Control , ctrl ); | |
1204 init_req( TypeFunc::I_O , abio ); | |
1205 init_req( TypeFunc::Memory , mem ); | |
1206 init_req( TypeFunc::ReturnAdr, topnode ); | |
1207 init_req( TypeFunc::FramePtr , topnode ); | |
1208 init_req( AllocSize , size); | |
1209 init_req( KlassNode , klass_node); | |
1210 init_req( InitialTest , initial_test); | |
1211 init_req( ALength , topnode); | |
1212 C->add_macro_node(this); | |
1213 } | |
1214 | |
1215 //============================================================================= | |
704
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1216 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
|
1217 if (remove_dead_region(phase, can_reshape)) return this; |
4115 | 1218 // Don't bother trying to transform a dead node |
1219 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
|
1220 |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1221 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
|
1222 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
|
1223 if (can_reshape) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1224 PhaseIterGVN *igvn = phase->is_IterGVN(); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1225 // 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
|
1226 // 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
|
1227 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
|
1228 Node* catchproj = NULL; |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1229 if (proj != NULL) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1230 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
|
1231 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
|
1232 if (cn->is_Catch()) { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1233 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
|
1234 break; |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1235 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1236 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1237 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1238 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
|
1239 (catchproj->outcnt() > 1 || |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1240 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
|
1241 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
|
1242 Node* nproj = catchproj->clone(); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1243 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
|
1244 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1245 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
|
1246 frame = phase->transform(frame); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1247 // Halt & Catch Fire |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1248 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
|
1249 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
|
1250 phase->transform(halt); |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1251 |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1252 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
|
1253 return this; |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1254 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1255 } else { |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1256 // 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
|
1257 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
|
1258 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1259 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1260 return NULL; |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1261 } |
ad8c635e757e
6823453: DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
kvn
parents:
601
diff
changeset
|
1262 |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1263 // 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
|
1264 // 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
|
1265 // 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
|
1266 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
|
1267 Node *length = in(AllocateNode::ALength); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1268 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
|
1269 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1270 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
|
1271 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
|
1272 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1273 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
|
1274 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
|
1275 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
|
1276 // Assert one of: |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1277 // - the narrow_length is 0 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1278 // - 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
|
1279 assert(narrow_length_type == TypeInt::ZERO || |
10278 | 1280 length_type->is_con() && narrow_length_type->is_con() && |
1281 (narrow_length_type->_hi <= length_type->_lo) || | |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1282 (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
|
1283 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
|
1284 "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
|
1285 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1286 // 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
|
1287 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
|
1288 // 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
|
1289 // 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
|
1290 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
|
1291 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
|
1292 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1293 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1294 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1295 return length; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1296 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
331
diff
changeset
|
1297 |
0 | 1298 //============================================================================= |
1299 uint LockNode::size_of() const { return sizeof(*this); } | |
1300 | |
1301 // Redundant lock elimination | |
1302 // | |
1303 // There are various patterns of locking where we release and | |
1304 // immediately reacquire a lock in a piece of code where no operations | |
1305 // occur in between that would be observable. In those cases we can | |
1306 // skip releasing and reacquiring the lock without violating any | |
1307 // fairness requirements. Doing this around a loop could cause a lock | |
1308 // to be held for a very long time so we concentrate on non-looping | |
1309 // control flow. We also require that the operations are fully | |
1310 // redundant meaning that we don't introduce new lock operations on | |
1311 // some paths so to be able to eliminate it on others ala PRE. This | |
1312 // would probably require some more extensive graph manipulation to | |
1313 // guarantee that the memory edges were all handled correctly. | |
1314 // | |
1315 // Assuming p is a simple predicate which can't trap in any way and s | |
1316 // is a synchronized method consider this code: | |
1317 // | |
1318 // s(); | |
1319 // if (p) | |
1320 // s(); | |
1321 // else | |
1322 // s(); | |
1323 // s(); | |
1324 // | |
1325 // 1. The unlocks of the first call to s can be eliminated if the | |
1326 // locks inside the then and else branches are eliminated. | |
1327 // | |
1328 // 2. The unlocks of the then and else branches can be eliminated if | |
1329 // the lock of the final call to s is eliminated. | |
1330 // | |
1331 // Either of these cases subsumes the simple case of sequential control flow | |
1332 // | |
1333 // Addtionally we can eliminate versions without the else case: | |
1334 // | |
1335 // s(); | |
1336 // if (p) | |
1337 // s(); | |
1338 // s(); | |
1339 // | |
1340 // 3. In this case we eliminate the unlock of the first s, the lock | |
1341 // and unlock in the then case and the lock in the final s. | |
1342 // | |
1343 // Note also that in all these cases the then/else pieces don't have | |
1344 // to be trivial as long as they begin and end with synchronization | |
1345 // operations. | |
1346 // | |
1347 // s(); | |
1348 // if (p) | |
1349 // s(); | |
1350 // f(); | |
1351 // s(); | |
1352 // s(); | |
1353 // | |
1354 // The code will work properly for this case, leaving in the unlock | |
1355 // before the call to f and the relock after it. | |
1356 // | |
1357 // A potentially interesting case which isn't handled here is when the | |
1358 // locking is partially redundant. | |
1359 // | |
1360 // s(); | |
1361 // if (p) | |
1362 // s(); | |
1363 // | |
1364 // This could be eliminated putting unlocking on the else case and | |
1365 // eliminating the first unlock and the lock in the then side. | |
1366 // Alternatively the unlock could be moved out of the then side so it | |
1367 // was after the merge and the first unlock and second lock | |
1368 // eliminated. This might require less manipulation of the memory | |
1369 // state to get correct. | |
1370 // | |
1371 // Additionally we might allow work between a unlock and lock before | |
1372 // giving up eliminating the locks. The current code disallows any | |
1373 // conditional control flow between these operations. A formulation | |
1374 // similar to partial redundancy elimination computing the | |
1375 // availability of unlocking and the anticipatability of locking at a | |
1376 // program point would allow detection of fully redundant locking with | |
1377 // some amount of work in between. I'm not sure how often I really | |
1378 // think that would occur though. Most of the cases I've seen | |
1379 // indicate it's likely non-trivial work would occur in between. | |
1380 // There may be other more complicated constructs where we could | |
1381 // eliminate locking but I haven't seen any others appear as hot or | |
1382 // interesting. | |
1383 // | |
1384 // Locking and unlocking have a canonical form in ideal that looks | |
1385 // roughly like this: | |
1386 // | |
1387 // <obj> | |
1388 // | \\------+ | |
1389 // | \ \ | |
1390 // | BoxLock \ | |
1391 // | | | \ | |
1392 // | | \ \ | |
1393 // | | FastLock | |
1394 // | | / | |
1395 // | | / | |
1396 // | | | | |
1397 // | |
1398 // Lock | |
1399 // | | |
1400 // Proj #0 | |
1401 // | | |
1402 // MembarAcquire | |
1403 // | | |
1404 // Proj #0 | |
1405 // | |
1406 // MembarRelease | |
1407 // | | |
1408 // Proj #0 | |
1409 // | | |
1410 // Unlock | |
1411 // | | |
1412 // Proj #0 | |
1413 // | |
1414 // | |
1415 // This code proceeds by processing Lock nodes during PhaseIterGVN | |
1416 // and searching back through its control for the proper code | |
1417 // patterns. Once it finds a set of lock and unlock operations to | |
1418 // eliminate they are marked as eliminatable which causes the | |
1419 // expansion of the Lock and Unlock macro nodes to make the operation a NOP | |
1420 // | |
1421 //============================================================================= | |
1422 | |
1423 // | |
1424 // Utility function to skip over uninteresting control nodes. Nodes skipped are: | |
1425 // - copy regions. (These may not have been optimized away yet.) | |
1426 // - eliminated locking nodes | |
1427 // | |
1428 static Node *next_control(Node *ctrl) { | |
1429 if (ctrl == NULL) | |
1430 return NULL; | |
1431 while (1) { | |
1432 if (ctrl->is_Region()) { | |
1433 RegionNode *r = ctrl->as_Region(); | |
1434 Node *n = r->is_copy(); | |
1435 if (n == NULL) | |
1436 break; // hit a region, return it | |
1437 else | |
1438 ctrl = n; | |
1439 } else if (ctrl->is_Proj()) { | |
1440 Node *in0 = ctrl->in(0); | |
1441 if (in0->is_AbstractLock() && in0->as_AbstractLock()->is_eliminated()) { | |
1442 ctrl = in0->in(0); | |
1443 } else { | |
1444 break; | |
1445 } | |
1446 } else { | |
1447 break; // found an interesting control | |
1448 } | |
1449 } | |
1450 return ctrl; | |
1451 } | |
1452 // | |
1453 // Given a control, see if it's the control projection of an Unlock which | |
1454 // operating on the same object as lock. | |
1455 // | |
1456 bool AbstractLockNode::find_matching_unlock(const Node* ctrl, LockNode* lock, | |
1457 GrowableArray<AbstractLockNode*> &lock_ops) { | |
1458 ProjNode *ctrl_proj = (ctrl->is_Proj()) ? ctrl->as_Proj() : NULL; | |
1459 if (ctrl_proj != NULL && ctrl_proj->_con == TypeFunc::Control) { | |
1460 Node *n = ctrl_proj->in(0); | |
1461 if (n != NULL && n->is_Unlock()) { | |
1462 UnlockNode *unlock = n->as_Unlock(); | |
4778 | 1463 if (lock->obj_node()->eqv_uncast(unlock->obj_node()) && |
4777 | 1464 BoxLockNode::same_slot(lock->box_node(), unlock->box_node()) && |
1465 !unlock->is_eliminated()) { | |
0 | 1466 lock_ops.append(unlock); |
1467 return true; | |
1468 } | |
1469 } | |
1470 } | |
1471 return false; | |
1472 } | |
1473 | |
1474 // | |
1475 // Find the lock matching an unlock. Returns null if a safepoint | |
1476 // or complicated control is encountered first. | |
1477 LockNode *AbstractLockNode::find_matching_lock(UnlockNode* unlock) { | |
1478 LockNode *lock_result = NULL; | |
1479 // find the matching lock, or an intervening safepoint | |
1480 Node *ctrl = next_control(unlock->in(0)); | |
1481 while (1) { | |
1482 assert(ctrl != NULL, "invalid control graph"); | |
1483 assert(!ctrl->is_Start(), "missing lock for unlock"); | |
1484 if (ctrl->is_top()) break; // dead control path | |
1485 if (ctrl->is_Proj()) ctrl = ctrl->in(0); | |
1486 if (ctrl->is_SafePoint()) { | |
1487 break; // found a safepoint (may be the lock we are searching for) | |
1488 } else if (ctrl->is_Region()) { | |
1489 // Check for a simple diamond pattern. Punt on anything more complicated | |
1490 if (ctrl->req() == 3 && ctrl->in(1) != NULL && ctrl->in(2) != NULL) { | |
1491 Node *in1 = next_control(ctrl->in(1)); | |
1492 Node *in2 = next_control(ctrl->in(2)); | |
1493 if (((in1->is_IfTrue() && in2->is_IfFalse()) || | |
1494 (in2->is_IfTrue() && in1->is_IfFalse())) && (in1->in(0) == in2->in(0))) { | |
1495 ctrl = next_control(in1->in(0)->in(0)); | |
1496 } else { | |
1497 break; | |
1498 } | |
1499 } else { | |
1500 break; | |
1501 } | |
1502 } else { | |
1503 ctrl = next_control(ctrl->in(0)); // keep searching | |
1504 } | |
1505 } | |
1506 if (ctrl->is_Lock()) { | |
1507 LockNode *lock = ctrl->as_Lock(); | |
4778 | 1508 if (lock->obj_node()->eqv_uncast(unlock->obj_node()) && |
4777 | 1509 BoxLockNode::same_slot(lock->box_node(), unlock->box_node())) { |
0 | 1510 lock_result = lock; |
1511 } | |
1512 } | |
1513 return lock_result; | |
1514 } | |
1515 | |
1516 // This code corresponds to case 3 above. | |
1517 | |
1518 bool AbstractLockNode::find_lock_and_unlock_through_if(Node* node, LockNode* lock, | |
1519 GrowableArray<AbstractLockNode*> &lock_ops) { | |
1520 Node* if_node = node->in(0); | |
1521 bool if_true = node->is_IfTrue(); | |
1522 | |
1523 if (if_node->is_If() && if_node->outcnt() == 2 && (if_true || node->is_IfFalse())) { | |
1524 Node *lock_ctrl = next_control(if_node->in(0)); | |
1525 if (find_matching_unlock(lock_ctrl, lock, lock_ops)) { | |
1526 Node* lock1_node = NULL; | |
1527 ProjNode* proj = if_node->as_If()->proj_out(!if_true); | |
1528 if (if_true) { | |
1529 if (proj->is_IfFalse() && proj->outcnt() == 1) { | |
1530 lock1_node = proj->unique_out(); | |
1531 } | |
1532 } else { | |
1533 if (proj->is_IfTrue() && proj->outcnt() == 1) { | |
1534 lock1_node = proj->unique_out(); | |
1535 } | |
1536 } | |
1537 if (lock1_node != NULL && lock1_node->is_Lock()) { | |
1538 LockNode *lock1 = lock1_node->as_Lock(); | |
4778 | 1539 if (lock->obj_node()->eqv_uncast(lock1->obj_node()) && |
4777 | 1540 BoxLockNode::same_slot(lock->box_node(), lock1->box_node()) && |
1541 !lock1->is_eliminated()) { | |
0 | 1542 lock_ops.append(lock1); |
1543 return true; | |
1544 } | |
1545 } | |
1546 } | |
1547 } | |
1548 | |
1549 lock_ops.trunc_to(0); | |
1550 return false; | |
1551 } | |
1552 | |
1553 bool AbstractLockNode::find_unlocks_for_region(const RegionNode* region, LockNode* lock, | |
1554 GrowableArray<AbstractLockNode*> &lock_ops) { | |
1555 // check each control merging at this point for a matching unlock. | |
1556 // in(0) should be self edge so skip it. | |
1557 for (int i = 1; i < (int)region->req(); i++) { | |
1558 Node *in_node = next_control(region->in(i)); | |
1559 if (in_node != NULL) { | |
1560 if (find_matching_unlock(in_node, lock, lock_ops)) { | |
1561 // found a match so keep on checking. | |
1562 continue; | |
1563 } else if (find_lock_and_unlock_through_if(in_node, lock, lock_ops)) { | |
1564 continue; | |
1565 } | |
1566 | |
1567 // If we fall through to here then it was some kind of node we | |
1568 // don't understand or there wasn't a matching unlock, so give | |
1569 // up trying to merge locks. | |
1570 lock_ops.trunc_to(0); | |
1571 return false; | |
1572 } | |
1573 } | |
1574 return true; | |
1575 | |
1576 } | |
1577 | |
1578 #ifndef PRODUCT | |
1579 // | |
1580 // Create a counter which counts the number of times this lock is acquired | |
1581 // | |
1582 void AbstractLockNode::create_lock_counter(JVMState* state) { | |
1583 _counter = OptoRuntime::new_named_counter(state, NamedCounter::LockCounter); | |
1584 } | |
1585 | |
4777 | 1586 void AbstractLockNode::set_eliminated_lock_counter() { |
0 | 1587 if (_counter) { |
1588 // Update the counter to indicate that this lock was eliminated. | |
1589 // The counter update code will stay around even though the | |
1590 // optimizer will eliminate the lock operation itself. | |
1591 _counter->set_tag(NamedCounter::EliminatedLockCounter); | |
1592 } | |
4777 | 1593 } |
0 | 1594 #endif |
1595 | |
1596 //============================================================================= | |
1597 Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
1598 | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1599 // perform any generic optimizations first (returns 'this' or NULL) |
0 | 1600 Node *result = SafePointNode::Ideal(phase, can_reshape); |
4115 | 1601 if (result != NULL) return result; |
1602 // Don't bother trying to transform a dead node | |
1603 if (in(0) && in(0)->is_top()) return NULL; | |
0 | 1604 |
1605 // Now see if we can optimize away this lock. We don't actually | |
1606 // remove the locking here, we simply set the _eliminate flag which | |
1607 // prevents macro expansion from expanding the lock. Since we don't | |
1608 // modify the graph, the value returned from this function is the | |
1609 // one computed above. | |
4777 | 1610 if (can_reshape && EliminateLocks && !is_non_esc_obj()) { |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1611 // |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1612 // 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
|
1613 // |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
1614 ConnectionGraph *cgr = phase->C->congraph(); |
5948
ee138854b3a6
7147744: CTW: assert(false) failed: infinite EA connection graph build
kvn
parents:
4790
diff
changeset
|
1615 if (cgr != NULL && cgr->not_global_escape(obj_node())) { |
4777 | 1616 assert(!is_eliminated() || is_coarsened(), "sanity"); |
1617 // The lock could be marked eliminated by lock coarsening | |
1618 // code during first IGVN before EA. Replace coarsened flag | |
1619 // to eliminate all associated locks/unlocks. | |
1620 this->set_non_esc_obj(); | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1621 return result; |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1622 } |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1623 |
0 | 1624 // |
1625 // Try lock coarsening | |
1626 // | |
1627 PhaseIterGVN* iter = phase->is_IterGVN(); | |
4115 | 1628 if (iter != NULL && !is_eliminated()) { |
0 | 1629 |
1630 GrowableArray<AbstractLockNode*> lock_ops; | |
1631 | |
1632 Node *ctrl = next_control(in(0)); | |
1633 | |
1634 // now search back for a matching Unlock | |
1635 if (find_matching_unlock(ctrl, this, lock_ops)) { | |
1636 // found an unlock directly preceding this lock. This is the | |
1637 // case of single unlock directly control dependent on a | |
1638 // single lock which is the trivial version of case 1 or 2. | |
1639 } else if (ctrl->is_Region() ) { | |
1640 if (find_unlocks_for_region(ctrl->as_Region(), this, lock_ops)) { | |
1641 // found lock preceded by multiple unlocks along all paths | |
1642 // joining at this point which is case 3 in description above. | |
1643 } | |
1644 } else { | |
1645 // see if this lock comes from either half of an if and the | |
1646 // predecessors merges unlocks and the other half of the if | |
1647 // performs a lock. | |
1648 if (find_lock_and_unlock_through_if(ctrl, this, lock_ops)) { | |
1649 // found unlock splitting to an if with locks on both branches. | |
1650 } | |
1651 } | |
1652 | |
1653 if (lock_ops.length() > 0) { | |
1654 // add ourselves to the list of locks to be eliminated. | |
1655 lock_ops.append(this); | |
1656 | |
1657 #ifndef PRODUCT | |
1658 if (PrintEliminateLocks) { | |
1659 int locks = 0; | |
1660 int unlocks = 0; | |
1661 for (int i = 0; i < lock_ops.length(); i++) { | |
1662 AbstractLockNode* lock = lock_ops.at(i); | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1663 if (lock->Opcode() == Op_Lock) |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1664 locks++; |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1665 else |
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1666 unlocks++; |
0 | 1667 if (Verbose) { |
1668 lock->dump(1); | |
1669 } | |
1670 } | |
1671 tty->print_cr("***Eliminated %d unlocks and %d locks", unlocks, locks); | |
1672 } | |
1673 #endif | |
1674 | |
1675 // for each of the identified locks, mark them | |
1676 // as eliminatable | |
1677 for (int i = 0; i < lock_ops.length(); i++) { | |
1678 AbstractLockNode* lock = lock_ops.at(i); | |
1679 | |
4777 | 1680 // 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
|
1681 lock->set_coarsened(); |
0 | 1682 } |
4115 | 1683 } else if (ctrl->is_Region() && |
0 | 1684 iter->_worklist.member(ctrl)) { |
1685 // We weren't able to find any opportunities but the region this | |
1686 // lock is control dependent on hasn't been processed yet so put | |
1687 // this lock back on the worklist so we can check again once any | |
1688 // region simplification has occurred. | |
1689 iter->_worklist.push(this); | |
1690 } | |
1691 } | |
1692 } | |
1693 | |
1694 return result; | |
1695 } | |
1696 | |
1697 //============================================================================= | |
4777 | 1698 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
|
1699 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
|
1700 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
|
1701 if (stk_slot <= 0) |
4777 | 1702 return false; // External lock or it is not Box (Phi node). |
1703 | |
1704 // Ignore complex cases: merged locks or multiple locks. | |
1705 Node* obj = obj_node(); | |
1706 LockNode* unique_lock = NULL; | |
4790
b0ff910edfc9
7128355: assert(!nocreate) failed: Cannot build a phi for a block already parsed
kvn
parents:
4778
diff
changeset
|
1707 if (!box->is_simple_lock_region(&unique_lock, obj) || |
4777 | 1708 (unique_lock != this)) { |
1709 return false; | |
1710 } | |
1711 | |
1712 // Look for external lock for the same object. | |
1713 SafePointNode* sfn = this->as_SafePoint(); | |
1714 JVMState* youngest_jvms = sfn->jvms(); | |
1715 int max_depth = youngest_jvms->depth(); | |
1716 for (int depth = 1; depth <= max_depth; depth++) { | |
1717 JVMState* jvms = youngest_jvms->of_depth(depth); | |
1718 int num_mon = jvms->nof_monitors(); | |
1719 // Loop over monitors | |
1720 for (int idx = 0; idx < num_mon; idx++) { | |
1721 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
|
1722 BoxLockNode* box_node = sfn->monitor_box(jvms, idx)->as_BoxLock(); |
4778 | 1723 if ((box_node->stack_slot() < stk_slot) && obj_node->eqv_uncast(obj)) { |
4777 | 1724 return true; |
1725 } | |
1726 } | |
1727 } | |
1728 return false; | |
1729 } | |
1730 | |
1731 //============================================================================= | |
0 | 1732 uint UnlockNode::size_of() const { return sizeof(*this); } |
1733 | |
1734 //============================================================================= | |
1735 Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
1736 | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1737 // perform any generic optimizations first (returns 'this' or NULL) |
4115 | 1738 Node *result = SafePointNode::Ideal(phase, can_reshape); |
1739 if (result != NULL) return result; | |
1740 // Don't bother trying to transform a dead node | |
1741 if (in(0) && in(0)->is_top()) return NULL; | |
0 | 1742 |
1743 // Now see if we can optimize away this unlock. We don't actually | |
1744 // remove the unlocking here, we simply set the _eliminate flag which | |
1745 // prevents macro expansion from expanding the unlock. Since we don't | |
1746 // modify the graph, the value returned from this function is the | |
1747 // one computed above. | |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1748 // Escape state is defined after Parse phase. |
4777 | 1749 if (can_reshape && EliminateLocks && !is_non_esc_obj()) { |
0 | 1750 // |
66
6dbf1a175d6b
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
65
diff
changeset
|
1751 // If we are unlocking an unescaped object, the lock/unlock is unnecessary. |
0 | 1752 // |
460
424f9bfe6b96
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
420
diff
changeset
|
1753 ConnectionGraph *cgr = phase->C->congraph(); |
5948
ee138854b3a6
7147744: CTW: assert(false) failed: infinite EA connection graph build
kvn
parents:
4790
diff
changeset
|
1754 if (cgr != NULL && cgr->not_global_escape(obj_node())) { |
4777 | 1755 assert(!is_eliminated() || is_coarsened(), "sanity"); |
1756 // The lock could be marked eliminated by lock coarsening | |
1757 // code during first IGVN before EA. Replace coarsened flag | |
1758 // to eliminate all associated locks/unlocks. | |
1759 this->set_non_esc_obj(); | |
0 | 1760 } |
1761 } | |
1762 return result; | |
1763 } |