Mercurial > hg > truffle
annotate src/share/vm/opto/matcher.cpp @ 1145:e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking.
Reviewed-by: jmasa
author | ysr |
---|---|
date | Wed, 23 Dec 2009 09:23:54 -0800 |
parents | 09572fede9d1 |
children | 97125851f396 |
rev | line source |
---|---|
0 | 1 /* |
579 | 2 * Copyright 1997-2009 Sun Microsystems, Inc. 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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_matcher.cpp.incl" | |
27 | |
28 OptoReg::Name OptoReg::c_frame_pointer; | |
29 | |
30 | |
31 | |
32 const int Matcher::base2reg[Type::lastype] = { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
33 Node::NotAMachineReg,0,0, Op_RegI, Op_RegL, 0, Op_RegN, |
0 | 34 Node::NotAMachineReg, Node::NotAMachineReg, /* tuple, array */ |
35 Op_RegP, Op_RegP, Op_RegP, Op_RegP, Op_RegP, Op_RegP, /* the pointers */ | |
36 0, 0/*abio*/, | |
37 Op_RegP /* Return address */, 0, /* the memories */ | |
38 Op_RegF, Op_RegF, Op_RegF, Op_RegD, Op_RegD, Op_RegD, | |
39 0 /*bottom*/ | |
40 }; | |
41 | |
42 const RegMask *Matcher::idealreg2regmask[_last_machine_leaf]; | |
43 RegMask Matcher::mreg2regmask[_last_Mach_Reg]; | |
44 RegMask Matcher::STACK_ONLY_mask; | |
45 RegMask Matcher::c_frame_ptr_mask; | |
46 const uint Matcher::_begin_rematerialize = _BEGIN_REMATERIALIZE; | |
47 const uint Matcher::_end_rematerialize = _END_REMATERIALIZE; | |
48 | |
49 //---------------------------Matcher------------------------------------------- | |
50 Matcher::Matcher( Node_List &proj_list ) : | |
51 PhaseTransform( Phase::Ins_Select ), | |
52 #ifdef ASSERT | |
53 _old2new_map(C->comp_arena()), | |
222 | 54 _new2old_map(C->comp_arena()), |
0 | 55 #endif |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
56 _shared_nodes(C->comp_arena()), |
0 | 57 _reduceOp(reduceOp), _leftOp(leftOp), _rightOp(rightOp), |
58 _swallowed(swallowed), | |
59 _begin_inst_chain_rule(_BEGIN_INST_CHAIN_RULE), | |
60 _end_inst_chain_rule(_END_INST_CHAIN_RULE), | |
61 _must_clone(must_clone), _proj_list(proj_list), | |
62 _register_save_policy(register_save_policy), | |
63 _c_reg_save_policy(c_reg_save_policy), | |
64 _register_save_type(register_save_type), | |
65 _ruleName(ruleName), | |
66 _allocation_started(false), | |
67 _states_arena(Chunk::medium_size), | |
68 _visited(&_states_arena), | |
69 _shared(&_states_arena), | |
70 _dontcare(&_states_arena) { | |
71 C->set_matcher(this); | |
72 | |
73 idealreg2spillmask[Op_RegI] = NULL; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
74 idealreg2spillmask[Op_RegN] = NULL; |
0 | 75 idealreg2spillmask[Op_RegL] = NULL; |
76 idealreg2spillmask[Op_RegF] = NULL; | |
77 idealreg2spillmask[Op_RegD] = NULL; | |
78 idealreg2spillmask[Op_RegP] = NULL; | |
79 | |
80 idealreg2debugmask[Op_RegI] = NULL; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
81 idealreg2debugmask[Op_RegN] = NULL; |
0 | 82 idealreg2debugmask[Op_RegL] = NULL; |
83 idealreg2debugmask[Op_RegF] = NULL; | |
84 idealreg2debugmask[Op_RegD] = NULL; | |
85 idealreg2debugmask[Op_RegP] = NULL; | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
86 debug_only(_mem_node = NULL;) // Ideal memory node consumed by mach node |
0 | 87 } |
88 | |
89 //------------------------------warp_incoming_stk_arg------------------------ | |
90 // This warps a VMReg into an OptoReg::Name | |
91 OptoReg::Name Matcher::warp_incoming_stk_arg( VMReg reg ) { | |
92 OptoReg::Name warped; | |
93 if( reg->is_stack() ) { // Stack slot argument? | |
94 warped = OptoReg::add(_old_SP, reg->reg2stack() ); | |
95 warped = OptoReg::add(warped, C->out_preserve_stack_slots()); | |
96 if( warped >= _in_arg_limit ) | |
97 _in_arg_limit = OptoReg::add(warped, 1); // Bump max stack slot seen | |
98 if (!RegMask::can_represent(warped)) { | |
99 // the compiler cannot represent this method's calling sequence | |
100 C->record_method_not_compilable_all_tiers("unsupported incoming calling sequence"); | |
101 return OptoReg::Bad; | |
102 } | |
103 return warped; | |
104 } | |
105 return OptoReg::as_OptoReg(reg); | |
106 } | |
107 | |
108 //---------------------------compute_old_SP------------------------------------ | |
109 OptoReg::Name Compile::compute_old_SP() { | |
110 int fixed = fixed_slots(); | |
111 int preserve = in_preserve_stack_slots(); | |
112 return OptoReg::stack2reg(round_to(fixed + preserve, Matcher::stack_alignment_in_slots())); | |
113 } | |
114 | |
115 | |
116 | |
117 #ifdef ASSERT | |
118 void Matcher::verify_new_nodes_only(Node* xroot) { | |
119 // Make sure that the new graph only references new nodes | |
120 ResourceMark rm; | |
121 Unique_Node_List worklist; | |
122 VectorSet visited(Thread::current()->resource_area()); | |
123 worklist.push(xroot); | |
124 while (worklist.size() > 0) { | |
125 Node* n = worklist.pop(); | |
126 visited <<= n->_idx; | |
127 assert(C->node_arena()->contains(n), "dead node"); | |
128 for (uint j = 0; j < n->req(); j++) { | |
129 Node* in = n->in(j); | |
130 if (in != NULL) { | |
131 assert(C->node_arena()->contains(in), "dead node"); | |
132 if (!visited.test(in->_idx)) { | |
133 worklist.push(in); | |
134 } | |
135 } | |
136 } | |
137 } | |
138 } | |
139 #endif | |
140 | |
141 | |
142 //---------------------------match--------------------------------------------- | |
143 void Matcher::match( ) { | |
823
14367225a853
6841800: Incorrect boundary values behavior for option -XX:MaxLabelRootDepth=0-6 leads to jvm crash
kvn
parents:
729
diff
changeset
|
144 if( MaxLabelRootDepth < 100 ) { // Too small? |
14367225a853
6841800: Incorrect boundary values behavior for option -XX:MaxLabelRootDepth=0-6 leads to jvm crash
kvn
parents:
729
diff
changeset
|
145 assert(false, "invalid MaxLabelRootDepth, increase it to 100 minimum"); |
14367225a853
6841800: Incorrect boundary values behavior for option -XX:MaxLabelRootDepth=0-6 leads to jvm crash
kvn
parents:
729
diff
changeset
|
146 MaxLabelRootDepth = 100; |
14367225a853
6841800: Incorrect boundary values behavior for option -XX:MaxLabelRootDepth=0-6 leads to jvm crash
kvn
parents:
729
diff
changeset
|
147 } |
0 | 148 // One-time initialization of some register masks. |
149 init_spill_mask( C->root()->in(1) ); | |
150 _return_addr_mask = return_addr(); | |
151 #ifdef _LP64 | |
152 // Pointers take 2 slots in 64-bit land | |
153 _return_addr_mask.Insert(OptoReg::add(return_addr(),1)); | |
154 #endif | |
155 | |
156 // Map a Java-signature return type into return register-value | |
157 // machine registers for 0, 1 and 2 returned values. | |
158 const TypeTuple *range = C->tf()->range(); | |
159 if( range->cnt() > TypeFunc::Parms ) { // If not a void function | |
160 // Get ideal-register return type | |
161 int ireg = base2reg[range->field_at(TypeFunc::Parms)->base()]; | |
162 // Get machine return register | |
163 uint sop = C->start()->Opcode(); | |
164 OptoRegPair regs = return_value(ireg, false); | |
165 | |
166 // And mask for same | |
167 _return_value_mask = RegMask(regs.first()); | |
168 if( OptoReg::is_valid(regs.second()) ) | |
169 _return_value_mask.Insert(regs.second()); | |
170 } | |
171 | |
172 // --------------- | |
173 // Frame Layout | |
174 | |
175 // Need the method signature to determine the incoming argument types, | |
176 // because the types determine which registers the incoming arguments are | |
177 // in, and this affects the matched code. | |
178 const TypeTuple *domain = C->tf()->domain(); | |
179 uint argcnt = domain->cnt() - TypeFunc::Parms; | |
180 BasicType *sig_bt = NEW_RESOURCE_ARRAY( BasicType, argcnt ); | |
181 VMRegPair *vm_parm_regs = NEW_RESOURCE_ARRAY( VMRegPair, argcnt ); | |
182 _parm_regs = NEW_RESOURCE_ARRAY( OptoRegPair, argcnt ); | |
183 _calling_convention_mask = NEW_RESOURCE_ARRAY( RegMask, argcnt ); | |
184 uint i; | |
185 for( i = 0; i<argcnt; i++ ) { | |
186 sig_bt[i] = domain->field_at(i+TypeFunc::Parms)->basic_type(); | |
187 } | |
188 | |
189 // Pass array of ideal registers and length to USER code (from the AD file) | |
190 // that will convert this to an array of register numbers. | |
191 const StartNode *start = C->start(); | |
192 start->calling_convention( sig_bt, vm_parm_regs, argcnt ); | |
193 #ifdef ASSERT | |
194 // Sanity check users' calling convention. Real handy while trying to | |
195 // get the initial port correct. | |
196 { for (uint i = 0; i<argcnt; i++) { | |
197 if( !vm_parm_regs[i].first()->is_valid() && !vm_parm_regs[i].second()->is_valid() ) { | |
198 assert(domain->field_at(i+TypeFunc::Parms)==Type::HALF, "only allowed on halve" ); | |
199 _parm_regs[i].set_bad(); | |
200 continue; | |
201 } | |
202 VMReg parm_reg = vm_parm_regs[i].first(); | |
203 assert(parm_reg->is_valid(), "invalid arg?"); | |
204 if (parm_reg->is_reg()) { | |
205 OptoReg::Name opto_parm_reg = OptoReg::as_OptoReg(parm_reg); | |
206 assert(can_be_java_arg(opto_parm_reg) || | |
207 C->stub_function() == CAST_FROM_FN_PTR(address, OptoRuntime::rethrow_C) || | |
208 opto_parm_reg == inline_cache_reg(), | |
209 "parameters in register must be preserved by runtime stubs"); | |
210 } | |
211 for (uint j = 0; j < i; j++) { | |
212 assert(parm_reg != vm_parm_regs[j].first(), | |
213 "calling conv. must produce distinct regs"); | |
214 } | |
215 } | |
216 } | |
217 #endif | |
218 | |
219 // Do some initial frame layout. | |
220 | |
221 // Compute the old incoming SP (may be called FP) as | |
222 // OptoReg::stack0() + locks + in_preserve_stack_slots + pad2. | |
223 _old_SP = C->compute_old_SP(); | |
224 assert( is_even(_old_SP), "must be even" ); | |
225 | |
226 // Compute highest incoming stack argument as | |
227 // _old_SP + out_preserve_stack_slots + incoming argument size. | |
228 _in_arg_limit = OptoReg::add(_old_SP, C->out_preserve_stack_slots()); | |
229 assert( is_even(_in_arg_limit), "out_preserve must be even" ); | |
230 for( i = 0; i < argcnt; i++ ) { | |
231 // Permit args to have no register | |
232 _calling_convention_mask[i].Clear(); | |
233 if( !vm_parm_regs[i].first()->is_valid() && !vm_parm_regs[i].second()->is_valid() ) { | |
234 continue; | |
235 } | |
236 // calling_convention returns stack arguments as a count of | |
237 // slots beyond OptoReg::stack0()/VMRegImpl::stack0. We need to convert this to | |
238 // the allocators point of view, taking into account all the | |
239 // preserve area, locks & pad2. | |
240 | |
241 OptoReg::Name reg1 = warp_incoming_stk_arg(vm_parm_regs[i].first()); | |
242 if( OptoReg::is_valid(reg1)) | |
243 _calling_convention_mask[i].Insert(reg1); | |
244 | |
245 OptoReg::Name reg2 = warp_incoming_stk_arg(vm_parm_regs[i].second()); | |
246 if( OptoReg::is_valid(reg2)) | |
247 _calling_convention_mask[i].Insert(reg2); | |
248 | |
249 // Saved biased stack-slot register number | |
250 _parm_regs[i].set_pair(reg2, reg1); | |
251 } | |
252 | |
253 // Finally, make sure the incoming arguments take up an even number of | |
254 // words, in case the arguments or locals need to contain doubleword stack | |
255 // slots. The rest of the system assumes that stack slot pairs (in | |
256 // particular, in the spill area) which look aligned will in fact be | |
257 // aligned relative to the stack pointer in the target machine. Double | |
258 // stack slots will always be allocated aligned. | |
259 _new_SP = OptoReg::Name(round_to(_in_arg_limit, RegMask::SlotsPerLong)); | |
260 | |
261 // Compute highest outgoing stack argument as | |
262 // _new_SP + out_preserve_stack_slots + max(outgoing argument size). | |
263 _out_arg_limit = OptoReg::add(_new_SP, C->out_preserve_stack_slots()); | |
264 assert( is_even(_out_arg_limit), "out_preserve must be even" ); | |
265 | |
266 if (!RegMask::can_represent(OptoReg::add(_out_arg_limit,-1))) { | |
267 // the compiler cannot represent this method's calling sequence | |
268 C->record_method_not_compilable("must be able to represent all call arguments in reg mask"); | |
269 } | |
270 | |
271 if (C->failing()) return; // bailed out on incoming arg failure | |
272 | |
273 // --------------- | |
274 // Collect roots of matcher trees. Every node for which | |
275 // _shared[_idx] is cleared is guaranteed to not be shared, and thus | |
276 // can be a valid interior of some tree. | |
277 find_shared( C->root() ); | |
278 find_shared( C->top() ); | |
279 | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
309
diff
changeset
|
280 C->print_method("Before Matching"); |
0 | 281 |
729
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
282 // Create new ideal node ConP #NULL even if it does exist in old space |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
283 // to avoid false sharing if the corresponding mach node is not used. |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
284 // The corresponding mach node is only used in rare cases for derived |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
285 // pointers. |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
286 Node* new_ideal_null = ConNode::make(C, TypePtr::NULL_PTR); |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
287 |
0 | 288 // Swap out to old-space; emptying new-space |
289 Arena *old = C->node_arena()->move_contents(C->old_arena()); | |
290 | |
291 // Save debug and profile information for nodes in old space: | |
292 _old_node_note_array = C->node_note_array(); | |
293 if (_old_node_note_array != NULL) { | |
294 C->set_node_note_array(new(C->comp_arena()) GrowableArray<Node_Notes*> | |
295 (C->comp_arena(), _old_node_note_array->length(), | |
296 0, NULL)); | |
297 } | |
298 | |
299 // Pre-size the new_node table to avoid the need for range checks. | |
300 grow_new_node_array(C->unique()); | |
301 | |
302 // Reset node counter so MachNodes start with _idx at 0 | |
303 int nodes = C->unique(); // save value | |
304 C->set_unique(0); | |
305 | |
306 // Recursively match trees from old space into new space. | |
307 // Correct leaves of new-space Nodes; they point to old-space. | |
308 _visited.Clear(); // Clear visit bits for xform call | |
309 C->set_cached_top_node(xform( C->top(), nodes )); | |
310 if (!C->failing()) { | |
311 Node* xroot = xform( C->root(), 1 ); | |
312 if (xroot == NULL) { | |
313 Matcher::soft_match_failure(); // recursive matching process failed | |
314 C->record_method_not_compilable("instruction match failed"); | |
315 } else { | |
316 // During matching shared constants were attached to C->root() | |
317 // because xroot wasn't available yet, so transfer the uses to | |
318 // the xroot. | |
319 for( DUIterator_Fast jmax, j = C->root()->fast_outs(jmax); j < jmax; j++ ) { | |
320 Node* n = C->root()->fast_out(j); | |
321 if (C->node_arena()->contains(n)) { | |
322 assert(n->in(0) == C->root(), "should be control user"); | |
323 n->set_req(0, xroot); | |
324 --j; | |
325 --jmax; | |
326 } | |
327 } | |
328 | |
729
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
329 // Generate new mach node for ConP #NULL |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
330 assert(new_ideal_null != NULL, "sanity"); |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
331 _mach_null = match_tree(new_ideal_null); |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
332 // Don't set control, it will confuse GCM since there are no uses. |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
333 // The control will be set when this node is used first time |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
334 // in find_base_for_derived(). |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
335 assert(_mach_null != NULL, ""); |
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
336 |
0 | 337 C->set_root(xroot->is_Root() ? xroot->as_Root() : NULL); |
729
04fa5affa478
6709742: find_base_for_derived's use of Ideal NULL is unsafe causing crashes during register allocation
kvn
parents:
681
diff
changeset
|
338 |
0 | 339 #ifdef ASSERT |
340 verify_new_nodes_only(xroot); | |
341 #endif | |
342 } | |
343 } | |
344 if (C->top() == NULL || C->root() == NULL) { | |
345 C->record_method_not_compilable("graph lost"); // %%% cannot happen? | |
346 } | |
347 if (C->failing()) { | |
348 // delete old; | |
349 old->destruct_contents(); | |
350 return; | |
351 } | |
352 assert( C->top(), "" ); | |
353 assert( C->root(), "" ); | |
354 validate_null_checks(); | |
355 | |
356 // Now smoke old-space | |
357 NOT_DEBUG( old->destruct_contents() ); | |
358 | |
359 // ------------------------ | |
360 // Set up save-on-entry registers | |
361 Fixup_Save_On_Entry( ); | |
362 } | |
363 | |
364 | |
365 //------------------------------Fixup_Save_On_Entry---------------------------- | |
366 // The stated purpose of this routine is to take care of save-on-entry | |
367 // registers. However, the overall goal of the Match phase is to convert into | |
368 // machine-specific instructions which have RegMasks to guide allocation. | |
369 // So what this procedure really does is put a valid RegMask on each input | |
370 // to the machine-specific variations of all Return, TailCall and Halt | |
371 // instructions. It also adds edgs to define the save-on-entry values (and of | |
372 // course gives them a mask). | |
373 | |
374 static RegMask *init_input_masks( uint size, RegMask &ret_adr, RegMask &fp ) { | |
375 RegMask *rms = NEW_RESOURCE_ARRAY( RegMask, size ); | |
376 // Do all the pre-defined register masks | |
377 rms[TypeFunc::Control ] = RegMask::Empty; | |
378 rms[TypeFunc::I_O ] = RegMask::Empty; | |
379 rms[TypeFunc::Memory ] = RegMask::Empty; | |
380 rms[TypeFunc::ReturnAdr] = ret_adr; | |
381 rms[TypeFunc::FramePtr ] = fp; | |
382 return rms; | |
383 } | |
384 | |
385 //---------------------------init_first_stack_mask----------------------------- | |
386 // Create the initial stack mask used by values spilling to the stack. | |
387 // Disallow any debug info in outgoing argument areas by setting the | |
388 // initial mask accordingly. | |
389 void Matcher::init_first_stack_mask() { | |
390 | |
391 // Allocate storage for spill masks as masks for the appropriate load type. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
392 RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask)*12); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
393 idealreg2spillmask[Op_RegN] = &rms[0]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
394 idealreg2spillmask[Op_RegI] = &rms[1]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
395 idealreg2spillmask[Op_RegL] = &rms[2]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
396 idealreg2spillmask[Op_RegF] = &rms[3]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
397 idealreg2spillmask[Op_RegD] = &rms[4]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
398 idealreg2spillmask[Op_RegP] = &rms[5]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
399 idealreg2debugmask[Op_RegN] = &rms[6]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
400 idealreg2debugmask[Op_RegI] = &rms[7]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
401 idealreg2debugmask[Op_RegL] = &rms[8]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
402 idealreg2debugmask[Op_RegF] = &rms[9]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
403 idealreg2debugmask[Op_RegD] = &rms[10]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
404 idealreg2debugmask[Op_RegP] = &rms[11]; |
0 | 405 |
406 OptoReg::Name i; | |
407 | |
408 // At first, start with the empty mask | |
409 C->FIRST_STACK_mask().Clear(); | |
410 | |
411 // Add in the incoming argument area | |
412 OptoReg::Name init = OptoReg::add(_old_SP, C->out_preserve_stack_slots()); | |
413 for (i = init; i < _in_arg_limit; i = OptoReg::add(i,1)) | |
414 C->FIRST_STACK_mask().Insert(i); | |
415 | |
416 // Add in all bits past the outgoing argument area | |
417 guarantee(RegMask::can_represent(OptoReg::add(_out_arg_limit,-1)), | |
418 "must be able to represent all call arguments in reg mask"); | |
419 init = _out_arg_limit; | |
420 for (i = init; RegMask::can_represent(i); i = OptoReg::add(i,1)) | |
421 C->FIRST_STACK_mask().Insert(i); | |
422 | |
423 // Finally, set the "infinite stack" bit. | |
424 C->FIRST_STACK_mask().set_AllStack(); | |
425 | |
426 // Make spill masks. Registers for their class, plus FIRST_STACK_mask. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
427 #ifdef _LP64 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
428 *idealreg2spillmask[Op_RegN] = *idealreg2regmask[Op_RegN]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
429 idealreg2spillmask[Op_RegN]->OR(C->FIRST_STACK_mask()); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
430 #endif |
0 | 431 *idealreg2spillmask[Op_RegI] = *idealreg2regmask[Op_RegI]; |
432 idealreg2spillmask[Op_RegI]->OR(C->FIRST_STACK_mask()); | |
433 *idealreg2spillmask[Op_RegL] = *idealreg2regmask[Op_RegL]; | |
434 idealreg2spillmask[Op_RegL]->OR(C->FIRST_STACK_mask()); | |
435 *idealreg2spillmask[Op_RegF] = *idealreg2regmask[Op_RegF]; | |
436 idealreg2spillmask[Op_RegF]->OR(C->FIRST_STACK_mask()); | |
437 *idealreg2spillmask[Op_RegD] = *idealreg2regmask[Op_RegD]; | |
438 idealreg2spillmask[Op_RegD]->OR(C->FIRST_STACK_mask()); | |
439 *idealreg2spillmask[Op_RegP] = *idealreg2regmask[Op_RegP]; | |
440 idealreg2spillmask[Op_RegP]->OR(C->FIRST_STACK_mask()); | |
441 | |
442 // Make up debug masks. Any spill slot plus callee-save registers. | |
443 // Caller-save registers are assumed to be trashable by the various | |
444 // inline-cache fixup routines. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
445 *idealreg2debugmask[Op_RegN]= *idealreg2spillmask[Op_RegN]; |
0 | 446 *idealreg2debugmask[Op_RegI]= *idealreg2spillmask[Op_RegI]; |
447 *idealreg2debugmask[Op_RegL]= *idealreg2spillmask[Op_RegL]; | |
448 *idealreg2debugmask[Op_RegF]= *idealreg2spillmask[Op_RegF]; | |
449 *idealreg2debugmask[Op_RegD]= *idealreg2spillmask[Op_RegD]; | |
450 *idealreg2debugmask[Op_RegP]= *idealreg2spillmask[Op_RegP]; | |
451 | |
452 // Prevent stub compilations from attempting to reference | |
453 // callee-saved registers from debug info | |
454 bool exclude_soe = !Compile::current()->is_method_compilation(); | |
455 | |
456 for( i=OptoReg::Name(0); i<OptoReg::Name(_last_Mach_Reg); i = OptoReg::add(i,1) ) { | |
457 // registers the caller has to save do not work | |
458 if( _register_save_policy[i] == 'C' || | |
459 _register_save_policy[i] == 'A' || | |
460 (_register_save_policy[i] == 'E' && exclude_soe) ) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
461 idealreg2debugmask[Op_RegN]->Remove(i); |
0 | 462 idealreg2debugmask[Op_RegI]->Remove(i); // Exclude save-on-call |
463 idealreg2debugmask[Op_RegL]->Remove(i); // registers from debug | |
464 idealreg2debugmask[Op_RegF]->Remove(i); // masks | |
465 idealreg2debugmask[Op_RegD]->Remove(i); | |
466 idealreg2debugmask[Op_RegP]->Remove(i); | |
467 } | |
468 } | |
469 } | |
470 | |
471 //---------------------------is_save_on_entry---------------------------------- | |
472 bool Matcher::is_save_on_entry( int reg ) { | |
473 return | |
474 _register_save_policy[reg] == 'E' || | |
475 _register_save_policy[reg] == 'A' || // Save-on-entry register? | |
476 // Also save argument registers in the trampolining stubs | |
477 (C->save_argument_registers() && is_spillable_arg(reg)); | |
478 } | |
479 | |
480 //---------------------------Fixup_Save_On_Entry------------------------------- | |
481 void Matcher::Fixup_Save_On_Entry( ) { | |
482 init_first_stack_mask(); | |
483 | |
484 Node *root = C->root(); // Short name for root | |
485 // Count number of save-on-entry registers. | |
486 uint soe_cnt = number_of_saved_registers(); | |
487 uint i; | |
488 | |
489 // Find the procedure Start Node | |
490 StartNode *start = C->start(); | |
491 assert( start, "Expect a start node" ); | |
492 | |
493 // Save argument registers in the trampolining stubs | |
494 if( C->save_argument_registers() ) | |
495 for( i = 0; i < _last_Mach_Reg; i++ ) | |
496 if( is_spillable_arg(i) ) | |
497 soe_cnt++; | |
498 | |
499 // Input RegMask array shared by all Returns. | |
500 // The type for doubles and longs has a count of 2, but | |
501 // there is only 1 returned value | |
502 uint ret_edge_cnt = TypeFunc::Parms + ((C->tf()->range()->cnt() == TypeFunc::Parms) ? 0 : 1); | |
503 RegMask *ret_rms = init_input_masks( ret_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask ); | |
504 // Returns have 0 or 1 returned values depending on call signature. | |
505 // Return register is specified by return_value in the AD file. | |
506 if (ret_edge_cnt > TypeFunc::Parms) | |
507 ret_rms[TypeFunc::Parms+0] = _return_value_mask; | |
508 | |
509 // Input RegMask array shared by all Rethrows. | |
510 uint reth_edge_cnt = TypeFunc::Parms+1; | |
511 RegMask *reth_rms = init_input_masks( reth_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask ); | |
512 // Rethrow takes exception oop only, but in the argument 0 slot. | |
513 reth_rms[TypeFunc::Parms] = mreg2regmask[find_receiver(false)]; | |
514 #ifdef _LP64 | |
515 // Need two slots for ptrs in 64-bit land | |
516 reth_rms[TypeFunc::Parms].Insert(OptoReg::add(OptoReg::Name(find_receiver(false)),1)); | |
517 #endif | |
518 | |
519 // Input RegMask array shared by all TailCalls | |
520 uint tail_call_edge_cnt = TypeFunc::Parms+2; | |
521 RegMask *tail_call_rms = init_input_masks( tail_call_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask ); | |
522 | |
523 // Input RegMask array shared by all TailJumps | |
524 uint tail_jump_edge_cnt = TypeFunc::Parms+2; | |
525 RegMask *tail_jump_rms = init_input_masks( tail_jump_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask ); | |
526 | |
527 // TailCalls have 2 returned values (target & moop), whose masks come | |
528 // from the usual MachNode/MachOper mechanism. Find a sample | |
529 // TailCall to extract these masks and put the correct masks into | |
530 // the tail_call_rms array. | |
531 for( i=1; i < root->req(); i++ ) { | |
532 MachReturnNode *m = root->in(i)->as_MachReturn(); | |
533 if( m->ideal_Opcode() == Op_TailCall ) { | |
534 tail_call_rms[TypeFunc::Parms+0] = m->MachNode::in_RegMask(TypeFunc::Parms+0); | |
535 tail_call_rms[TypeFunc::Parms+1] = m->MachNode::in_RegMask(TypeFunc::Parms+1); | |
536 break; | |
537 } | |
538 } | |
539 | |
540 // TailJumps have 2 returned values (target & ex_oop), whose masks come | |
541 // from the usual MachNode/MachOper mechanism. Find a sample | |
542 // TailJump to extract these masks and put the correct masks into | |
543 // the tail_jump_rms array. | |
544 for( i=1; i < root->req(); i++ ) { | |
545 MachReturnNode *m = root->in(i)->as_MachReturn(); | |
546 if( m->ideal_Opcode() == Op_TailJump ) { | |
547 tail_jump_rms[TypeFunc::Parms+0] = m->MachNode::in_RegMask(TypeFunc::Parms+0); | |
548 tail_jump_rms[TypeFunc::Parms+1] = m->MachNode::in_RegMask(TypeFunc::Parms+1); | |
549 break; | |
550 } | |
551 } | |
552 | |
553 // Input RegMask array shared by all Halts | |
554 uint halt_edge_cnt = TypeFunc::Parms; | |
555 RegMask *halt_rms = init_input_masks( halt_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask ); | |
556 | |
557 // Capture the return input masks into each exit flavor | |
558 for( i=1; i < root->req(); i++ ) { | |
559 MachReturnNode *exit = root->in(i)->as_MachReturn(); | |
560 switch( exit->ideal_Opcode() ) { | |
561 case Op_Return : exit->_in_rms = ret_rms; break; | |
562 case Op_Rethrow : exit->_in_rms = reth_rms; break; | |
563 case Op_TailCall : exit->_in_rms = tail_call_rms; break; | |
564 case Op_TailJump : exit->_in_rms = tail_jump_rms; break; | |
565 case Op_Halt : exit->_in_rms = halt_rms; break; | |
566 default : ShouldNotReachHere(); | |
567 } | |
568 } | |
569 | |
570 // Next unused projection number from Start. | |
571 int proj_cnt = C->tf()->domain()->cnt(); | |
572 | |
573 // Do all the save-on-entry registers. Make projections from Start for | |
574 // them, and give them a use at the exit points. To the allocator, they | |
575 // look like incoming register arguments. | |
576 for( i = 0; i < _last_Mach_Reg; i++ ) { | |
577 if( is_save_on_entry(i) ) { | |
578 | |
579 // Add the save-on-entry to the mask array | |
580 ret_rms [ ret_edge_cnt] = mreg2regmask[i]; | |
581 reth_rms [ reth_edge_cnt] = mreg2regmask[i]; | |
582 tail_call_rms[tail_call_edge_cnt] = mreg2regmask[i]; | |
583 tail_jump_rms[tail_jump_edge_cnt] = mreg2regmask[i]; | |
584 // Halts need the SOE registers, but only in the stack as debug info. | |
585 // A just-prior uncommon-trap or deoptimization will use the SOE regs. | |
586 halt_rms [ halt_edge_cnt] = *idealreg2spillmask[_register_save_type[i]]; | |
587 | |
588 Node *mproj; | |
589 | |
590 // Is this a RegF low half of a RegD? Double up 2 adjacent RegF's | |
591 // into a single RegD. | |
592 if( (i&1) == 0 && | |
593 _register_save_type[i ] == Op_RegF && | |
594 _register_save_type[i+1] == Op_RegF && | |
595 is_save_on_entry(i+1) ) { | |
596 // Add other bit for double | |
597 ret_rms [ ret_edge_cnt].Insert(OptoReg::Name(i+1)); | |
598 reth_rms [ reth_edge_cnt].Insert(OptoReg::Name(i+1)); | |
599 tail_call_rms[tail_call_edge_cnt].Insert(OptoReg::Name(i+1)); | |
600 tail_jump_rms[tail_jump_edge_cnt].Insert(OptoReg::Name(i+1)); | |
601 halt_rms [ halt_edge_cnt].Insert(OptoReg::Name(i+1)); | |
602 mproj = new (C, 1) MachProjNode( start, proj_cnt, ret_rms[ret_edge_cnt], Op_RegD ); | |
603 proj_cnt += 2; // Skip 2 for doubles | |
604 } | |
605 else if( (i&1) == 1 && // Else check for high half of double | |
606 _register_save_type[i-1] == Op_RegF && | |
607 _register_save_type[i ] == Op_RegF && | |
608 is_save_on_entry(i-1) ) { | |
609 ret_rms [ ret_edge_cnt] = RegMask::Empty; | |
610 reth_rms [ reth_edge_cnt] = RegMask::Empty; | |
611 tail_call_rms[tail_call_edge_cnt] = RegMask::Empty; | |
612 tail_jump_rms[tail_jump_edge_cnt] = RegMask::Empty; | |
613 halt_rms [ halt_edge_cnt] = RegMask::Empty; | |
614 mproj = C->top(); | |
615 } | |
616 // Is this a RegI low half of a RegL? Double up 2 adjacent RegI's | |
617 // into a single RegL. | |
618 else if( (i&1) == 0 && | |
619 _register_save_type[i ] == Op_RegI && | |
620 _register_save_type[i+1] == Op_RegI && | |
621 is_save_on_entry(i+1) ) { | |
622 // Add other bit for long | |
623 ret_rms [ ret_edge_cnt].Insert(OptoReg::Name(i+1)); | |
624 reth_rms [ reth_edge_cnt].Insert(OptoReg::Name(i+1)); | |
625 tail_call_rms[tail_call_edge_cnt].Insert(OptoReg::Name(i+1)); | |
626 tail_jump_rms[tail_jump_edge_cnt].Insert(OptoReg::Name(i+1)); | |
627 halt_rms [ halt_edge_cnt].Insert(OptoReg::Name(i+1)); | |
628 mproj = new (C, 1) MachProjNode( start, proj_cnt, ret_rms[ret_edge_cnt], Op_RegL ); | |
629 proj_cnt += 2; // Skip 2 for longs | |
630 } | |
631 else if( (i&1) == 1 && // Else check for high half of long | |
632 _register_save_type[i-1] == Op_RegI && | |
633 _register_save_type[i ] == Op_RegI && | |
634 is_save_on_entry(i-1) ) { | |
635 ret_rms [ ret_edge_cnt] = RegMask::Empty; | |
636 reth_rms [ reth_edge_cnt] = RegMask::Empty; | |
637 tail_call_rms[tail_call_edge_cnt] = RegMask::Empty; | |
638 tail_jump_rms[tail_jump_edge_cnt] = RegMask::Empty; | |
639 halt_rms [ halt_edge_cnt] = RegMask::Empty; | |
640 mproj = C->top(); | |
641 } else { | |
642 // Make a projection for it off the Start | |
643 mproj = new (C, 1) MachProjNode( start, proj_cnt++, ret_rms[ret_edge_cnt], _register_save_type[i] ); | |
644 } | |
645 | |
646 ret_edge_cnt ++; | |
647 reth_edge_cnt ++; | |
648 tail_call_edge_cnt ++; | |
649 tail_jump_edge_cnt ++; | |
650 halt_edge_cnt ++; | |
651 | |
652 // Add a use of the SOE register to all exit paths | |
653 for( uint j=1; j < root->req(); j++ ) | |
654 root->in(j)->add_req(mproj); | |
655 } // End of if a save-on-entry register | |
656 } // End of for all machine registers | |
657 } | |
658 | |
659 //------------------------------init_spill_mask-------------------------------- | |
660 void Matcher::init_spill_mask( Node *ret ) { | |
661 if( idealreg2regmask[Op_RegI] ) return; // One time only init | |
662 | |
663 OptoReg::c_frame_pointer = c_frame_pointer(); | |
664 c_frame_ptr_mask = c_frame_pointer(); | |
665 #ifdef _LP64 | |
666 // pointers are twice as big | |
667 c_frame_ptr_mask.Insert(OptoReg::add(c_frame_pointer(),1)); | |
668 #endif | |
669 | |
670 // Start at OptoReg::stack0() | |
671 STACK_ONLY_mask.Clear(); | |
672 OptoReg::Name init = OptoReg::stack2reg(0); | |
673 // STACK_ONLY_mask is all stack bits | |
674 OptoReg::Name i; | |
675 for (i = init; RegMask::can_represent(i); i = OptoReg::add(i,1)) | |
676 STACK_ONLY_mask.Insert(i); | |
677 // Also set the "infinite stack" bit. | |
678 STACK_ONLY_mask.set_AllStack(); | |
679 | |
680 // Copy the register names over into the shared world | |
681 for( i=OptoReg::Name(0); i<OptoReg::Name(_last_Mach_Reg); i = OptoReg::add(i,1) ) { | |
682 // SharedInfo::regName[i] = regName[i]; | |
683 // Handy RegMasks per machine register | |
684 mreg2regmask[i].Insert(i); | |
685 } | |
686 | |
687 // Grab the Frame Pointer | |
688 Node *fp = ret->in(TypeFunc::FramePtr); | |
689 Node *mem = ret->in(TypeFunc::Memory); | |
690 const TypePtr* atp = TypePtr::BOTTOM; | |
691 // Share frame pointer while making spill ops | |
692 set_shared(fp); | |
693 | |
694 // Compute generic short-offset Loads | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
695 #ifdef _LP64 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
696 MachNode *spillCP = match_tree(new (C, 3) LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM)); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
697 #endif |
0 | 698 MachNode *spillI = match_tree(new (C, 3) LoadINode(NULL,mem,fp,atp)); |
699 MachNode *spillL = match_tree(new (C, 3) LoadLNode(NULL,mem,fp,atp)); | |
700 MachNode *spillF = match_tree(new (C, 3) LoadFNode(NULL,mem,fp,atp)); | |
701 MachNode *spillD = match_tree(new (C, 3) LoadDNode(NULL,mem,fp,atp)); | |
702 MachNode *spillP = match_tree(new (C, 3) LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM)); | |
703 assert(spillI != NULL && spillL != NULL && spillF != NULL && | |
704 spillD != NULL && spillP != NULL, ""); | |
705 | |
706 // Get the ADLC notion of the right regmask, for each basic type. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
707 #ifdef _LP64 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
708 idealreg2regmask[Op_RegN] = &spillCP->out_RegMask(); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
709 #endif |
0 | 710 idealreg2regmask[Op_RegI] = &spillI->out_RegMask(); |
711 idealreg2regmask[Op_RegL] = &spillL->out_RegMask(); | |
712 idealreg2regmask[Op_RegF] = &spillF->out_RegMask(); | |
713 idealreg2regmask[Op_RegD] = &spillD->out_RegMask(); | |
714 idealreg2regmask[Op_RegP] = &spillP->out_RegMask(); | |
715 } | |
716 | |
717 #ifdef ASSERT | |
718 static void match_alias_type(Compile* C, Node* n, Node* m) { | |
719 if (!VerifyAliases) return; // do not go looking for trouble by default | |
720 const TypePtr* nat = n->adr_type(); | |
721 const TypePtr* mat = m->adr_type(); | |
722 int nidx = C->get_alias_index(nat); | |
723 int midx = C->get_alias_index(mat); | |
724 // Detune the assert for cases like (AndI 0xFF (LoadB p)). | |
725 if (nidx == Compile::AliasIdxTop && midx >= Compile::AliasIdxRaw) { | |
726 for (uint i = 1; i < n->req(); i++) { | |
727 Node* n1 = n->in(i); | |
728 const TypePtr* n1at = n1->adr_type(); | |
729 if (n1at != NULL) { | |
730 nat = n1at; | |
731 nidx = C->get_alias_index(n1at); | |
732 } | |
733 } | |
734 } | |
735 // %%% Kludgery. Instead, fix ideal adr_type methods for all these cases: | |
736 if (nidx == Compile::AliasIdxTop && midx == Compile::AliasIdxRaw) { | |
737 switch (n->Opcode()) { | |
738 case Op_PrefetchRead: | |
739 case Op_PrefetchWrite: | |
740 nidx = Compile::AliasIdxRaw; | |
741 nat = TypeRawPtr::BOTTOM; | |
742 break; | |
743 } | |
744 } | |
745 if (nidx == Compile::AliasIdxRaw && midx == Compile::AliasIdxTop) { | |
746 switch (n->Opcode()) { | |
747 case Op_ClearArray: | |
748 midx = Compile::AliasIdxRaw; | |
749 mat = TypeRawPtr::BOTTOM; | |
750 break; | |
751 } | |
752 } | |
753 if (nidx == Compile::AliasIdxTop && midx == Compile::AliasIdxBot) { | |
754 switch (n->Opcode()) { | |
755 case Op_Return: | |
756 case Op_Rethrow: | |
757 case Op_Halt: | |
758 case Op_TailCall: | |
759 case Op_TailJump: | |
760 nidx = Compile::AliasIdxBot; | |
761 nat = TypePtr::BOTTOM; | |
762 break; | |
763 } | |
764 } | |
765 if (nidx == Compile::AliasIdxBot && midx == Compile::AliasIdxTop) { | |
766 switch (n->Opcode()) { | |
767 case Op_StrComp: | |
681 | 768 case Op_StrEquals: |
769 case Op_StrIndexOf: | |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
168
diff
changeset
|
770 case Op_AryEq: |
0 | 771 case Op_MemBarVolatile: |
772 case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type? | |
773 nidx = Compile::AliasIdxTop; | |
774 nat = NULL; | |
775 break; | |
776 } | |
777 } | |
778 if (nidx != midx) { | |
779 if (PrintOpto || (PrintMiscellaneous && (WizardMode || Verbose))) { | |
780 tty->print_cr("==== Matcher alias shift %d => %d", nidx, midx); | |
781 n->dump(); | |
782 m->dump(); | |
783 } | |
784 assert(C->subsume_loads() && C->must_alias(nat, midx), | |
785 "must not lose alias info when matching"); | |
786 } | |
787 } | |
788 #endif | |
789 | |
790 | |
791 //------------------------------MStack----------------------------------------- | |
792 // State and MStack class used in xform() and find_shared() iterative methods. | |
793 enum Node_State { Pre_Visit, // node has to be pre-visited | |
794 Visit, // visit node | |
795 Post_Visit, // post-visit node | |
796 Alt_Post_Visit // alternative post-visit path | |
797 }; | |
798 | |
799 class MStack: public Node_Stack { | |
800 public: | |
801 MStack(int size) : Node_Stack(size) { } | |
802 | |
803 void push(Node *n, Node_State ns) { | |
804 Node_Stack::push(n, (uint)ns); | |
805 } | |
806 void push(Node *n, Node_State ns, Node *parent, int indx) { | |
807 ++_inode_top; | |
808 if ((_inode_top + 1) >= _inode_max) grow(); | |
809 _inode_top->node = parent; | |
810 _inode_top->indx = (uint)indx; | |
811 ++_inode_top; | |
812 _inode_top->node = n; | |
813 _inode_top->indx = (uint)ns; | |
814 } | |
815 Node *parent() { | |
816 pop(); | |
817 return node(); | |
818 } | |
819 Node_State state() const { | |
820 return (Node_State)index(); | |
821 } | |
822 void set_state(Node_State ns) { | |
823 set_index((uint)ns); | |
824 } | |
825 }; | |
826 | |
827 | |
828 //------------------------------xform------------------------------------------ | |
829 // Given a Node in old-space, Match him (Label/Reduce) to produce a machine | |
830 // Node in new-space. Given a new-space Node, recursively walk his children. | |
831 Node *Matcher::transform( Node *n ) { ShouldNotCallThis(); return n; } | |
832 Node *Matcher::xform( Node *n, int max_stack ) { | |
833 // Use one stack to keep both: child's node/state and parent's node/index | |
834 MStack mstack(max_stack * 2 * 2); // C->unique() * 2 * 2 | |
835 mstack.push(n, Visit, NULL, -1); // set NULL as parent to indicate root | |
836 | |
837 while (mstack.is_nonempty()) { | |
838 n = mstack.node(); // Leave node on stack | |
839 Node_State nstate = mstack.state(); | |
840 if (nstate == Visit) { | |
841 mstack.set_state(Post_Visit); | |
842 Node *oldn = n; | |
843 // Old-space or new-space check | |
844 if (!C->node_arena()->contains(n)) { | |
845 // Old space! | |
846 Node* m; | |
847 if (has_new_node(n)) { // Not yet Label/Reduced | |
848 m = new_node(n); | |
849 } else { | |
850 if (!is_dontcare(n)) { // Matcher can match this guy | |
851 // Calls match special. They match alone with no children. | |
852 // Their children, the incoming arguments, match normally. | |
853 m = n->is_SafePoint() ? match_sfpt(n->as_SafePoint()):match_tree(n); | |
854 if (C->failing()) return NULL; | |
855 if (m == NULL) { Matcher::soft_match_failure(); return NULL; } | |
856 } else { // Nothing the matcher cares about | |
857 if( n->is_Proj() && n->in(0)->is_Multi()) { // Projections? | |
858 // Convert to machine-dependent projection | |
859 m = n->in(0)->as_Multi()->match( n->as_Proj(), this ); | |
222 | 860 #ifdef ASSERT |
861 _new2old_map.map(m->_idx, n); | |
862 #endif | |
0 | 863 if (m->in(0) != NULL) // m might be top |
368
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
864 collect_null_checks(m, n); |
0 | 865 } else { // Else just a regular 'ol guy |
866 m = n->clone(); // So just clone into new-space | |
222 | 867 #ifdef ASSERT |
868 _new2old_map.map(m->_idx, n); | |
869 #endif | |
0 | 870 // Def-Use edges will be added incrementally as Uses |
871 // of this node are matched. | |
872 assert(m->outcnt() == 0, "no Uses of this clone yet"); | |
873 } | |
874 } | |
875 | |
876 set_new_node(n, m); // Map old to new | |
877 if (_old_node_note_array != NULL) { | |
878 Node_Notes* nn = C->locate_node_notes(_old_node_note_array, | |
879 n->_idx); | |
880 C->set_node_notes_at(m->_idx, nn); | |
881 } | |
882 debug_only(match_alias_type(C, n, m)); | |
883 } | |
884 n = m; // n is now a new-space node | |
885 mstack.set_node(n); | |
886 } | |
887 | |
888 // New space! | |
889 if (_visited.test_set(n->_idx)) continue; // while(mstack.is_nonempty()) | |
890 | |
891 int i; | |
892 // Put precedence edges on stack first (match them last). | |
893 for (i = oldn->req(); (uint)i < oldn->len(); i++) { | |
894 Node *m = oldn->in(i); | |
895 if (m == NULL) break; | |
896 // set -1 to call add_prec() instead of set_req() during Step1 | |
897 mstack.push(m, Visit, n, -1); | |
898 } | |
899 | |
900 // For constant debug info, I'd rather have unmatched constants. | |
901 int cnt = n->req(); | |
902 JVMState* jvms = n->jvms(); | |
903 int debug_cnt = jvms ? jvms->debug_start() : cnt; | |
904 | |
905 // Now do only debug info. Clone constants rather than matching. | |
906 // Constants are represented directly in the debug info without | |
907 // the need for executable machine instructions. | |
908 // Monitor boxes are also represented directly. | |
909 for (i = cnt - 1; i >= debug_cnt; --i) { // For all debug inputs do | |
910 Node *m = n->in(i); // Get input | |
911 int op = m->Opcode(); | |
912 assert((op == Op_BoxLock) == jvms->is_monitor_use(i), "boxes only at monitor sites"); | |
163 | 913 if( op == Op_ConI || op == Op_ConP || op == Op_ConN || |
0 | 914 op == Op_ConF || op == Op_ConD || op == Op_ConL |
915 // || op == Op_BoxLock // %%%% enable this and remove (+++) in chaitin.cpp | |
916 ) { | |
917 m = m->clone(); | |
222 | 918 #ifdef ASSERT |
919 _new2old_map.map(m->_idx, n); | |
920 #endif | |
605 | 921 mstack.push(m, Post_Visit, n, i); // Don't need to visit |
0 | 922 mstack.push(m->in(0), Visit, m, 0); |
923 } else { | |
924 mstack.push(m, Visit, n, i); | |
925 } | |
926 } | |
927 | |
928 // And now walk his children, and convert his inputs to new-space. | |
929 for( ; i >= 0; --i ) { // For all normal inputs do | |
930 Node *m = n->in(i); // Get input | |
931 if(m != NULL) | |
932 mstack.push(m, Visit, n, i); | |
933 } | |
934 | |
935 } | |
936 else if (nstate == Post_Visit) { | |
937 // Set xformed input | |
938 Node *p = mstack.parent(); | |
939 if (p != NULL) { // root doesn't have parent | |
940 int i = (int)mstack.index(); | |
941 if (i >= 0) | |
942 p->set_req(i, n); // required input | |
943 else if (i == -1) | |
944 p->add_prec(n); // precedence input | |
945 else | |
946 ShouldNotReachHere(); | |
947 } | |
948 mstack.pop(); // remove processed node from stack | |
949 } | |
950 else { | |
951 ShouldNotReachHere(); | |
952 } | |
953 } // while (mstack.is_nonempty()) | |
954 return n; // Return new-space Node | |
955 } | |
956 | |
957 //------------------------------warp_outgoing_stk_arg------------------------ | |
958 OptoReg::Name Matcher::warp_outgoing_stk_arg( VMReg reg, OptoReg::Name begin_out_arg_area, OptoReg::Name &out_arg_limit_per_call ) { | |
959 // Convert outgoing argument location to a pre-biased stack offset | |
960 if (reg->is_stack()) { | |
961 OptoReg::Name warped = reg->reg2stack(); | |
962 // Adjust the stack slot offset to be the register number used | |
963 // by the allocator. | |
964 warped = OptoReg::add(begin_out_arg_area, warped); | |
965 // Keep track of the largest numbered stack slot used for an arg. | |
966 // Largest used slot per call-site indicates the amount of stack | |
967 // that is killed by the call. | |
968 if( warped >= out_arg_limit_per_call ) | |
969 out_arg_limit_per_call = OptoReg::add(warped,1); | |
970 if (!RegMask::can_represent(warped)) { | |
971 C->record_method_not_compilable_all_tiers("unsupported calling sequence"); | |
972 return OptoReg::Bad; | |
973 } | |
974 return warped; | |
975 } | |
976 return OptoReg::as_OptoReg(reg); | |
977 } | |
978 | |
979 | |
980 //------------------------------match_sfpt------------------------------------- | |
981 // Helper function to match call instructions. Calls match special. | |
982 // They match alone with no children. Their children, the incoming | |
983 // arguments, match normally. | |
984 MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { | |
985 MachSafePointNode *msfpt = NULL; | |
986 MachCallNode *mcall = NULL; | |
987 uint cnt; | |
988 // Split out case for SafePoint vs Call | |
989 CallNode *call; | |
990 const TypeTuple *domain; | |
991 ciMethod* method = NULL; | |
992 if( sfpt->is_Call() ) { | |
993 call = sfpt->as_Call(); | |
994 domain = call->tf()->domain(); | |
995 cnt = domain->cnt(); | |
996 | |
997 // Match just the call, nothing else | |
998 MachNode *m = match_tree(call); | |
999 if (C->failing()) return NULL; | |
1000 if( m == NULL ) { Matcher::soft_match_failure(); return NULL; } | |
1001 | |
1002 // Copy data from the Ideal SafePoint to the machine version | |
1003 mcall = m->as_MachCall(); | |
1004 | |
1005 mcall->set_tf( call->tf()); | |
1006 mcall->set_entry_point(call->entry_point()); | |
1007 mcall->set_cnt( call->cnt()); | |
1008 | |
1009 if( mcall->is_MachCallJava() ) { | |
1010 MachCallJavaNode *mcall_java = mcall->as_MachCallJava(); | |
1011 const CallJavaNode *call_java = call->as_CallJava(); | |
1012 method = call_java->method(); | |
1013 mcall_java->_method = method; | |
1014 mcall_java->_bci = call_java->_bci; | |
1015 mcall_java->_optimized_virtual = call_java->is_optimized_virtual(); | |
1016 if( mcall_java->is_MachCallStaticJava() ) | |
1017 mcall_java->as_MachCallStaticJava()->_name = | |
1018 call_java->as_CallStaticJava()->_name; | |
1019 if( mcall_java->is_MachCallDynamicJava() ) | |
1020 mcall_java->as_MachCallDynamicJava()->_vtable_index = | |
1021 call_java->as_CallDynamicJava()->_vtable_index; | |
1022 } | |
1023 else if( mcall->is_MachCallRuntime() ) { | |
1024 mcall->as_MachCallRuntime()->_name = call->as_CallRuntime()->_name; | |
1025 } | |
1026 msfpt = mcall; | |
1027 } | |
1028 // This is a non-call safepoint | |
1029 else { | |
1030 call = NULL; | |
1031 domain = NULL; | |
1032 MachNode *mn = match_tree(sfpt); | |
1033 if (C->failing()) return NULL; | |
1034 msfpt = mn->as_MachSafePoint(); | |
1035 cnt = TypeFunc::Parms; | |
1036 } | |
1037 | |
1038 // Advertise the correct memory effects (for anti-dependence computation). | |
1039 msfpt->set_adr_type(sfpt->adr_type()); | |
1040 | |
1041 // Allocate a private array of RegMasks. These RegMasks are not shared. | |
1042 msfpt->_in_rms = NEW_RESOURCE_ARRAY( RegMask, cnt ); | |
1043 // Empty them all. | |
1044 memset( msfpt->_in_rms, 0, sizeof(RegMask)*cnt ); | |
1045 | |
1046 // Do all the pre-defined non-Empty register masks | |
1047 msfpt->_in_rms[TypeFunc::ReturnAdr] = _return_addr_mask; | |
1048 msfpt->_in_rms[TypeFunc::FramePtr ] = c_frame_ptr_mask; | |
1049 | |
1050 // Place first outgoing argument can possibly be put. | |
1051 OptoReg::Name begin_out_arg_area = OptoReg::add(_new_SP, C->out_preserve_stack_slots()); | |
1052 assert( is_even(begin_out_arg_area), "" ); | |
1053 // Compute max outgoing register number per call site. | |
1054 OptoReg::Name out_arg_limit_per_call = begin_out_arg_area; | |
1055 // Calls to C may hammer extra stack slots above and beyond any arguments. | |
1056 // These are usually backing store for register arguments for varargs. | |
1057 if( call != NULL && call->is_CallRuntime() ) | |
1058 out_arg_limit_per_call = OptoReg::add(out_arg_limit_per_call,C->varargs_C_out_slots_killed()); | |
1059 | |
1060 | |
1061 // Do the normal argument list (parameters) register masks | |
1062 int argcnt = cnt - TypeFunc::Parms; | |
1063 if( argcnt > 0 ) { // Skip it all if we have no args | |
1064 BasicType *sig_bt = NEW_RESOURCE_ARRAY( BasicType, argcnt ); | |
1065 VMRegPair *parm_regs = NEW_RESOURCE_ARRAY( VMRegPair, argcnt ); | |
1066 int i; | |
1067 for( i = 0; i < argcnt; i++ ) { | |
1068 sig_bt[i] = domain->field_at(i+TypeFunc::Parms)->basic_type(); | |
1069 } | |
1070 // V-call to pick proper calling convention | |
1071 call->calling_convention( sig_bt, parm_regs, argcnt ); | |
1072 | |
1073 #ifdef ASSERT | |
1074 // Sanity check users' calling convention. Really handy during | |
1075 // the initial porting effort. Fairly expensive otherwise. | |
1076 { for (int i = 0; i<argcnt; i++) { | |
1077 if( !parm_regs[i].first()->is_valid() && | |
1078 !parm_regs[i].second()->is_valid() ) continue; | |
1079 VMReg reg1 = parm_regs[i].first(); | |
1080 VMReg reg2 = parm_regs[i].second(); | |
1081 for (int j = 0; j < i; j++) { | |
1082 if( !parm_regs[j].first()->is_valid() && | |
1083 !parm_regs[j].second()->is_valid() ) continue; | |
1084 VMReg reg3 = parm_regs[j].first(); | |
1085 VMReg reg4 = parm_regs[j].second(); | |
1086 if( !reg1->is_valid() ) { | |
1087 assert( !reg2->is_valid(), "valid halvsies" ); | |
1088 } else if( !reg3->is_valid() ) { | |
1089 assert( !reg4->is_valid(), "valid halvsies" ); | |
1090 } else { | |
1091 assert( reg1 != reg2, "calling conv. must produce distinct regs"); | |
1092 assert( reg1 != reg3, "calling conv. must produce distinct regs"); | |
1093 assert( reg1 != reg4, "calling conv. must produce distinct regs"); | |
1094 assert( reg2 != reg3, "calling conv. must produce distinct regs"); | |
1095 assert( reg2 != reg4 || !reg2->is_valid(), "calling conv. must produce distinct regs"); | |
1096 assert( reg3 != reg4, "calling conv. must produce distinct regs"); | |
1097 } | |
1098 } | |
1099 } | |
1100 } | |
1101 #endif | |
1102 | |
1103 // Visit each argument. Compute its outgoing register mask. | |
1104 // Return results now can have 2 bits returned. | |
1105 // Compute max over all outgoing arguments both per call-site | |
1106 // and over the entire method. | |
1107 for( i = 0; i < argcnt; i++ ) { | |
1108 // Address of incoming argument mask to fill in | |
1109 RegMask *rm = &mcall->_in_rms[i+TypeFunc::Parms]; | |
1110 if( !parm_regs[i].first()->is_valid() && | |
1111 !parm_regs[i].second()->is_valid() ) { | |
1112 continue; // Avoid Halves | |
1113 } | |
1114 // Grab first register, adjust stack slots and insert in mask. | |
1115 OptoReg::Name reg1 = warp_outgoing_stk_arg(parm_regs[i].first(), begin_out_arg_area, out_arg_limit_per_call ); | |
1116 if (OptoReg::is_valid(reg1)) | |
1117 rm->Insert( reg1 ); | |
1118 // Grab second register (if any), adjust stack slots and insert in mask. | |
1119 OptoReg::Name reg2 = warp_outgoing_stk_arg(parm_regs[i].second(), begin_out_arg_area, out_arg_limit_per_call ); | |
1120 if (OptoReg::is_valid(reg2)) | |
1121 rm->Insert( reg2 ); | |
1122 } // End of for all arguments | |
1123 | |
1124 // Compute number of stack slots needed to restore stack in case of | |
1125 // Pascal-style argument popping. | |
1126 mcall->_argsize = out_arg_limit_per_call - begin_out_arg_area; | |
1127 } | |
1128 | |
1129 // Compute the max stack slot killed by any call. These will not be | |
1130 // available for debug info, and will be used to adjust FIRST_STACK_mask | |
1131 // after all call sites have been visited. | |
1132 if( _out_arg_limit < out_arg_limit_per_call) | |
1133 _out_arg_limit = out_arg_limit_per_call; | |
1134 | |
1135 if (mcall) { | |
1136 // Kill the outgoing argument area, including any non-argument holes and | |
1137 // any legacy C-killed slots. Use Fat-Projections to do the killing. | |
1138 // Since the max-per-method covers the max-per-call-site and debug info | |
1139 // is excluded on the max-per-method basis, debug info cannot land in | |
1140 // this killed area. | |
1141 uint r_cnt = mcall->tf()->range()->cnt(); | |
1142 MachProjNode *proj = new (C, 1) MachProjNode( mcall, r_cnt+10000, RegMask::Empty, MachProjNode::fat_proj ); | |
1143 if (!RegMask::can_represent(OptoReg::Name(out_arg_limit_per_call-1))) { | |
1144 C->record_method_not_compilable_all_tiers("unsupported outgoing calling sequence"); | |
1145 } else { | |
1146 for (int i = begin_out_arg_area; i < out_arg_limit_per_call; i++) | |
1147 proj->_rout.Insert(OptoReg::Name(i)); | |
1148 } | |
1149 if( proj->_rout.is_NotEmpty() ) | |
1150 _proj_list.push(proj); | |
1151 } | |
1152 // Transfer the safepoint information from the call to the mcall | |
1153 // Move the JVMState list | |
1154 msfpt->set_jvms(sfpt->jvms()); | |
1155 for (JVMState* jvms = msfpt->jvms(); jvms; jvms = jvms->caller()) { | |
1156 jvms->set_map(sfpt); | |
1157 } | |
1158 | |
1159 // Debug inputs begin just after the last incoming parameter | |
1160 assert( (mcall == NULL) || (mcall->jvms() == NULL) || | |
1161 (mcall->jvms()->debug_start() + mcall->_jvmadj == mcall->tf()->domain()->cnt()), "" ); | |
1162 | |
1163 // Move the OopMap | |
1164 msfpt->_oop_map = sfpt->_oop_map; | |
1165 | |
1166 // Registers killed by the call are set in the local scheduling pass | |
1167 // of Global Code Motion. | |
1168 return msfpt; | |
1169 } | |
1170 | |
1171 //---------------------------match_tree---------------------------------------- | |
1172 // Match a Ideal Node DAG - turn it into a tree; Label & Reduce. Used as part | |
1173 // of the whole-sale conversion from Ideal to Mach Nodes. Also used for | |
1174 // making GotoNodes while building the CFG and in init_spill_mask() to identify | |
1175 // a Load's result RegMask for memoization in idealreg2regmask[] | |
1176 MachNode *Matcher::match_tree( const Node *n ) { | |
1177 assert( n->Opcode() != Op_Phi, "cannot match" ); | |
1178 assert( !n->is_block_start(), "cannot match" ); | |
1179 // Set the mark for all locally allocated State objects. | |
1180 // When this call returns, the _states_arena arena will be reset | |
1181 // freeing all State objects. | |
1182 ResourceMark rm( &_states_arena ); | |
1183 | |
1184 LabelRootDepth = 0; | |
1185 | |
1186 // StoreNodes require their Memory input to match any LoadNodes | |
1187 Node *mem = n->is_Store() ? n->in(MemNode::Memory) : (Node*)1 ; | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1188 #ifdef ASSERT |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1189 Node* save_mem_node = _mem_node; |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1190 _mem_node = n->is_Store() ? (Node*)n : NULL; |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1191 #endif |
0 | 1192 // State object for root node of match tree |
1193 // Allocate it on _states_arena - stack allocation can cause stack overflow. | |
1194 State *s = new (&_states_arena) State; | |
1195 s->_kids[0] = NULL; | |
1196 s->_kids[1] = NULL; | |
1197 s->_leaf = (Node*)n; | |
1198 // Label the input tree, allocating labels from top-level arena | |
1199 Label_Root( n, s, n->in(0), mem ); | |
1200 if (C->failing()) return NULL; | |
1201 | |
1202 // The minimum cost match for the whole tree is found at the root State | |
1203 uint mincost = max_juint; | |
1204 uint cost = max_juint; | |
1205 uint i; | |
1206 for( i = 0; i < NUM_OPERANDS; i++ ) { | |
1207 if( s->valid(i) && // valid entry and | |
1208 s->_cost[i] < cost && // low cost and | |
1209 s->_rule[i] >= NUM_OPERANDS ) // not an operand | |
1210 cost = s->_cost[mincost=i]; | |
1211 } | |
1212 if (mincost == max_juint) { | |
1213 #ifndef PRODUCT | |
1214 tty->print("No matching rule for:"); | |
1215 s->dump(); | |
1216 #endif | |
1217 Matcher::soft_match_failure(); | |
1218 return NULL; | |
1219 } | |
1220 // Reduce input tree based upon the state labels to machine Nodes | |
1221 MachNode *m = ReduceInst( s, s->_rule[mincost], mem ); | |
1222 #ifdef ASSERT | |
1223 _old2new_map.map(n->_idx, m); | |
222 | 1224 _new2old_map.map(m->_idx, (Node*)n); |
0 | 1225 #endif |
1226 | |
1227 // Add any Matcher-ignored edges | |
1228 uint cnt = n->req(); | |
1229 uint start = 1; | |
1230 if( mem != (Node*)1 ) start = MemNode::Memory+1; | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1231 if( n->is_AddP() ) { |
0 | 1232 assert( mem == (Node*)1, "" ); |
1233 start = AddPNode::Base+1; | |
1234 } | |
1235 for( i = start; i < cnt; i++ ) { | |
1236 if( !n->match_edge(i) ) { | |
1237 if( i < m->req() ) | |
1238 m->ins_req( i, n->in(i) ); | |
1239 else | |
1240 m->add_req( n->in(i) ); | |
1241 } | |
1242 } | |
1243 | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1244 debug_only( _mem_node = save_mem_node; ) |
0 | 1245 return m; |
1246 } | |
1247 | |
1248 | |
1249 //------------------------------match_into_reg--------------------------------- | |
1250 // Choose to either match this Node in a register or part of the current | |
1251 // match tree. Return true for requiring a register and false for matching | |
1252 // as part of the current match tree. | |
1253 static bool match_into_reg( const Node *n, Node *m, Node *control, int i, bool shared ) { | |
1254 | |
1255 const Type *t = m->bottom_type(); | |
1256 | |
1257 if( t->singleton() ) { | |
1258 // Never force constants into registers. Allow them to match as | |
1259 // constants or registers. Copies of the same value will share | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1260 // the same register. See find_shared_node. |
0 | 1261 return false; |
1262 } else { // Not a constant | |
1263 // Stop recursion if they have different Controls. | |
1264 // Slot 0 of constants is not really a Control. | |
1265 if( control && m->in(0) && control != m->in(0) ) { | |
1266 | |
1267 // Actually, we can live with the most conservative control we | |
1268 // find, if it post-dominates the others. This allows us to | |
1269 // pick up load/op/store trees where the load can float a little | |
1270 // above the store. | |
1271 Node *x = control; | |
1272 const uint max_scan = 6; // Arbitrary scan cutoff | |
1273 uint j; | |
1274 for( j=0; j<max_scan; j++ ) { | |
1275 if( x->is_Region() ) // Bail out at merge points | |
1276 return true; | |
1277 x = x->in(0); | |
1278 if( x == m->in(0) ) // Does 'control' post-dominate | |
1279 break; // m->in(0)? If so, we can use it | |
1280 } | |
1281 if( j == max_scan ) // No post-domination before scan end? | |
1282 return true; // Then break the match tree up | |
1283 } | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1284 if (m->is_DecodeN() && Matcher::clone_shift_expressions) { |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
1285 // These are commonly used in address expressions and can |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1286 // efficiently fold into them on X64 in some cases. |
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1287 return false; |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
1288 } |
0 | 1289 } |
1290 | |
605 | 1291 // Not forceable cloning. If shared, put it into a register. |
0 | 1292 return shared; |
1293 } | |
1294 | |
1295 | |
1296 //------------------------------Instruction Selection-------------------------- | |
1297 // Label method walks a "tree" of nodes, using the ADLC generated DFA to match | |
1298 // ideal nodes to machine instructions. Trees are delimited by shared Nodes, | |
1299 // things the Matcher does not match (e.g., Memory), and things with different | |
1300 // Controls (hence forced into different blocks). We pass in the Control | |
1301 // selected for this entire State tree. | |
1302 | |
1303 // The Matcher works on Trees, but an Intel add-to-memory requires a DAG: the | |
1304 // Store and the Load must have identical Memories (as well as identical | |
1305 // pointers). Since the Matcher does not have anything for Memory (and | |
1306 // does not handle DAGs), I have to match the Memory input myself. If the | |
1307 // Tree root is a Store, I require all Loads to have the identical memory. | |
1308 Node *Matcher::Label_Root( const Node *n, State *svec, Node *control, const Node *mem){ | |
1309 // Since Label_Root is a recursive function, its possible that we might run | |
1310 // out of stack space. See bugs 6272980 & 6227033 for more info. | |
1311 LabelRootDepth++; | |
1312 if (LabelRootDepth > MaxLabelRootDepth) { | |
1313 C->record_method_not_compilable_all_tiers("Out of stack space, increase MaxLabelRootDepth"); | |
1314 return NULL; | |
1315 } | |
1316 uint care = 0; // Edges matcher cares about | |
1317 uint cnt = n->req(); | |
1318 uint i = 0; | |
1319 | |
1320 // Examine children for memory state | |
1321 // Can only subsume a child into your match-tree if that child's memory state | |
1322 // is not modified along the path to another input. | |
1323 // It is unsafe even if the other inputs are separate roots. | |
1324 Node *input_mem = NULL; | |
1325 for( i = 1; i < cnt; i++ ) { | |
1326 if( !n->match_edge(i) ) continue; | |
1327 Node *m = n->in(i); // Get ith input | |
1328 assert( m, "expect non-null children" ); | |
1329 if( m->is_Load() ) { | |
1330 if( input_mem == NULL ) { | |
1331 input_mem = m->in(MemNode::Memory); | |
1332 } else if( input_mem != m->in(MemNode::Memory) ) { | |
1333 input_mem = NodeSentinel; | |
1334 } | |
1335 } | |
1336 } | |
1337 | |
1338 for( i = 1; i < cnt; i++ ){// For my children | |
1339 if( !n->match_edge(i) ) continue; | |
1340 Node *m = n->in(i); // Get ith input | |
1341 // Allocate states out of a private arena | |
1342 State *s = new (&_states_arena) State; | |
1343 svec->_kids[care++] = s; | |
1344 assert( care <= 2, "binary only for now" ); | |
1345 | |
1346 // Recursively label the State tree. | |
1347 s->_kids[0] = NULL; | |
1348 s->_kids[1] = NULL; | |
1349 s->_leaf = m; | |
1350 | |
1351 // Check for leaves of the State Tree; things that cannot be a part of | |
1352 // the current tree. If it finds any, that value is matched as a | |
1353 // register operand. If not, then the normal matching is used. | |
1354 if( match_into_reg(n, m, control, i, is_shared(m)) || | |
1355 // | |
1356 // Stop recursion if this is LoadNode and the root of this tree is a | |
1357 // StoreNode and the load & store have different memories. | |
1358 ((mem!=(Node*)1) && m->is_Load() && m->in(MemNode::Memory) != mem) || | |
1359 // Can NOT include the match of a subtree when its memory state | |
1360 // is used by any of the other subtrees | |
1361 (input_mem == NodeSentinel) ) { | |
1362 #ifndef PRODUCT | |
1363 // Print when we exclude matching due to different memory states at input-loads | |
1364 if( PrintOpto && (Verbose && WizardMode) && (input_mem == NodeSentinel) | |
1365 && !((mem!=(Node*)1) && m->is_Load() && m->in(MemNode::Memory) != mem) ) { | |
1366 tty->print_cr("invalid input_mem"); | |
1367 } | |
1368 #endif | |
1369 // Switch to a register-only opcode; this value must be in a register | |
1370 // and cannot be subsumed as part of a larger instruction. | |
1371 s->DFA( m->ideal_reg(), m ); | |
1372 | |
1373 } else { | |
1374 // If match tree has no control and we do, adopt it for entire tree | |
1375 if( control == NULL && m->in(0) != NULL && m->req() > 1 ) | |
1376 control = m->in(0); // Pick up control | |
1377 // Else match as a normal part of the match tree. | |
1378 control = Label_Root(m,s,control,mem); | |
1379 if (C->failing()) return NULL; | |
1380 } | |
1381 } | |
1382 | |
1383 | |
1384 // Call DFA to match this node, and return | |
1385 svec->DFA( n->Opcode(), n ); | |
1386 | |
1387 #ifdef ASSERT | |
1388 uint x; | |
1389 for( x = 0; x < _LAST_MACH_OPER; x++ ) | |
1390 if( svec->valid(x) ) | |
1391 break; | |
1392 | |
1393 if (x >= _LAST_MACH_OPER) { | |
1394 n->dump(); | |
1395 svec->dump(); | |
1396 assert( false, "bad AD file" ); | |
1397 } | |
1398 #endif | |
1399 return control; | |
1400 } | |
1401 | |
1402 | |
1403 // Con nodes reduced using the same rule can share their MachNode | |
1404 // which reduces the number of copies of a constant in the final | |
1405 // program. The register allocator is free to split uses later to | |
1406 // split live ranges. | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1407 MachNode* Matcher::find_shared_node(Node* leaf, uint rule) { |
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1408 if (!leaf->is_Con() && !leaf->is_DecodeN()) return NULL; |
0 | 1409 |
1410 // See if this Con has already been reduced using this rule. | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1411 if (_shared_nodes.Size() <= leaf->_idx) return NULL; |
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1412 MachNode* last = (MachNode*)_shared_nodes.at(leaf->_idx); |
0 | 1413 if (last != NULL && rule == last->rule()) { |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1414 // Don't expect control change for DecodeN |
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1415 if (leaf->is_DecodeN()) |
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1416 return last; |
0 | 1417 // Get the new space root. |
1418 Node* xroot = new_node(C->root()); | |
1419 if (xroot == NULL) { | |
1420 // This shouldn't happen give the order of matching. | |
1421 return NULL; | |
1422 } | |
1423 | |
1424 // Shared constants need to have their control be root so they | |
1425 // can be scheduled properly. | |
1426 Node* control = last->in(0); | |
1427 if (control != xroot) { | |
1428 if (control == NULL || control == C->root()) { | |
1429 last->set_req(0, xroot); | |
1430 } else { | |
1431 assert(false, "unexpected control"); | |
1432 return NULL; | |
1433 } | |
1434 } | |
1435 return last; | |
1436 } | |
1437 return NULL; | |
1438 } | |
1439 | |
1440 | |
1441 //------------------------------ReduceInst------------------------------------- | |
1442 // Reduce a State tree (with given Control) into a tree of MachNodes. | |
1443 // This routine (and it's cohort ReduceOper) convert Ideal Nodes into | |
1444 // complicated machine Nodes. Each MachNode covers some tree of Ideal Nodes. | |
1445 // Each MachNode has a number of complicated MachOper operands; each | |
1446 // MachOper also covers a further tree of Ideal Nodes. | |
1447 | |
1448 // The root of the Ideal match tree is always an instruction, so we enter | |
1449 // the recursion here. After building the MachNode, we need to recurse | |
1450 // the tree checking for these cases: | |
1451 // (1) Child is an instruction - | |
1452 // Build the instruction (recursively), add it as an edge. | |
1453 // Build a simple operand (register) to hold the result of the instruction. | |
1454 // (2) Child is an interior part of an instruction - | |
1455 // Skip over it (do nothing) | |
1456 // (3) Child is the start of a operand - | |
1457 // Build the operand, place it inside the instruction | |
1458 // Call ReduceOper. | |
1459 MachNode *Matcher::ReduceInst( State *s, int rule, Node *&mem ) { | |
1460 assert( rule >= NUM_OPERANDS, "called with operand rule" ); | |
1461 | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1462 MachNode* shared_node = find_shared_node(s->_leaf, rule); |
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1463 if (shared_node != NULL) { |
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1464 return shared_node; |
0 | 1465 } |
1466 | |
1467 // Build the object to represent this state & prepare for recursive calls | |
1468 MachNode *mach = s->MachNodeGenerator( rule, C ); | |
1469 mach->_opnds[0] = s->MachOperGenerator( _reduceOp[rule], C ); | |
1470 assert( mach->_opnds[0] != NULL, "Missing result operand" ); | |
1471 Node *leaf = s->_leaf; | |
1472 // Check for instruction or instruction chain rule | |
1473 if( rule >= _END_INST_CHAIN_RULE || rule < _BEGIN_INST_CHAIN_RULE ) { | |
309
eaf496ad4a14
6732698: crash with dead code from compressed oops in gcm
never
parents:
235
diff
changeset
|
1474 assert(C->node_arena()->contains(s->_leaf) || !has_new_node(s->_leaf), |
eaf496ad4a14
6732698: crash with dead code from compressed oops in gcm
never
parents:
235
diff
changeset
|
1475 "duplicating node that's already been matched"); |
0 | 1476 // Instruction |
1477 mach->add_req( leaf->in(0) ); // Set initial control | |
1478 // Reduce interior of complex instruction | |
1479 ReduceInst_Interior( s, rule, mem, mach, 1 ); | |
1480 } else { | |
1481 // Instruction chain rules are data-dependent on their inputs | |
1482 mach->add_req(0); // Set initial control to none | |
1483 ReduceInst_Chain_Rule( s, rule, mem, mach ); | |
1484 } | |
1485 | |
1486 // If a Memory was used, insert a Memory edge | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1487 if( mem != (Node*)1 ) { |
0 | 1488 mach->ins_req(MemNode::Memory,mem); |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1489 #ifdef ASSERT |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1490 // Verify adr type after matching memory operation |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1491 const MachOper* oper = mach->memory_operand(); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
823
diff
changeset
|
1492 if (oper != NULL && oper != (MachOper*)-1) { |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1493 // It has a unique memory operand. Find corresponding ideal mem node. |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1494 Node* m = NULL; |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1495 if (leaf->is_Mem()) { |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1496 m = leaf; |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1497 } else { |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1498 m = _mem_node; |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1499 assert(m != NULL && m->is_Mem(), "expecting memory node"); |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1500 } |
368
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
1501 const Type* mach_at = mach->adr_type(); |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
1502 // DecodeN node consumed by an address may have different type |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
1503 // then its input. Don't compare types for such case. |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
605
diff
changeset
|
1504 if (m->adr_type() != mach_at && |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
605
diff
changeset
|
1505 (m->in(MemNode::Address)->is_DecodeN() || |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
605
diff
changeset
|
1506 m->in(MemNode::Address)->is_AddP() && |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
605
diff
changeset
|
1507 m->in(MemNode::Address)->in(AddPNode::Address)->is_DecodeN() || |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
605
diff
changeset
|
1508 m->in(MemNode::Address)->is_AddP() && |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
605
diff
changeset
|
1509 m->in(MemNode::Address)->in(AddPNode::Address)->is_AddP() && |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
605
diff
changeset
|
1510 m->in(MemNode::Address)->in(AddPNode::Address)->in(AddPNode::Address)->is_DecodeN())) { |
368
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
1511 mach_at = m->adr_type(); |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
1512 } |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
1513 if (m->adr_type() != mach_at) { |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1514 m->dump(); |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1515 tty->print_cr("mach:"); |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1516 mach->dump(1); |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1517 } |
368
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
1518 assert(m->adr_type() == mach_at, "matcher should not change adr type"); |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1519 } |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1520 #endif |
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1521 } |
0 | 1522 |
1523 // If the _leaf is an AddP, insert the base edge | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1524 if( leaf->is_AddP() ) |
0 | 1525 mach->ins_req(AddPNode::Base,leaf->in(AddPNode::Base)); |
1526 | |
1527 uint num_proj = _proj_list.size(); | |
1528 | |
1529 // Perform any 1-to-many expansions required | |
1530 MachNode *ex = mach->Expand(s,_proj_list); | |
1531 if( ex != mach ) { | |
1532 assert(ex->ideal_reg() == mach->ideal_reg(), "ideal types should match"); | |
1533 if( ex->in(1)->is_Con() ) | |
1534 ex->in(1)->set_req(0, C->root()); | |
1535 // Remove old node from the graph | |
1536 for( uint i=0; i<mach->req(); i++ ) { | |
1537 mach->set_req(i,NULL); | |
1538 } | |
222 | 1539 #ifdef ASSERT |
1540 _new2old_map.map(ex->_idx, s->_leaf); | |
1541 #endif | |
0 | 1542 } |
1543 | |
1544 // PhaseChaitin::fixup_spills will sometimes generate spill code | |
1545 // via the matcher. By the time, nodes have been wired into the CFG, | |
1546 // and any further nodes generated by expand rules will be left hanging | |
1547 // in space, and will not get emitted as output code. Catch this. | |
1548 // Also, catch any new register allocation constraints ("projections") | |
1549 // generated belatedly during spill code generation. | |
1550 if (_allocation_started) { | |
1551 guarantee(ex == mach, "no expand rules during spill generation"); | |
1552 guarantee(_proj_list.size() == num_proj, "no allocation during spill generation"); | |
1553 } | |
1554 | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1555 if (leaf->is_Con() || leaf->is_DecodeN()) { |
0 | 1556 // Record the con for sharing |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1557 _shared_nodes.map(leaf->_idx, ex); |
0 | 1558 } |
1559 | |
1560 return ex; | |
1561 } | |
1562 | |
1563 void Matcher::ReduceInst_Chain_Rule( State *s, int rule, Node *&mem, MachNode *mach ) { | |
1564 // 'op' is what I am expecting to receive | |
1565 int op = _leftOp[rule]; | |
1566 // Operand type to catch childs result | |
1567 // This is what my child will give me. | |
1568 int opnd_class_instance = s->_rule[op]; | |
1569 // Choose between operand class or not. | |
605 | 1570 // This is what I will receive. |
0 | 1571 int catch_op = (FIRST_OPERAND_CLASS <= op && op < NUM_OPERANDS) ? opnd_class_instance : op; |
1572 // New rule for child. Chase operand classes to get the actual rule. | |
1573 int newrule = s->_rule[catch_op]; | |
1574 | |
1575 if( newrule < NUM_OPERANDS ) { | |
1576 // Chain from operand or operand class, may be output of shared node | |
1577 assert( 0 <= opnd_class_instance && opnd_class_instance < NUM_OPERANDS, | |
1578 "Bad AD file: Instruction chain rule must chain from operand"); | |
1579 // Insert operand into array of operands for this instruction | |
1580 mach->_opnds[1] = s->MachOperGenerator( opnd_class_instance, C ); | |
1581 | |
1582 ReduceOper( s, newrule, mem, mach ); | |
1583 } else { | |
1584 // Chain from the result of an instruction | |
1585 assert( newrule >= _LAST_MACH_OPER, "Do NOT chain from internal operand"); | |
1586 mach->_opnds[1] = s->MachOperGenerator( _reduceOp[catch_op], C ); | |
1587 Node *mem1 = (Node*)1; | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1588 debug_only(Node *save_mem_node = _mem_node;) |
0 | 1589 mach->add_req( ReduceInst(s, newrule, mem1) ); |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1590 debug_only(_mem_node = save_mem_node;) |
0 | 1591 } |
1592 return; | |
1593 } | |
1594 | |
1595 | |
1596 uint Matcher::ReduceInst_Interior( State *s, int rule, Node *&mem, MachNode *mach, uint num_opnds ) { | |
1597 if( s->_leaf->is_Load() ) { | |
1598 Node *mem2 = s->_leaf->in(MemNode::Memory); | |
1599 assert( mem == (Node*)1 || mem == mem2, "multiple Memories being matched at once?" ); | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1600 debug_only( if( mem == (Node*)1 ) _mem_node = s->_leaf;) |
0 | 1601 mem = mem2; |
1602 } | |
1603 if( s->_leaf->in(0) != NULL && s->_leaf->req() > 1) { | |
1604 if( mach->in(0) == NULL ) | |
1605 mach->set_req(0, s->_leaf->in(0)); | |
1606 } | |
1607 | |
1608 // Now recursively walk the state tree & add operand list. | |
1609 for( uint i=0; i<2; i++ ) { // binary tree | |
1610 State *newstate = s->_kids[i]; | |
1611 if( newstate == NULL ) break; // Might only have 1 child | |
1612 // 'op' is what I am expecting to receive | |
1613 int op; | |
1614 if( i == 0 ) { | |
1615 op = _leftOp[rule]; | |
1616 } else { | |
1617 op = _rightOp[rule]; | |
1618 } | |
1619 // Operand type to catch childs result | |
1620 // This is what my child will give me. | |
1621 int opnd_class_instance = newstate->_rule[op]; | |
1622 // Choose between operand class or not. | |
1623 // This is what I will receive. | |
1624 int catch_op = (op >= FIRST_OPERAND_CLASS && op < NUM_OPERANDS) ? opnd_class_instance : op; | |
1625 // New rule for child. Chase operand classes to get the actual rule. | |
1626 int newrule = newstate->_rule[catch_op]; | |
1627 | |
1628 if( newrule < NUM_OPERANDS ) { // Operand/operandClass or internalOp/instruction? | |
1629 // Operand/operandClass | |
1630 // Insert operand into array of operands for this instruction | |
1631 mach->_opnds[num_opnds++] = newstate->MachOperGenerator( opnd_class_instance, C ); | |
1632 ReduceOper( newstate, newrule, mem, mach ); | |
1633 | |
1634 } else { // Child is internal operand or new instruction | |
1635 if( newrule < _LAST_MACH_OPER ) { // internal operand or instruction? | |
1636 // internal operand --> call ReduceInst_Interior | |
1637 // Interior of complex instruction. Do nothing but recurse. | |
1638 num_opnds = ReduceInst_Interior( newstate, newrule, mem, mach, num_opnds ); | |
1639 } else { | |
1640 // instruction --> call build operand( ) to catch result | |
1641 // --> ReduceInst( newrule ) | |
1642 mach->_opnds[num_opnds++] = s->MachOperGenerator( _reduceOp[catch_op], C ); | |
1643 Node *mem1 = (Node*)1; | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1644 debug_only(Node *save_mem_node = _mem_node;) |
0 | 1645 mach->add_req( ReduceInst( newstate, newrule, mem1 ) ); |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1646 debug_only(_mem_node = save_mem_node;) |
0 | 1647 } |
1648 } | |
1649 assert( mach->_opnds[num_opnds-1], "" ); | |
1650 } | |
1651 return num_opnds; | |
1652 } | |
1653 | |
1654 // This routine walks the interior of possible complex operands. | |
1655 // At each point we check our children in the match tree: | |
1656 // (1) No children - | |
1657 // We are a leaf; add _leaf field as an input to the MachNode | |
1658 // (2) Child is an internal operand - | |
1659 // Skip over it ( do nothing ) | |
1660 // (3) Child is an instruction - | |
1661 // Call ReduceInst recursively and | |
1662 // and instruction as an input to the MachNode | |
1663 void Matcher::ReduceOper( State *s, int rule, Node *&mem, MachNode *mach ) { | |
1664 assert( rule < _LAST_MACH_OPER, "called with operand rule" ); | |
1665 State *kid = s->_kids[0]; | |
1666 assert( kid == NULL || s->_leaf->in(0) == NULL, "internal operands have no control" ); | |
1667 | |
1668 // Leaf? And not subsumed? | |
1669 if( kid == NULL && !_swallowed[rule] ) { | |
1670 mach->add_req( s->_leaf ); // Add leaf pointer | |
1671 return; // Bail out | |
1672 } | |
1673 | |
1674 if( s->_leaf->is_Load() ) { | |
1675 assert( mem == (Node*)1, "multiple Memories being matched at once?" ); | |
1676 mem = s->_leaf->in(MemNode::Memory); | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1677 debug_only(_mem_node = s->_leaf;) |
0 | 1678 } |
1679 if( s->_leaf->in(0) && s->_leaf->req() > 1) { | |
1680 if( !mach->in(0) ) | |
1681 mach->set_req(0,s->_leaf->in(0)); | |
1682 else { | |
1683 assert( s->_leaf->in(0) == mach->in(0), "same instruction, differing controls?" ); | |
1684 } | |
1685 } | |
1686 | |
1687 for( uint i=0; kid != NULL && i<2; kid = s->_kids[1], i++ ) { // binary tree | |
1688 int newrule; | |
1689 if( i == 0 ) | |
1690 newrule = kid->_rule[_leftOp[rule]]; | |
1691 else | |
1692 newrule = kid->_rule[_rightOp[rule]]; | |
1693 | |
1694 if( newrule < _LAST_MACH_OPER ) { // Operand or instruction? | |
1695 // Internal operand; recurse but do nothing else | |
1696 ReduceOper( kid, newrule, mem, mach ); | |
1697 | |
1698 } else { // Child is a new instruction | |
1699 // Reduce the instruction, and add a direct pointer from this | |
1700 // machine instruction to the newly reduced one. | |
1701 Node *mem1 = (Node*)1; | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1702 debug_only(Node *save_mem_node = _mem_node;) |
0 | 1703 mach->add_req( ReduceInst( kid, newrule, mem1 ) ); |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
169
diff
changeset
|
1704 debug_only(_mem_node = save_mem_node;) |
0 | 1705 } |
1706 } | |
1707 } | |
1708 | |
1709 | |
1710 // ------------------------------------------------------------------------- | |
1711 // Java-Java calling convention | |
1712 // (what you use when Java calls Java) | |
1713 | |
1714 //------------------------------find_receiver---------------------------------- | |
1715 // For a given signature, return the OptoReg for parameter 0. | |
1716 OptoReg::Name Matcher::find_receiver( bool is_outgoing ) { | |
1717 VMRegPair regs; | |
1718 BasicType sig_bt = T_OBJECT; | |
1719 calling_convention(&sig_bt, ®s, 1, is_outgoing); | |
1720 // Return argument 0 register. In the LP64 build pointers | |
1721 // take 2 registers, but the VM wants only the 'main' name. | |
1722 return OptoReg::as_OptoReg(regs.first()); | |
1723 } | |
1724 | |
1725 // A method-klass-holder may be passed in the inline_cache_reg | |
1726 // and then expanded into the inline_cache_reg and a method_oop register | |
1727 // defined in ad_<arch>.cpp | |
1728 | |
1729 | |
1730 //------------------------------find_shared------------------------------------ | |
1731 // Set bits if Node is shared or otherwise a root | |
1732 void Matcher::find_shared( Node *n ) { | |
1733 // Allocate stack of size C->unique() * 2 to avoid frequent realloc | |
1734 MStack mstack(C->unique() * 2); | |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1735 // Mark nodes as address_visited if they are inputs to an address expression |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1736 VectorSet address_visited(Thread::current()->resource_area()); |
0 | 1737 mstack.push(n, Visit); // Don't need to pre-visit root node |
1738 while (mstack.is_nonempty()) { | |
1739 n = mstack.node(); // Leave node on stack | |
1740 Node_State nstate = mstack.state(); | |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1741 uint nop = n->Opcode(); |
0 | 1742 if (nstate == Pre_Visit) { |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1743 if (address_visited.test(n->_idx)) { // Visited in address already? |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1744 // Flag as visited and shared now. |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1745 set_visited(n); |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1746 } |
0 | 1747 if (is_visited(n)) { // Visited already? |
1748 // Node is shared and has no reason to clone. Flag it as shared. | |
1749 // This causes it to match into a register for the sharing. | |
1750 set_shared(n); // Flag as shared and | |
1751 mstack.pop(); // remove node from stack | |
1752 continue; | |
1753 } | |
1754 nstate = Visit; // Not already visited; so visit now | |
1755 } | |
1756 if (nstate == Visit) { | |
1757 mstack.set_state(Post_Visit); | |
1758 set_visited(n); // Flag as visited now | |
1759 bool mem_op = false; | |
1760 | |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1761 switch( nop ) { // Handle some opcodes special |
0 | 1762 case Op_Phi: // Treat Phis as shared roots |
1763 case Op_Parm: | |
1764 case Op_Proj: // All handled specially during matching | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
0
diff
changeset
|
1765 case Op_SafePointScalarObject: |
0 | 1766 set_shared(n); |
1767 set_dontcare(n); | |
1768 break; | |
1769 case Op_If: | |
1770 case Op_CountedLoopEnd: | |
1771 mstack.set_state(Alt_Post_Visit); // Alternative way | |
1772 // Convert (If (Bool (CmpX A B))) into (If (Bool) (CmpX A B)). Helps | |
1773 // with matching cmp/branch in 1 instruction. The Matcher needs the | |
1774 // Bool and CmpX side-by-side, because it can only get at constants | |
1775 // that are at the leaves of Match trees, and the Bool's condition acts | |
1776 // as a constant here. | |
1777 mstack.push(n->in(1), Visit); // Clone the Bool | |
1778 mstack.push(n->in(0), Pre_Visit); // Visit control input | |
1779 continue; // while (mstack.is_nonempty()) | |
1780 case Op_ConvI2D: // These forms efficiently match with a prior | |
1781 case Op_ConvI2F: // Load but not a following Store | |
1782 if( n->in(1)->is_Load() && // Prior load | |
1783 n->outcnt() == 1 && // Not already shared | |
1784 n->unique_out()->is_Store() ) // Following store | |
1785 set_shared(n); // Force it to be a root | |
1786 break; | |
1787 case Op_ReverseBytesI: | |
1788 case Op_ReverseBytesL: | |
1789 if( n->in(1)->is_Load() && // Prior load | |
1790 n->outcnt() == 1 ) // Not already shared | |
1791 set_shared(n); // Force it to be a root | |
1792 break; | |
1793 case Op_BoxLock: // Cant match until we get stack-regs in ADLC | |
1794 case Op_IfFalse: | |
1795 case Op_IfTrue: | |
1796 case Op_MachProj: | |
1797 case Op_MergeMem: | |
1798 case Op_Catch: | |
1799 case Op_CatchProj: | |
1800 case Op_CProj: | |
1801 case Op_JumpProj: | |
1802 case Op_JProj: | |
1803 case Op_NeverBranch: | |
1804 set_dontcare(n); | |
1805 break; | |
1806 case Op_Jump: | |
1807 mstack.push(n->in(1), Visit); // Switch Value | |
1808 mstack.push(n->in(0), Pre_Visit); // Visit Control input | |
1809 continue; // while (mstack.is_nonempty()) | |
1810 case Op_StrComp: | |
681 | 1811 case Op_StrEquals: |
1812 case Op_StrIndexOf: | |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
168
diff
changeset
|
1813 case Op_AryEq: |
0 | 1814 set_shared(n); // Force result into register (it will be anyways) |
1815 break; | |
1816 case Op_ConP: { // Convert pointers above the centerline to NUL | |
1817 TypeNode *tn = n->as_Type(); // Constants derive from type nodes | |
1818 const TypePtr* tp = tn->type()->is_ptr(); | |
1819 if (tp->_ptr == TypePtr::AnyNull) { | |
1820 tn->set_type(TypePtr::NULL_PTR); | |
1821 } | |
1822 break; | |
1823 } | |
163 | 1824 case Op_ConN: { // Convert narrow pointers above the centerline to NUL |
1825 TypeNode *tn = n->as_Type(); // Constants derive from type nodes | |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
216
diff
changeset
|
1826 const TypePtr* tp = tn->type()->make_ptr(); |
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
216
diff
changeset
|
1827 if (tp && tp->_ptr == TypePtr::AnyNull) { |
163 | 1828 tn->set_type(TypeNarrowOop::NULL_PTR); |
1829 } | |
1830 break; | |
1831 } | |
0 | 1832 case Op_Binary: // These are introduced in the Post_Visit state. |
1833 ShouldNotReachHere(); | |
1834 break; | |
1835 case Op_ClearArray: | |
1836 case Op_SafePoint: | |
1837 mem_op = true; | |
1838 break; | |
1061
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1839 default: |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1840 if( n->is_Store() ) { |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1841 // Do match stores, despite no ideal reg |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1842 mem_op = true; |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1843 break; |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1844 } |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1845 if( n->is_Mem() ) { // Loads and LoadStores |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1846 mem_op = true; |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1847 // Loads must be root of match tree due to prior load conflict |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1848 if( C->subsume_loads() == false ) |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1849 set_shared(n); |
0 | 1850 } |
1851 // Fall into default case | |
1852 if( !n->ideal_reg() ) | |
1853 set_dontcare(n); // Unmatchable Nodes | |
1854 } // end_switch | |
1855 | |
1856 for(int i = n->req() - 1; i >= 0; --i) { // For my children | |
1857 Node *m = n->in(i); // Get ith input | |
1858 if (m == NULL) continue; // Ignore NULLs | |
1859 uint mop = m->Opcode(); | |
1860 | |
1861 // Must clone all producers of flags, or we will not match correctly. | |
1862 // Suppose a compare setting int-flags is shared (e.g., a switch-tree) | |
1863 // then it will match into an ideal Op_RegFlags. Alas, the fp-flags | |
1864 // are also there, so we may match a float-branch to int-flags and | |
1865 // expect the allocator to haul the flags from the int-side to the | |
1866 // fp-side. No can do. | |
1867 if( _must_clone[mop] ) { | |
1868 mstack.push(m, Visit); | |
1869 continue; // for(int i = ...) | |
1870 } | |
1871 | |
1061
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1872 if( mop == Op_AddP && m->in(AddPNode::Base)->Opcode() == Op_DecodeN ) { |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1873 // Bases used in addresses must be shared but since |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1874 // they are shared through a DecodeN they may appear |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1875 // to have a single use so force sharing here. |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1876 set_shared(m->in(AddPNode::Base)->in(1)); |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1877 } |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1878 |
09572fede9d1
6896370: CTW fails share/vm/opto/matcher.cpp:1475 "duplicating node that's already been matched"
kvn
parents:
986
diff
changeset
|
1879 // Clone addressing expressions as they are "free" in memory access instructions |
0 | 1880 if( mem_op && i == MemNode::Address && mop == Op_AddP ) { |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1881 // Some inputs for address expression are not put on stack |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1882 // to avoid marking them as shared and forcing them into register |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1883 // if they are used only in address expressions. |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1884 // But they should be marked as shared if there are other uses |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1885 // besides address expressions. |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1886 |
0 | 1887 Node *off = m->in(AddPNode::Offset); |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1888 if( off->is_Con() && |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1889 // When there are other uses besides address expressions |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1890 // put it on stack and mark as shared. |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1891 !is_visited(m) ) { |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1892 address_visited.test_set(m->_idx); // Flag as address_visited |
0 | 1893 Node *adr = m->in(AddPNode::Address); |
1894 | |
1895 // Intel, ARM and friends can handle 2 adds in addressing mode | |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1896 if( clone_shift_expressions && adr->is_AddP() && |
0 | 1897 // AtomicAdd is not an addressing expression. |
1898 // Cheap to find it by looking for screwy base. | |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1899 !adr->in(AddPNode::Base)->is_top() && |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1900 // Are there other uses besides address expressions? |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1901 !is_visited(adr) ) { |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1902 address_visited.set(adr->_idx); // Flag as address_visited |
0 | 1903 Node *shift = adr->in(AddPNode::Offset); |
1904 // Check for shift by small constant as well | |
1905 if( shift->Opcode() == Op_LShiftX && shift->in(2)->is_Con() && | |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1906 shift->in(2)->get_int() <= 3 && |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1907 // Are there other uses besides address expressions? |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1908 !is_visited(shift) ) { |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1909 address_visited.set(shift->_idx); // Flag as address_visited |
0 | 1910 mstack.push(shift->in(2), Visit); |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1911 Node *conv = shift->in(1); |
0 | 1912 #ifdef _LP64 |
1913 // Allow Matcher to match the rule which bypass | |
1914 // ConvI2L operation for an array index on LP64 | |
1915 // if the index value is positive. | |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1916 if( conv->Opcode() == Op_ConvI2L && |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1917 conv->as_Type()->type()->is_long()->_lo >= 0 && |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1918 // Are there other uses besides address expressions? |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1919 !is_visited(conv) ) { |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1920 address_visited.set(conv->_idx); // Flag as address_visited |
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1921 mstack.push(conv->in(1), Pre_Visit); |
0 | 1922 } else |
1923 #endif | |
586
6bea93606c11
6791572: assert("duplicating node that's already been matched")
kvn
parents:
558
diff
changeset
|
1924 mstack.push(conv, Pre_Visit); |
0 | 1925 } else { |
1926 mstack.push(shift, Pre_Visit); | |
1927 } | |
1928 mstack.push(adr->in(AddPNode::Address), Pre_Visit); | |
1929 mstack.push(adr->in(AddPNode::Base), Pre_Visit); | |
1930 } else { // Sparc, Alpha, PPC and friends | |
1931 mstack.push(adr, Pre_Visit); | |
1932 } | |
1933 | |
1934 // Clone X+offset as it also folds into most addressing expressions | |
1935 mstack.push(off, Visit); | |
1936 mstack.push(m->in(AddPNode::Base), Pre_Visit); | |
1937 continue; // for(int i = ...) | |
1938 } // if( off->is_Con() ) | |
1939 } // if( mem_op && | |
1940 mstack.push(m, Pre_Visit); | |
1941 } // for(int i = ...) | |
1942 } | |
1943 else if (nstate == Alt_Post_Visit) { | |
1944 mstack.pop(); // Remove node from stack | |
1945 // We cannot remove the Cmp input from the Bool here, as the Bool may be | |
1946 // shared and all users of the Bool need to move the Cmp in parallel. | |
1947 // This leaves both the Bool and the If pointing at the Cmp. To | |
1948 // prevent the Matcher from trying to Match the Cmp along both paths | |
1949 // BoolNode::match_edge always returns a zero. | |
1950 | |
1951 // We reorder the Op_If in a pre-order manner, so we can visit without | |
605 | 1952 // accidentally sharing the Cmp (the Bool and the If make 2 users). |
0 | 1953 n->add_req( n->in(1)->in(1) ); // Add the Cmp next to the Bool |
1954 } | |
1955 else if (nstate == Post_Visit) { | |
1956 mstack.pop(); // Remove node from stack | |
1957 | |
1958 // Now hack a few special opcodes | |
1959 switch( n->Opcode() ) { // Handle some opcodes special | |
1960 case Op_StorePConditional: | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
368
diff
changeset
|
1961 case Op_StoreIConditional: |
0 | 1962 case Op_StoreLConditional: |
1963 case Op_CompareAndSwapI: | |
1964 case Op_CompareAndSwapL: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
1965 case Op_CompareAndSwapP: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
1966 case Op_CompareAndSwapN: { // Convert trinary to binary-tree |
0 | 1967 Node *newval = n->in(MemNode::ValueIn ); |
1968 Node *oldval = n->in(LoadStoreNode::ExpectedIn); | |
1969 Node *pair = new (C, 3) BinaryNode( oldval, newval ); | |
1970 n->set_req(MemNode::ValueIn,pair); | |
1971 n->del_req(LoadStoreNode::ExpectedIn); | |
1972 break; | |
1973 } | |
1974 case Op_CMoveD: // Convert trinary to binary-tree | |
1975 case Op_CMoveF: | |
1976 case Op_CMoveI: | |
1977 case Op_CMoveL: | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1978 case Op_CMoveN: |
0 | 1979 case Op_CMoveP: { |
1980 // Restructure into a binary tree for Matching. It's possible that | |
1981 // we could move this code up next to the graph reshaping for IfNodes | |
1982 // or vice-versa, but I do not want to debug this for Ladybird. | |
1983 // 10/2/2000 CNC. | |
1984 Node *pair1 = new (C, 3) BinaryNode(n->in(1),n->in(1)->in(1)); | |
1985 n->set_req(1,pair1); | |
1986 Node *pair2 = new (C, 3) BinaryNode(n->in(2),n->in(3)); | |
1987 n->set_req(2,pair2); | |
1988 n->del_req(3); | |
1989 break; | |
1990 } | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
1991 case Op_StrEquals: { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
1992 Node *pair1 = new (C, 3) BinaryNode(n->in(2),n->in(3)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
1993 n->set_req(2,pair1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
1994 n->set_req(3,n->in(4)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
1995 n->del_req(4); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
1996 break; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
1997 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
1998 case Op_StrComp: |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
1999 case Op_StrIndexOf: { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
2000 Node *pair1 = new (C, 3) BinaryNode(n->in(2),n->in(3)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
2001 n->set_req(2,pair1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
2002 Node *pair2 = new (C, 3) BinaryNode(n->in(4),n->in(5)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
2003 n->set_req(3,pair2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
2004 n->del_req(5); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
2005 n->del_req(4); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
2006 break; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
851
diff
changeset
|
2007 } |
0 | 2008 default: |
2009 break; | |
2010 } | |
2011 } | |
2012 else { | |
2013 ShouldNotReachHere(); | |
2014 } | |
2015 } // end of while (mstack.is_nonempty()) | |
2016 } | |
2017 | |
2018 #ifdef ASSERT | |
2019 // machine-independent root to machine-dependent root | |
2020 void Matcher::dump_old2new_map() { | |
2021 _old2new_map.dump(); | |
2022 } | |
2023 #endif | |
2024 | |
2025 //---------------------------collect_null_checks------------------------------- | |
2026 // Find null checks in the ideal graph; write a machine-specific node for | |
2027 // it. Used by later implicit-null-check handling. Actually collects | |
2028 // either an IfTrue or IfFalse for the common NOT-null path, AND the ideal | |
2029 // value being tested. | |
368
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2030 void Matcher::collect_null_checks( Node *proj, Node *orig_proj ) { |
0 | 2031 Node *iff = proj->in(0); |
2032 if( iff->Opcode() == Op_If ) { | |
2033 // During matching If's have Bool & Cmp side-by-side | |
2034 BoolNode *b = iff->in(1)->as_Bool(); | |
2035 Node *cmp = iff->in(2); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2036 int opc = cmp->Opcode(); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2037 if (opc != Op_CmpP && opc != Op_CmpN) return; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2038 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2039 const Type* ct = cmp->in(2)->bottom_type(); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2040 if (ct == TypePtr::NULL_PTR || |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2041 (opc == Op_CmpN && ct == TypeNarrowOop::NULL_PTR)) { |
0 | 2042 |
368
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2043 bool push_it = false; |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2044 if( proj->Opcode() == Op_IfTrue ) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2045 extern int all_null_checks_found; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2046 all_null_checks_found++; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2047 if( b->_test._test == BoolTest::ne ) { |
368
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2048 push_it = true; |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2049 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2050 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2051 assert( proj->Opcode() == Op_IfFalse, "" ); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2052 if( b->_test._test == BoolTest::eq ) { |
368
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2053 push_it = true; |
0 | 2054 } |
2055 } | |
368
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2056 if( push_it ) { |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2057 _null_check_tests.push(proj); |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2058 Node* val = cmp->in(1); |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2059 #ifdef _LP64 |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2060 if (UseCompressedOops && !Matcher::clone_shift_expressions && |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2061 val->bottom_type()->isa_narrowoop()) { |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2062 // |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2063 // Look for DecodeN node which should be pinned to orig_proj. |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2064 // On platforms (Sparc) which can not handle 2 adds |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2065 // in addressing mode we have to keep a DecodeN node and |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2066 // use it to do implicit NULL check in address. |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2067 // |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2068 // DecodeN node was pinned to non-null path (orig_proj) during |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2069 // CastPP transformation in final_graph_reshaping_impl(). |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2070 // |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2071 uint cnt = orig_proj->outcnt(); |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2072 for (uint i = 0; i < orig_proj->outcnt(); i++) { |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2073 Node* d = orig_proj->raw_out(i); |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2074 if (d->is_DecodeN() && d->in(1) == val) { |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2075 val = d; |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2076 val->set_req(0, NULL); // Unpin now. |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2077 break; |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2078 } |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2079 } |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2080 } |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2081 #endif |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2082 _null_check_tests.push(val); |
36ccc817fca4
6747051: Improve code and implicit null check generation for compressed oops
kvn
parents:
367
diff
changeset
|
2083 } |
0 | 2084 } |
2085 } | |
2086 } | |
2087 | |
2088 //---------------------------validate_null_checks------------------------------ | |
2089 // Its possible that the value being NULL checked is not the root of a match | |
2090 // tree. If so, I cannot use the value in an implicit null check. | |
2091 void Matcher::validate_null_checks( ) { | |
2092 uint cnt = _null_check_tests.size(); | |
2093 for( uint i=0; i < cnt; i+=2 ) { | |
2094 Node *test = _null_check_tests[i]; | |
2095 Node *val = _null_check_tests[i+1]; | |
2096 if (has_new_node(val)) { | |
2097 // Is a match-tree root, so replace with the matched value | |
2098 _null_check_tests.map(i+1, new_node(val)); | |
2099 } else { | |
2100 // Yank from candidate list | |
2101 _null_check_tests.map(i+1,_null_check_tests[--cnt]); | |
2102 _null_check_tests.map(i,_null_check_tests[--cnt]); | |
2103 _null_check_tests.pop(); | |
2104 _null_check_tests.pop(); | |
2105 i-=2; | |
2106 } | |
2107 } | |
2108 } | |
2109 | |
2110 | |
2111 // Used by the DFA in dfa_sparc.cpp. Check for a prior FastLock | |
2112 // acting as an Acquire and thus we don't need an Acquire here. We | |
2113 // retain the Node to act as a compiler ordering barrier. | |
2114 bool Matcher::prior_fast_lock( const Node *acq ) { | |
2115 Node *r = acq->in(0); | |
2116 if( !r->is_Region() || r->req() <= 1 ) return false; | |
2117 Node *proj = r->in(1); | |
2118 if( !proj->is_Proj() ) return false; | |
2119 Node *call = proj->in(0); | |
2120 if( !call->is_Call() || call->as_Call()->entry_point() != OptoRuntime::complete_monitor_locking_Java() ) | |
2121 return false; | |
2122 | |
2123 return true; | |
2124 } | |
2125 | |
2126 // Used by the DFA in dfa_sparc.cpp. Check for a following FastUnLock | |
2127 // acting as a Release and thus we don't need a Release here. We | |
2128 // retain the Node to act as a compiler ordering barrier. | |
2129 bool Matcher::post_fast_unlock( const Node *rel ) { | |
2130 Compile *C = Compile::current(); | |
2131 assert( rel->Opcode() == Op_MemBarRelease, "" ); | |
2132 const MemBarReleaseNode *mem = (const MemBarReleaseNode*)rel; | |
2133 DUIterator_Fast imax, i = mem->fast_outs(imax); | |
2134 Node *ctrl = NULL; | |
2135 while( true ) { | |
2136 ctrl = mem->fast_out(i); // Throw out-of-bounds if proj not found | |
2137 assert( ctrl->is_Proj(), "only projections here" ); | |
2138 ProjNode *proj = (ProjNode*)ctrl; | |
2139 if( proj->_con == TypeFunc::Control && | |
2140 !C->node_arena()->contains(ctrl) ) // Unmatched old-space only | |
2141 break; | |
2142 i++; | |
2143 } | |
2144 Node *iff = NULL; | |
2145 for( DUIterator_Fast jmax, j = ctrl->fast_outs(jmax); j < jmax; j++ ) { | |
2146 Node *x = ctrl->fast_out(j); | |
2147 if( x->is_If() && x->req() > 1 && | |
2148 !C->node_arena()->contains(x) ) { // Unmatched old-space only | |
2149 iff = x; | |
2150 break; | |
2151 } | |
2152 } | |
2153 if( !iff ) return false; | |
2154 Node *bol = iff->in(1); | |
2155 // The iff might be some random subclass of If or bol might be Con-Top | |
2156 if (!bol->is_Bool()) return false; | |
2157 assert( bol->req() > 1, "" ); | |
2158 return (bol->in(1)->Opcode() == Op_FastUnlock); | |
2159 } | |
2160 | |
2161 // Used by the DFA in dfa_xxx.cpp. Check for a following barrier or | |
2162 // atomic instruction acting as a store_load barrier without any | |
2163 // intervening volatile load, and thus we don't need a barrier here. | |
2164 // We retain the Node to act as a compiler ordering barrier. | |
2165 bool Matcher::post_store_load_barrier(const Node *vmb) { | |
2166 Compile *C = Compile::current(); | |
2167 assert( vmb->is_MemBar(), "" ); | |
2168 assert( vmb->Opcode() != Op_MemBarAcquire, "" ); | |
2169 const MemBarNode *mem = (const MemBarNode*)vmb; | |
2170 | |
2171 // Get the Proj node, ctrl, that can be used to iterate forward | |
2172 Node *ctrl = NULL; | |
2173 DUIterator_Fast imax, i = mem->fast_outs(imax); | |
2174 while( true ) { | |
2175 ctrl = mem->fast_out(i); // Throw out-of-bounds if proj not found | |
2176 assert( ctrl->is_Proj(), "only projections here" ); | |
2177 ProjNode *proj = (ProjNode*)ctrl; | |
2178 if( proj->_con == TypeFunc::Control && | |
2179 !C->node_arena()->contains(ctrl) ) // Unmatched old-space only | |
2180 break; | |
2181 i++; | |
2182 } | |
2183 | |
2184 for( DUIterator_Fast jmax, j = ctrl->fast_outs(jmax); j < jmax; j++ ) { | |
2185 Node *x = ctrl->fast_out(j); | |
2186 int xop = x->Opcode(); | |
2187 | |
2188 // We don't need current barrier if we see another or a lock | |
2189 // before seeing volatile load. | |
2190 // | |
2191 // Op_Fastunlock previously appeared in the Op_* list below. | |
2192 // With the advent of 1-0 lock operations we're no longer guaranteed | |
2193 // that a monitor exit operation contains a serializing instruction. | |
2194 | |
2195 if (xop == Op_MemBarVolatile || | |
2196 xop == Op_FastLock || | |
2197 xop == Op_CompareAndSwapL || | |
2198 xop == Op_CompareAndSwapP || | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
63
diff
changeset
|
2199 xop == Op_CompareAndSwapN || |
0 | 2200 xop == Op_CompareAndSwapI) |
2201 return true; | |
2202 | |
2203 if (x->is_MemBar()) { | |
2204 // We must retain this membar if there is an upcoming volatile | |
2205 // load, which will be preceded by acquire membar. | |
2206 if (xop == Op_MemBarAcquire) | |
2207 return false; | |
2208 // For other kinds of barriers, check by pretending we | |
2209 // are them, and seeing if we can be removed. | |
2210 else | |
2211 return post_store_load_barrier((const MemBarNode*)x); | |
2212 } | |
2213 | |
2214 // Delicate code to detect case of an upcoming fastlock block | |
2215 if( x->is_If() && x->req() > 1 && | |
2216 !C->node_arena()->contains(x) ) { // Unmatched old-space only | |
2217 Node *iff = x; | |
2218 Node *bol = iff->in(1); | |
2219 // The iff might be some random subclass of If or bol might be Con-Top | |
2220 if (!bol->is_Bool()) return false; | |
2221 assert( bol->req() > 1, "" ); | |
2222 return (bol->in(1)->Opcode() == Op_FastUnlock); | |
2223 } | |
2224 // probably not necessary to check for these | |
2225 if (x->is_Call() || x->is_SafePoint() || x->is_block_proj()) | |
2226 return false; | |
2227 } | |
2228 return false; | |
2229 } | |
2230 | |
2231 //============================================================================= | |
2232 //---------------------------State--------------------------------------------- | |
2233 State::State(void) { | |
2234 #ifdef ASSERT | |
2235 _id = 0; | |
2236 _kids[0] = _kids[1] = (State*)(intptr_t) CONST64(0xcafebabecafebabe); | |
2237 _leaf = (Node*)(intptr_t) CONST64(0xbaadf00dbaadf00d); | |
2238 //memset(_cost, -1, sizeof(_cost)); | |
2239 //memset(_rule, -1, sizeof(_rule)); | |
2240 #endif | |
2241 memset(_valid, 0, sizeof(_valid)); | |
2242 } | |
2243 | |
2244 #ifdef ASSERT | |
2245 State::~State() { | |
2246 _id = 99; | |
2247 _kids[0] = _kids[1] = (State*)(intptr_t) CONST64(0xcafebabecafebabe); | |
2248 _leaf = (Node*)(intptr_t) CONST64(0xbaadf00dbaadf00d); | |
2249 memset(_cost, -3, sizeof(_cost)); | |
2250 memset(_rule, -3, sizeof(_rule)); | |
2251 } | |
2252 #endif | |
2253 | |
2254 #ifndef PRODUCT | |
2255 //---------------------------dump---------------------------------------------- | |
2256 void State::dump() { | |
2257 tty->print("\n"); | |
2258 dump(0); | |
2259 } | |
2260 | |
2261 void State::dump(int depth) { | |
2262 for( int j = 0; j < depth; j++ ) | |
2263 tty->print(" "); | |
2264 tty->print("--N: "); | |
2265 _leaf->dump(); | |
2266 uint i; | |
2267 for( i = 0; i < _LAST_MACH_OPER; i++ ) | |
2268 // Check for valid entry | |
2269 if( valid(i) ) { | |
2270 for( int j = 0; j < depth; j++ ) | |
2271 tty->print(" "); | |
2272 assert(_cost[i] != max_juint, "cost must be a valid value"); | |
2273 assert(_rule[i] < _last_Mach_Node, "rule[i] must be valid rule"); | |
2274 tty->print_cr("%s %d %s", | |
2275 ruleName[i], _cost[i], ruleName[_rule[i]] ); | |
2276 } | |
2277 tty->print_cr(""); | |
2278 | |
2279 for( i=0; i<2; i++ ) | |
2280 if( _kids[i] ) | |
2281 _kids[i]->dump(depth+1); | |
2282 } | |
2283 #endif |