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