File: | jdk/src/hotspot/share/c1/c1_IR.cpp |
Warning: | line 478, column 71 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. | |||
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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |||
20 | * or visit www.oracle.com if you need additional information or have any | |||
21 | * questions. | |||
22 | * | |||
23 | */ | |||
24 | ||||
25 | #include "precompiled.hpp" | |||
26 | #include "c1/c1_Compilation.hpp" | |||
27 | #include "c1/c1_FrameMap.hpp" | |||
28 | #include "c1/c1_GraphBuilder.hpp" | |||
29 | #include "c1/c1_IR.hpp" | |||
30 | #include "c1/c1_InstructionPrinter.hpp" | |||
31 | #include "c1/c1_Optimizer.hpp" | |||
32 | #include "compiler/oopMap.hpp" | |||
33 | #include "memory/resourceArea.hpp" | |||
34 | #include "utilities/bitMap.inline.hpp" | |||
35 | ||||
36 | ||||
37 | // Implementation of XHandlers | |||
38 | // | |||
39 | // Note: This code could eventually go away if we are | |||
40 | // just using the ciExceptionHandlerStream. | |||
41 | ||||
42 | XHandlers::XHandlers(ciMethod* method) : _list(method->exception_table_length()) { | |||
43 | ciExceptionHandlerStream s(method); | |||
44 | while (!s.is_done()) { | |||
45 | _list.append(new XHandler(s.handler())); | |||
46 | s.next(); | |||
47 | } | |||
48 | assert(s.count() == method->exception_table_length(), "exception table lengths inconsistent")do { if (!(s.count() == method->exception_table_length())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 48, "assert(" "s.count() == method->exception_table_length()" ") failed", "exception table lengths inconsistent"); ::breakpoint (); } } while (0); | |||
49 | } | |||
50 | ||||
51 | // deep copy of all XHandler contained in list | |||
52 | XHandlers::XHandlers(XHandlers* other) : | |||
53 | _list(other->length()) | |||
54 | { | |||
55 | for (int i = 0; i < other->length(); i++) { | |||
56 | _list.append(new XHandler(other->handler_at(i))); | |||
57 | } | |||
58 | } | |||
59 | ||||
60 | // Returns whether a particular exception type can be caught. Also | |||
61 | // returns true if klass is unloaded or any exception handler | |||
62 | // classes are unloaded. type_is_exact indicates whether the throw | |||
63 | // is known to be exactly that class or it might throw a subtype. | |||
64 | bool XHandlers::could_catch(ciInstanceKlass* klass, bool type_is_exact) const { | |||
65 | // the type is unknown so be conservative | |||
66 | if (!klass->is_loaded()) { | |||
67 | return true; | |||
68 | } | |||
69 | ||||
70 | for (int i = 0; i < length(); i++) { | |||
71 | XHandler* handler = handler_at(i); | |||
72 | if (handler->is_catch_all()) { | |||
73 | // catch of ANY | |||
74 | return true; | |||
75 | } | |||
76 | ciInstanceKlass* handler_klass = handler->catch_klass(); | |||
77 | // if it's unknown it might be catchable | |||
78 | if (!handler_klass->is_loaded()) { | |||
79 | return true; | |||
80 | } | |||
81 | // if the throw type is definitely a subtype of the catch type | |||
82 | // then it can be caught. | |||
83 | if (klass->is_subtype_of(handler_klass)) { | |||
84 | return true; | |||
85 | } | |||
86 | if (!type_is_exact) { | |||
87 | // If the type isn't exactly known then it can also be caught by | |||
88 | // catch statements where the inexact type is a subtype of the | |||
89 | // catch type. | |||
90 | // given: foo extends bar extends Exception | |||
91 | // throw bar can be caught by catch foo, catch bar, and catch | |||
92 | // Exception, however it can't be caught by any handlers without | |||
93 | // bar in its type hierarchy. | |||
94 | if (handler_klass->is_subtype_of(klass)) { | |||
95 | return true; | |||
96 | } | |||
97 | } | |||
98 | } | |||
99 | ||||
100 | return false; | |||
101 | } | |||
102 | ||||
103 | ||||
104 | bool XHandlers::equals(XHandlers* others) const { | |||
105 | if (others == NULL__null) return false; | |||
106 | if (length() != others->length()) return false; | |||
107 | ||||
108 | for (int i = 0; i < length(); i++) { | |||
109 | if (!handler_at(i)->equals(others->handler_at(i))) return false; | |||
110 | } | |||
111 | return true; | |||
112 | } | |||
113 | ||||
114 | bool XHandler::equals(XHandler* other) const { | |||
115 | assert(entry_pco() != -1 && other->entry_pco() != -1, "must have entry_pco")do { if (!(entry_pco() != -1 && other->entry_pco() != -1)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 115, "assert(" "entry_pco() != -1 && other->entry_pco() != -1" ") failed", "must have entry_pco"); ::breakpoint(); } } while (0); | |||
116 | ||||
117 | if (entry_pco() != other->entry_pco()) return false; | |||
118 | if (scope_count() != other->scope_count()) return false; | |||
119 | if (_desc != other->_desc) return false; | |||
120 | ||||
121 | assert(entry_block() == other->entry_block(), "entry_block must be equal when entry_pco is equal")do { if (!(entry_block() == other->entry_block())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 121, "assert(" "entry_block() == other->entry_block()" ") failed" , "entry_block must be equal when entry_pco is equal"); ::breakpoint (); } } while (0); | |||
122 | return true; | |||
123 | } | |||
124 | ||||
125 | ||||
126 | // Implementation of IRScope | |||
127 | BlockBegin* IRScope::build_graph(Compilation* compilation, int osr_bci) { | |||
128 | GraphBuilder gm(compilation, this); | |||
129 | NOT_PRODUCT(if (PrintValueNumbering && Verbose) gm.print_stats())if (PrintValueNumbering && Verbose) gm.print_stats(); | |||
130 | if (compilation->bailed_out()) return NULL__null; | |||
131 | return gm.start(); | |||
132 | } | |||
133 | ||||
134 | ||||
135 | IRScope::IRScope(Compilation* compilation, IRScope* caller, int caller_bci, ciMethod* method, int osr_bci, bool create_graph) | |||
136 | : _compilation(compilation) | |||
137 | , _callees(2) | |||
138 | , _requires_phi_function(method->max_locals()) | |||
139 | { | |||
140 | _caller = caller; | |||
141 | _level = caller == NULL__null ? 0 : caller->level() + 1; | |||
142 | _method = method; | |||
143 | _xhandlers = new XHandlers(method); | |||
144 | _number_of_locks = 0; | |||
145 | _monitor_pairing_ok = method->has_balanced_monitors(); | |||
146 | _wrote_final = false; | |||
147 | _wrote_fields = false; | |||
148 | _wrote_volatile = false; | |||
149 | _start = NULL__null; | |||
150 | ||||
151 | if (osr_bci != -1) { | |||
152 | // selective creation of phi functions is not possibel in osr-methods | |||
153 | _requires_phi_function.set_range(0, method->max_locals()); | |||
154 | } | |||
155 | ||||
156 | assert(method->holder()->is_loaded() , "method holder must be loaded")do { if (!(method->holder()->is_loaded())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 156, "assert(" "method->holder()->is_loaded()" ") failed" , "method holder must be loaded"); ::breakpoint(); } } while ( 0); | |||
157 | ||||
158 | // build graph if monitor pairing is ok | |||
159 | if (create_graph && monitor_pairing_ok()) _start = build_graph(compilation, osr_bci); | |||
160 | } | |||
161 | ||||
162 | ||||
163 | int IRScope::max_stack() const { | |||
164 | int my_max = method()->max_stack(); | |||
165 | int callee_max = 0; | |||
166 | for (int i = 0; i < number_of_callees(); i++) { | |||
167 | callee_max = MAX2(callee_max, callee_no(i)->max_stack()); | |||
168 | } | |||
169 | return my_max + callee_max; | |||
170 | } | |||
171 | ||||
172 | ||||
173 | bool IRScopeDebugInfo::should_reexecute() { | |||
174 | ciMethod* cur_method = scope()->method(); | |||
175 | int cur_bci = bci(); | |||
176 | if (cur_method != NULL__null && cur_bci != SynchronizationEntryBCI) { | |||
177 | Bytecodes::Code code = cur_method->java_code_at_bci(cur_bci); | |||
178 | return Interpreter::bytecode_should_reexecute(code); | |||
179 | } else | |||
180 | return false; | |||
181 | } | |||
182 | ||||
183 | ||||
184 | // Implementation of CodeEmitInfo | |||
185 | ||||
186 | // Stack must be NON-null | |||
187 | CodeEmitInfo::CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers, bool deoptimize_on_exception) | |||
188 | : _scope_debug_info(NULL__null) | |||
189 | , _scope(stack->scope()) | |||
190 | , _exception_handlers(exception_handlers) | |||
191 | , _oop_map(NULL__null) | |||
192 | , _stack(stack) | |||
193 | , _is_method_handle_invoke(false) | |||
194 | , _deoptimize_on_exception(deoptimize_on_exception) | |||
195 | , _force_reexecute(false) { | |||
196 | assert(_stack != NULL, "must be non null")do { if (!(_stack != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 196, "assert(" "_stack != __null" ") failed", "must be non null" ); ::breakpoint(); } } while (0); | |||
197 | } | |||
198 | ||||
199 | ||||
200 | CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, ValueStack* stack) | |||
201 | : _scope_debug_info(NULL__null) | |||
202 | , _scope(info->_scope) | |||
203 | , _exception_handlers(NULL__null) | |||
204 | , _oop_map(NULL__null) | |||
205 | , _stack(stack == NULL__null ? info->_stack : stack) | |||
206 | , _is_method_handle_invoke(info->_is_method_handle_invoke) | |||
207 | , _deoptimize_on_exception(info->_deoptimize_on_exception) | |||
208 | , _force_reexecute(info->_force_reexecute) { | |||
209 | ||||
210 | // deep copy of exception handlers | |||
211 | if (info->_exception_handlers != NULL__null) { | |||
212 | _exception_handlers = new XHandlers(info->_exception_handlers); | |||
213 | } | |||
214 | } | |||
215 | ||||
216 | ||||
217 | void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) { | |||
218 | // record the safepoint before recording the debug info for enclosing scopes | |||
219 | recorder->add_safepoint(pc_offset, _oop_map->deep_copy()); | |||
220 | bool reexecute = _force_reexecute || _scope_debug_info->should_reexecute(); | |||
221 | _scope_debug_info->record_debug_info(recorder, pc_offset, reexecute, _is_method_handle_invoke); | |||
222 | recorder->end_safepoint(pc_offset); | |||
223 | } | |||
224 | ||||
225 | ||||
226 | void CodeEmitInfo::add_register_oop(LIR_Opr opr) { | |||
227 | assert(_oop_map != NULL, "oop map must already exist")do { if (!(_oop_map != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 227, "assert(" "_oop_map != __null" ") failed", "oop map must already exist" ); ::breakpoint(); } } while (0); | |||
228 | assert(opr->is_single_cpu(), "should not call otherwise")do { if (!(opr->is_single_cpu())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 228, "assert(" "opr->is_single_cpu()" ") failed", "should not call otherwise" ); ::breakpoint(); } } while (0); | |||
229 | ||||
230 | VMReg name = frame_map()->regname(opr); | |||
231 | _oop_map->set_oop(name); | |||
232 | } | |||
233 | ||||
234 | // Mirror the stack size calculation in the deopt code | |||
235 | // How much stack space would we need at this point in the program in | |||
236 | // case of deoptimization? | |||
237 | int CodeEmitInfo::interpreter_frame_size() const { | |||
238 | ValueStack* state = _stack; | |||
239 | int size = 0; | |||
240 | int callee_parameters = 0; | |||
241 | int callee_locals = 0; | |||
242 | int extra_args = state->scope()->method()->max_stack() - state->stack_size(); | |||
243 | ||||
244 | while (state != NULL__null) { | |||
245 | int locks = state->locks_size(); | |||
246 | int temps = state->stack_size(); | |||
247 | bool is_top_frame = (state == _stack); | |||
248 | ciMethod* method = state->scope()->method(); | |||
249 | ||||
250 | int frame_size = BytesPerWord * Interpreter::size_activation(method->max_stack(), | |||
251 | temps + callee_parameters, | |||
252 | extra_args, | |||
253 | locks, | |||
254 | callee_parameters, | |||
255 | callee_locals, | |||
256 | is_top_frame); | |||
257 | size += frame_size; | |||
258 | ||||
259 | callee_parameters = method->size_of_parameters(); | |||
260 | callee_locals = method->max_locals(); | |||
261 | extra_args = 0; | |||
262 | state = state->caller_state(); | |||
263 | } | |||
264 | return size + Deoptimization::last_frame_adjust(0, callee_locals) * BytesPerWord; | |||
265 | } | |||
266 | ||||
267 | // Implementation of IR | |||
268 | ||||
269 | IR::IR(Compilation* compilation, ciMethod* method, int osr_bci) : | |||
270 | _num_loops(0) { | |||
271 | // setup IR fields | |||
272 | _compilation = compilation; | |||
273 | _top_scope = new IRScope(compilation, NULL__null, -1, method, osr_bci, true); | |||
274 | _code = NULL__null; | |||
275 | } | |||
276 | ||||
277 | ||||
278 | void IR::optimize_blocks() { | |||
279 | Optimizer opt(this); | |||
280 | if (!compilation()->profile_branches()) { | |||
281 | if (DoCEE) { | |||
282 | opt.eliminate_conditional_expressions(); | |||
283 | #ifndef PRODUCT | |||
284 | if (PrintCFG || PrintCFG1) { tty->print_cr("CFG after CEE"); print(true); } | |||
285 | if (PrintIR || PrintIR1 ) { tty->print_cr("IR after CEE"); print(false); } | |||
286 | #endif | |||
287 | } | |||
288 | if (EliminateBlocks) { | |||
289 | opt.eliminate_blocks(); | |||
290 | #ifndef PRODUCT | |||
291 | if (PrintCFG || PrintCFG1) { tty->print_cr("CFG after block elimination"); print(true); } | |||
292 | if (PrintIR || PrintIR1 ) { tty->print_cr("IR after block elimination"); print(false); } | |||
293 | #endif | |||
294 | } | |||
295 | } | |||
296 | } | |||
297 | ||||
298 | void IR::eliminate_null_checks() { | |||
299 | Optimizer opt(this); | |||
300 | if (EliminateNullChecks) { | |||
301 | opt.eliminate_null_checks(); | |||
302 | #ifndef PRODUCT | |||
303 | if (PrintCFG || PrintCFG1) { tty->print_cr("CFG after null check elimination"); print(true); } | |||
304 | if (PrintIR || PrintIR1 ) { tty->print_cr("IR after null check elimination"); print(false); } | |||
305 | #endif | |||
306 | } | |||
307 | } | |||
308 | ||||
309 | ||||
310 | static int sort_pairs(BlockPair** a, BlockPair** b) { | |||
311 | if ((*a)->from() == (*b)->from()) { | |||
312 | return (*a)->to()->block_id() - (*b)->to()->block_id(); | |||
313 | } else { | |||
314 | return (*a)->from()->block_id() - (*b)->from()->block_id(); | |||
315 | } | |||
316 | } | |||
317 | ||||
318 | ||||
319 | class CriticalEdgeFinder: public BlockClosure { | |||
320 | BlockPairList blocks; | |||
321 | IR* _ir; | |||
322 | ||||
323 | public: | |||
324 | CriticalEdgeFinder(IR* ir): _ir(ir) {} | |||
325 | void block_do(BlockBegin* bb) { | |||
326 | BlockEnd* be = bb->end(); | |||
327 | int nos = be->number_of_sux(); | |||
328 | if (nos >= 2) { | |||
329 | for (int i = 0; i < nos; i++) { | |||
330 | BlockBegin* sux = be->sux_at(i); | |||
331 | if (sux->number_of_preds() >= 2) { | |||
332 | blocks.append(new BlockPair(bb, sux)); | |||
333 | } | |||
334 | } | |||
335 | } | |||
336 | } | |||
337 | ||||
338 | void split_edges() { | |||
339 | BlockPair* last_pair = NULL__null; | |||
340 | blocks.sort(sort_pairs); | |||
341 | for (int i = 0; i < blocks.length(); i++) { | |||
342 | BlockPair* pair = blocks.at(i); | |||
343 | if (last_pair != NULL__null && pair->is_same(last_pair)) continue; | |||
344 | BlockBegin* from = pair->from(); | |||
345 | BlockBegin* to = pair->to(); | |||
346 | BlockBegin* split = from->insert_block_between(to); | |||
347 | #ifndef PRODUCT | |||
348 | if ((PrintIR || PrintIR1) && Verbose) { | |||
349 | tty->print_cr("Split critical edge B%d -> B%d (new block B%d)", | |||
350 | from->block_id(), to->block_id(), split->block_id()); | |||
351 | } | |||
352 | #endif | |||
353 | last_pair = pair; | |||
354 | } | |||
355 | } | |||
356 | }; | |||
357 | ||||
358 | void IR::split_critical_edges() { | |||
359 | CriticalEdgeFinder cef(this); | |||
360 | ||||
361 | iterate_preorder(&cef); | |||
362 | cef.split_edges(); | |||
363 | } | |||
364 | ||||
365 | ||||
366 | class UseCountComputer: public ValueVisitor, BlockClosure { | |||
367 | private: | |||
368 | void visit(Value* n) { | |||
369 | // Local instructions and Phis for expression stack values at the | |||
370 | // start of basic blocks are not added to the instruction list | |||
371 | if (!(*n)->is_linked() && (*n)->can_be_linked()) { | |||
372 | assert(false, "a node was not appended to the graph")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 372, "assert(" "false" ") failed", "a node was not appended to the graph" ); ::breakpoint(); } } while (0); | |||
373 | Compilation::current()->bailout("a node was not appended to the graph"); | |||
374 | } | |||
375 | // use n's input if not visited before | |||
376 | if (!(*n)->is_pinned() && !(*n)->has_uses()) { | |||
377 | // note: a) if the instruction is pinned, it will be handled by compute_use_count | |||
378 | // b) if the instruction has uses, it was touched before | |||
379 | // => in both cases we don't need to update n's values | |||
380 | uses_do(n); | |||
381 | } | |||
382 | // use n | |||
383 | (*n)->_use_count++; | |||
384 | } | |||
385 | ||||
386 | Values* worklist; | |||
387 | int depth; | |||
388 | enum { | |||
389 | max_recurse_depth = 20 | |||
390 | }; | |||
391 | ||||
392 | void uses_do(Value* n) { | |||
393 | depth++; | |||
394 | if (depth > max_recurse_depth) { | |||
395 | // don't allow the traversal to recurse too deeply | |||
396 | worklist->push(*n); | |||
397 | } else { | |||
398 | (*n)->input_values_do(this); | |||
399 | // special handling for some instructions | |||
400 | if ((*n)->as_BlockEnd() != NULL__null) { | |||
401 | // note on BlockEnd: | |||
402 | // must 'use' the stack only if the method doesn't | |||
403 | // terminate, however, in those cases stack is empty | |||
404 | (*n)->state_values_do(this); | |||
405 | } | |||
406 | } | |||
407 | depth--; | |||
408 | } | |||
409 | ||||
410 | void block_do(BlockBegin* b) { | |||
411 | depth = 0; | |||
412 | // process all pinned nodes as the roots of expression trees | |||
413 | for (Instruction* n = b; n != NULL__null; n = n->next()) { | |||
414 | if (n->is_pinned()) uses_do(&n); | |||
415 | } | |||
416 | assert(depth == 0, "should have counted back down")do { if (!(depth == 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 416, "assert(" "depth == 0" ") failed", "should have counted back down" ); ::breakpoint(); } } while (0); | |||
417 | ||||
418 | // now process any unpinned nodes which recursed too deeply | |||
419 | while (worklist->length() > 0) { | |||
420 | Value t = worklist->pop(); | |||
421 | if (!t->is_pinned()) { | |||
422 | // compute the use count | |||
423 | uses_do(&t); | |||
424 | ||||
425 | // pin the instruction so that LIRGenerator doesn't recurse | |||
426 | // too deeply during it's evaluation. | |||
427 | t->pin(); | |||
428 | } | |||
429 | } | |||
430 | assert(depth == 0, "should have counted back down")do { if (!(depth == 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 430, "assert(" "depth == 0" ") failed", "should have counted back down" ); ::breakpoint(); } } while (0); | |||
431 | } | |||
432 | ||||
433 | UseCountComputer() { | |||
434 | worklist = new Values(); | |||
435 | depth = 0; | |||
436 | } | |||
437 | ||||
438 | public: | |||
439 | static void compute(BlockList* blocks) { | |||
440 | UseCountComputer ucc; | |||
441 | blocks->iterate_backward(&ucc); | |||
442 | } | |||
443 | }; | |||
444 | ||||
445 | ||||
446 | // helper macro for short definition of trace-output inside code | |||
447 | #ifdef ASSERT1 | |||
448 | #define TRACE_LINEAR_SCAN(level, code)if (TraceLinearScanLevel >= level) { code; } \ | |||
449 | if (TraceLinearScanLevel >= level) { \ | |||
450 | code; \ | |||
451 | } | |||
452 | #else | |||
453 | #define TRACE_LINEAR_SCAN(level, code)if (TraceLinearScanLevel >= level) { code; } | |||
454 | #endif | |||
455 | ||||
456 | class ComputeLinearScanOrder : public StackObj { | |||
457 | private: | |||
458 | int _max_block_id; // the highest block_id of a block | |||
459 | int _num_blocks; // total number of blocks (smaller than _max_block_id) | |||
460 | int _num_loops; // total number of loops | |||
461 | bool _iterative_dominators;// method requires iterative computation of dominatiors | |||
462 | ||||
463 | BlockList* _linear_scan_order; // the resulting list of blocks in correct order | |||
464 | ||||
465 | ResourceBitMap _visited_blocks; // used for recursive processing of blocks | |||
466 | ResourceBitMap _active_blocks; // used for recursive processing of blocks | |||
467 | ResourceBitMap _dominator_blocks; // temproary BitMap used for computation of dominator | |||
468 | intArray _forward_branches; // number of incoming forward branches for each block | |||
469 | BlockList _loop_end_blocks; // list of all loop end blocks collected during count_edges | |||
470 | BitMap2D _loop_map; // two-dimensional bit set: a bit is set if a block is contained in a loop | |||
471 | BlockList _work_list; // temporary list (used in mark_loops and compute_order) | |||
472 | BlockList _loop_headers; | |||
473 | ||||
474 | Compilation* _compilation; | |||
475 | ||||
476 | // accessors for _visited_blocks and _active_blocks | |||
477 | void init_visited() { _active_blocks.clear(); _visited_blocks.clear(); } | |||
478 | bool is_visited(BlockBegin* b) const { return _visited_blocks.at(b->block_id()); } | |||
| ||||
479 | bool is_active(BlockBegin* b) const { return _active_blocks.at(b->block_id()); } | |||
480 | void set_visited(BlockBegin* b) { assert(!is_visited(b), "already set")do { if (!(!is_visited(b))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 480, "assert(" "!is_visited(b)" ") failed", "already set"); ::breakpoint(); } } while (0); _visited_blocks.set_bit(b->block_id()); } | |||
481 | void set_active(BlockBegin* b) { assert(!is_active(b), "already set")do { if (!(!is_active(b))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 481, "assert(" "!is_active(b)" ") failed", "already set"); :: breakpoint(); } } while (0); _active_blocks.set_bit(b->block_id()); } | |||
482 | void clear_active(BlockBegin* b) { assert(is_active(b), "not already")do { if (!(is_active(b))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 482, "assert(" "is_active(b)" ") failed", "not already"); :: breakpoint(); } } while (0); _active_blocks.clear_bit(b->block_id()); } | |||
483 | ||||
484 | // accessors for _forward_branches | |||
485 | void inc_forward_branches(BlockBegin* b) { _forward_branches.at_put(b->block_id(), _forward_branches.at(b->block_id()) + 1); } | |||
486 | int dec_forward_branches(BlockBegin* b) { _forward_branches.at_put(b->block_id(), _forward_branches.at(b->block_id()) - 1); return _forward_branches.at(b->block_id()); } | |||
487 | ||||
488 | // accessors for _loop_map | |||
489 | bool is_block_in_loop (int loop_idx, BlockBegin* b) const { return _loop_map.at(loop_idx, b->block_id()); } | |||
490 | void set_block_in_loop (int loop_idx, BlockBegin* b) { _loop_map.set_bit(loop_idx, b->block_id()); } | |||
491 | void clear_block_in_loop(int loop_idx, int block_id) { _loop_map.clear_bit(loop_idx, block_id); } | |||
492 | ||||
493 | // count edges between blocks | |||
494 | void count_edges(BlockBegin* cur, BlockBegin* parent); | |||
495 | ||||
496 | // loop detection | |||
497 | void mark_loops(); | |||
498 | void clear_non_natural_loops(BlockBegin* start_block); | |||
499 | void assign_loop_depth(BlockBegin* start_block); | |||
500 | ||||
501 | // computation of final block order | |||
502 | BlockBegin* common_dominator(BlockBegin* a, BlockBegin* b); | |||
503 | void compute_dominator(BlockBegin* cur, BlockBegin* parent); | |||
504 | void compute_dominator_impl(BlockBegin* cur, BlockBegin* parent); | |||
505 | int compute_weight(BlockBegin* cur); | |||
506 | bool ready_for_processing(BlockBegin* cur); | |||
507 | void sort_into_work_list(BlockBegin* b); | |||
508 | void append_block(BlockBegin* cur); | |||
509 | void compute_order(BlockBegin* start_block); | |||
510 | ||||
511 | // fixup of dominators for non-natural loops | |||
512 | bool compute_dominators_iter(); | |||
513 | void compute_dominators(); | |||
514 | ||||
515 | // debug functions | |||
516 | DEBUG_ONLY(void print_blocks();)void print_blocks(); | |||
517 | DEBUG_ONLY(void verify();)void verify(); | |||
518 | ||||
519 | Compilation* compilation() const { return _compilation; } | |||
520 | public: | |||
521 | ComputeLinearScanOrder(Compilation* c, BlockBegin* start_block); | |||
522 | ||||
523 | // accessors for final result | |||
524 | BlockList* linear_scan_order() const { return _linear_scan_order; } | |||
525 | int num_loops() const { return _num_loops; } | |||
526 | }; | |||
527 | ||||
528 | ||||
529 | ComputeLinearScanOrder::ComputeLinearScanOrder(Compilation* c, BlockBegin* start_block) : | |||
530 | _max_block_id(BlockBegin::number_of_blocks()), | |||
531 | _num_blocks(0), | |||
532 | _num_loops(0), | |||
533 | _iterative_dominators(false), | |||
534 | _linear_scan_order(NULL__null), // initialized later with correct size | |||
535 | _visited_blocks(_max_block_id), | |||
536 | _active_blocks(_max_block_id), | |||
537 | _dominator_blocks(_max_block_id), | |||
538 | _forward_branches(_max_block_id, _max_block_id, 0), | |||
539 | _loop_end_blocks(8), | |||
540 | _loop_map(0), // initialized later with correct size | |||
541 | _work_list(8), | |||
542 | _compilation(c) | |||
543 | { | |||
544 | TRACE_LINEAR_SCAN(2, tty->print_cr("***** computing linear-scan block order"))if (TraceLinearScanLevel >= 2) { tty->print_cr("***** computing linear-scan block order" ); }; | |||
545 | ||||
546 | count_edges(start_block, NULL__null); | |||
547 | ||||
548 | if (compilation()->is_profiling()) { | |||
549 | ciMethod *method = compilation()->method(); | |||
550 | if (!method->is_accessor()) { | |||
551 | ciMethodData* md = method->method_data_or_null(); | |||
552 | assert(md != NULL, "Sanity")do { if (!(md != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 552, "assert(" "md != __null" ") failed", "Sanity"); ::breakpoint (); } } while (0); | |||
553 | md->set_compilation_stats(_num_loops, _num_blocks); | |||
554 | } | |||
555 | } | |||
556 | ||||
557 | if (_num_loops > 0) { | |||
558 | mark_loops(); | |||
559 | clear_non_natural_loops(start_block); | |||
560 | assign_loop_depth(start_block); | |||
561 | } | |||
562 | ||||
563 | compute_order(start_block); | |||
564 | compute_dominators(); | |||
565 | ||||
566 | DEBUG_ONLY(print_blocks())print_blocks(); | |||
567 | DEBUG_ONLY(verify())verify(); | |||
568 | } | |||
569 | ||||
570 | ||||
571 | // Traverse the CFG: | |||
572 | // * count total number of blocks | |||
573 | // * count all incoming edges and backward incoming edges | |||
574 | // * number loop header blocks | |||
575 | // * create a list with all loop end blocks | |||
576 | void ComputeLinearScanOrder::count_edges(BlockBegin* cur, BlockBegin* parent) { | |||
577 | TRACE_LINEAR_SCAN(3, tty->print_cr("Enter count_edges for block B%d coming from B%d", cur->block_id(), parent != NULL ? parent->block_id() : -1))if (TraceLinearScanLevel >= 3) { tty->print_cr("Enter count_edges for block B%d coming from B%d" , cur->block_id(), parent != __null ? parent->block_id( ) : -1); }; | |||
578 | assert(cur->dominator() == NULL, "dominator already initialized")do { if (!(cur->dominator() == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 578, "assert(" "cur->dominator() == __null" ") failed", "dominator already initialized" ); ::breakpoint(); } } while (0); | |||
579 | ||||
580 | if (is_active(cur)) { | |||
581 | TRACE_LINEAR_SCAN(3, tty->print_cr("backward branch"))if (TraceLinearScanLevel >= 3) { tty->print_cr("backward branch" ); }; | |||
582 | assert(is_visited(cur), "block must be visisted when block is active")do { if (!(is_visited(cur))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 582, "assert(" "is_visited(cur)" ") failed", "block must be visisted when block is active" ); ::breakpoint(); } } while (0); | |||
583 | assert(parent != NULL, "must have parent")do { if (!(parent != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 583, "assert(" "parent != __null" ") failed", "must have parent" ); ::breakpoint(); } } while (0); | |||
584 | ||||
585 | cur->set(BlockBegin::backward_branch_target_flag); | |||
586 | ||||
587 | // When a loop header is also the start of an exception handler, then the backward branch is | |||
588 | // an exception edge. Because such edges are usually critical edges which cannot be split, the | |||
589 | // loop must be excluded here from processing. | |||
590 | if (cur->is_set(BlockBegin::exception_entry_flag)) { | |||
591 | // Make sure that dominators are correct in this weird situation | |||
592 | _iterative_dominators = true; | |||
593 | return; | |||
594 | } | |||
595 | ||||
596 | cur->set(BlockBegin::linear_scan_loop_header_flag); | |||
597 | parent->set(BlockBegin::linear_scan_loop_end_flag); | |||
598 | ||||
599 | assert(parent->number_of_sux() == 1 && parent->sux_at(0) == cur,do { if (!(parent->number_of_sux() == 1 && parent-> sux_at(0) == cur)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 600, "assert(" "parent->number_of_sux() == 1 && parent->sux_at(0) == cur" ") failed", "loop end blocks must have one successor (critical edges are split)" ); ::breakpoint(); } } while (0) | |||
600 | "loop end blocks must have one successor (critical edges are split)")do { if (!(parent->number_of_sux() == 1 && parent-> sux_at(0) == cur)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 600, "assert(" "parent->number_of_sux() == 1 && parent->sux_at(0) == cur" ") failed", "loop end blocks must have one successor (critical edges are split)" ); ::breakpoint(); } } while (0); | |||
601 | ||||
602 | _loop_end_blocks.append(parent); | |||
603 | return; | |||
604 | } | |||
605 | ||||
606 | // increment number of incoming forward branches | |||
607 | inc_forward_branches(cur); | |||
608 | ||||
609 | if (is_visited(cur)) { | |||
610 | TRACE_LINEAR_SCAN(3, tty->print_cr("block already visited"))if (TraceLinearScanLevel >= 3) { tty->print_cr("block already visited" ); }; | |||
611 | return; | |||
612 | } | |||
613 | ||||
614 | _num_blocks++; | |||
615 | set_visited(cur); | |||
616 | set_active(cur); | |||
617 | ||||
618 | // recursive call for all successors | |||
619 | int i; | |||
620 | for (i = cur->number_of_sux() - 1; i >= 0; i--) { | |||
621 | count_edges(cur->sux_at(i), cur); | |||
622 | } | |||
623 | for (i = cur->number_of_exception_handlers() - 1; i >= 0; i--) { | |||
624 | count_edges(cur->exception_handler_at(i), cur); | |||
625 | } | |||
626 | ||||
627 | clear_active(cur); | |||
628 | ||||
629 | // Each loop has a unique number. | |||
630 | // When multiple loops are nested, assign_loop_depth assumes that the | |||
631 | // innermost loop has the lowest number. This is guaranteed by setting | |||
632 | // the loop number after the recursive calls for the successors above | |||
633 | // have returned. | |||
634 | if (cur->is_set(BlockBegin::linear_scan_loop_header_flag)) { | |||
635 | assert(cur->loop_index() == -1, "cannot set loop-index twice")do { if (!(cur->loop_index() == -1)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 635, "assert(" "cur->loop_index() == -1" ") failed", "cannot set loop-index twice" ); ::breakpoint(); } } while (0); | |||
636 | TRACE_LINEAR_SCAN(3, tty->print_cr("Block B%d is loop header of loop %d", cur->block_id(), _num_loops))if (TraceLinearScanLevel >= 3) { tty->print_cr("Block B%d is loop header of loop %d" , cur->block_id(), _num_loops); }; | |||
637 | ||||
638 | cur->set_loop_index(_num_loops); | |||
639 | _loop_headers.append(cur); | |||
640 | _num_loops++; | |||
641 | } | |||
642 | ||||
643 | TRACE_LINEAR_SCAN(3, tty->print_cr("Finished count_edges for block B%d", cur->block_id()))if (TraceLinearScanLevel >= 3) { tty->print_cr("Finished count_edges for block B%d" , cur->block_id()); }; | |||
644 | } | |||
645 | ||||
646 | ||||
647 | void ComputeLinearScanOrder::mark_loops() { | |||
648 | TRACE_LINEAR_SCAN(3, tty->print_cr("----- marking loops"))if (TraceLinearScanLevel >= 3) { tty->print_cr("----- marking loops" ); }; | |||
649 | ||||
650 | _loop_map = BitMap2D(_num_loops, _max_block_id); | |||
651 | ||||
652 | for (int i = _loop_end_blocks.length() - 1; i >= 0; i--) { | |||
653 | BlockBegin* loop_end = _loop_end_blocks.at(i); | |||
654 | BlockBegin* loop_start = loop_end->sux_at(0); | |||
655 | int loop_idx = loop_start->loop_index(); | |||
656 | ||||
657 | TRACE_LINEAR_SCAN(3, tty->print_cr("Processing loop from B%d to B%d (loop %d):", loop_start->block_id(), loop_end->block_id(), loop_idx))if (TraceLinearScanLevel >= 3) { tty->print_cr("Processing loop from B%d to B%d (loop %d):" , loop_start->block_id(), loop_end->block_id(), loop_idx ); }; | |||
658 | assert(loop_end->is_set(BlockBegin::linear_scan_loop_end_flag), "loop end flag must be set")do { if (!(loop_end->is_set(BlockBegin::linear_scan_loop_end_flag ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 658, "assert(" "loop_end->is_set(BlockBegin::linear_scan_loop_end_flag)" ") failed", "loop end flag must be set"); ::breakpoint(); } } while (0); | |||
659 | assert(loop_end->number_of_sux() == 1, "incorrect number of successors")do { if (!(loop_end->number_of_sux() == 1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 659, "assert(" "loop_end->number_of_sux() == 1" ") failed" , "incorrect number of successors"); ::breakpoint(); } } while (0); | |||
660 | assert(loop_start->is_set(BlockBegin::linear_scan_loop_header_flag), "loop header flag must be set")do { if (!(loop_start->is_set(BlockBegin::linear_scan_loop_header_flag ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 660, "assert(" "loop_start->is_set(BlockBegin::linear_scan_loop_header_flag)" ") failed", "loop header flag must be set"); ::breakpoint(); } } while (0); | |||
661 | assert(loop_idx >= 0 && loop_idx < _num_loops, "loop index not set")do { if (!(loop_idx >= 0 && loop_idx < _num_loops )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 661, "assert(" "loop_idx >= 0 && loop_idx < _num_loops" ") failed", "loop index not set"); ::breakpoint(); } } while (0); | |||
662 | assert(_work_list.is_empty(), "work list must be empty before processing")do { if (!(_work_list.is_empty())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 662, "assert(" "_work_list.is_empty()" ") failed", "work list must be empty before processing" ); ::breakpoint(); } } while (0); | |||
663 | ||||
664 | // add the end-block of the loop to the working list | |||
665 | _work_list.push(loop_end); | |||
666 | set_block_in_loop(loop_idx, loop_end); | |||
667 | do { | |||
668 | BlockBegin* cur = _work_list.pop(); | |||
669 | ||||
670 | TRACE_LINEAR_SCAN(3, tty->print_cr(" processing B%d", cur->block_id()))if (TraceLinearScanLevel >= 3) { tty->print_cr(" processing B%d" , cur->block_id()); }; | |||
671 | assert(is_block_in_loop(loop_idx, cur), "bit in loop map must be set when block is in work list")do { if (!(is_block_in_loop(loop_idx, cur))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 671, "assert(" "is_block_in_loop(loop_idx, cur)" ") failed" , "bit in loop map must be set when block is in work list"); :: breakpoint(); } } while (0); | |||
672 | ||||
673 | // recursive processing of all predecessors ends when start block of loop is reached | |||
674 | if (cur != loop_start && !cur->is_set(BlockBegin::osr_entry_flag)) { | |||
675 | for (int j = cur->number_of_preds() - 1; j >= 0; j--) { | |||
676 | BlockBegin* pred = cur->pred_at(j); | |||
677 | ||||
678 | if (!is_block_in_loop(loop_idx, pred) /*&& !pred->is_set(BlockBeginosr_entry_flag)*/) { | |||
679 | // this predecessor has not been processed yet, so add it to work list | |||
680 | TRACE_LINEAR_SCAN(3, tty->print_cr(" pushing B%d", pred->block_id()))if (TraceLinearScanLevel >= 3) { tty->print_cr(" pushing B%d" , pred->block_id()); }; | |||
681 | _work_list.push(pred); | |||
682 | set_block_in_loop(loop_idx, pred); | |||
683 | } | |||
684 | } | |||
685 | } | |||
686 | } while (!_work_list.is_empty()); | |||
687 | } | |||
688 | } | |||
689 | ||||
690 | ||||
691 | // check for non-natural loops (loops where the loop header does not dominate | |||
692 | // all other loop blocks = loops with mulitple entries). | |||
693 | // such loops are ignored | |||
694 | void ComputeLinearScanOrder::clear_non_natural_loops(BlockBegin* start_block) { | |||
695 | for (int i = _num_loops - 1; i >= 0; i--) { | |||
696 | if (is_block_in_loop(i, start_block)) { | |||
697 | // loop i contains the entry block of the method | |||
698 | // -> this is not a natural loop, so ignore it | |||
699 | TRACE_LINEAR_SCAN(2, tty->print_cr("Loop %d is non-natural, so it is ignored", i))if (TraceLinearScanLevel >= 2) { tty->print_cr("Loop %d is non-natural, so it is ignored" , i); }; | |||
700 | ||||
701 | BlockBegin *loop_header = _loop_headers.at(i); | |||
702 | assert(loop_header->is_set(BlockBegin::linear_scan_loop_header_flag), "Must be loop header")do { if (!(loop_header->is_set(BlockBegin::linear_scan_loop_header_flag ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 702, "assert(" "loop_header->is_set(BlockBegin::linear_scan_loop_header_flag)" ") failed", "Must be loop header"); ::breakpoint(); } } while (0); | |||
703 | ||||
704 | for (int j = 0; j < loop_header->number_of_preds(); j++) { | |||
705 | BlockBegin *pred = loop_header->pred_at(j); | |||
706 | pred->clear(BlockBegin::linear_scan_loop_end_flag); | |||
707 | } | |||
708 | ||||
709 | loop_header->clear(BlockBegin::linear_scan_loop_header_flag); | |||
710 | ||||
711 | for (int block_id = _max_block_id - 1; block_id >= 0; block_id--) { | |||
712 | clear_block_in_loop(i, block_id); | |||
713 | } | |||
714 | _iterative_dominators = true; | |||
715 | } | |||
716 | } | |||
717 | } | |||
718 | ||||
719 | void ComputeLinearScanOrder::assign_loop_depth(BlockBegin* start_block) { | |||
720 | TRACE_LINEAR_SCAN(3, tty->print_cr("----- computing loop-depth and weight"))if (TraceLinearScanLevel >= 3) { tty->print_cr("----- computing loop-depth and weight" ); }; | |||
721 | init_visited(); | |||
722 | ||||
723 | assert(_work_list.is_empty(), "work list must be empty before processing")do { if (!(_work_list.is_empty())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 723, "assert(" "_work_list.is_empty()" ") failed", "work list must be empty before processing" ); ::breakpoint(); } } while (0); | |||
724 | _work_list.append(start_block); | |||
725 | ||||
726 | do { | |||
727 | BlockBegin* cur = _work_list.pop(); | |||
728 | ||||
729 | if (!is_visited(cur)) { | |||
730 | set_visited(cur); | |||
731 | TRACE_LINEAR_SCAN(4, tty->print_cr("Computing loop depth for block B%d", cur->block_id()))if (TraceLinearScanLevel >= 4) { tty->print_cr("Computing loop depth for block B%d" , cur->block_id()); }; | |||
732 | ||||
733 | // compute loop-depth and loop-index for the block | |||
734 | assert(cur->loop_depth() == 0, "cannot set loop-depth twice")do { if (!(cur->loop_depth() == 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 734, "assert(" "cur->loop_depth() == 0" ") failed", "cannot set loop-depth twice" ); ::breakpoint(); } } while (0); | |||
735 | int i; | |||
736 | int loop_depth = 0; | |||
737 | int min_loop_idx = -1; | |||
738 | for (i = _num_loops - 1; i >= 0; i--) { | |||
739 | if (is_block_in_loop(i, cur)) { | |||
740 | loop_depth++; | |||
741 | min_loop_idx = i; | |||
742 | } | |||
743 | } | |||
744 | cur->set_loop_depth(loop_depth); | |||
745 | cur->set_loop_index(min_loop_idx); | |||
746 | ||||
747 | // append all unvisited successors to work list | |||
748 | for (i = cur->number_of_sux() - 1; i >= 0; i--) { | |||
749 | _work_list.append(cur->sux_at(i)); | |||
750 | } | |||
751 | for (i = cur->number_of_exception_handlers() - 1; i >= 0; i--) { | |||
752 | _work_list.append(cur->exception_handler_at(i)); | |||
753 | } | |||
754 | } | |||
755 | } while (!_work_list.is_empty()); | |||
756 | } | |||
757 | ||||
758 | ||||
759 | BlockBegin* ComputeLinearScanOrder::common_dominator(BlockBegin* a, BlockBegin* b) { | |||
760 | assert(a != NULL && b != NULL, "must have input blocks")do { if (!(a != __null && b != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 760, "assert(" "a != __null && b != __null" ") failed" , "must have input blocks"); ::breakpoint(); } } while (0); | |||
761 | ||||
762 | _dominator_blocks.clear(); | |||
763 | while (a != NULL__null) { | |||
764 | _dominator_blocks.set_bit(a->block_id()); | |||
765 | assert(a->dominator() != NULL || a == _linear_scan_order->at(0), "dominator must be initialized")do { if (!(a->dominator() != __null || a == _linear_scan_order ->at(0))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 765, "assert(" "a->dominator() != __null || a == _linear_scan_order->at(0)" ") failed", "dominator must be initialized"); ::breakpoint() ; } } while (0); | |||
766 | a = a->dominator(); | |||
767 | } | |||
768 | while (b != NULL__null && !_dominator_blocks.at(b->block_id())) { | |||
769 | assert(b->dominator() != NULL || b == _linear_scan_order->at(0), "dominator must be initialized")do { if (!(b->dominator() != __null || b == _linear_scan_order ->at(0))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 769, "assert(" "b->dominator() != __null || b == _linear_scan_order->at(0)" ") failed", "dominator must be initialized"); ::breakpoint() ; } } while (0); | |||
770 | b = b->dominator(); | |||
771 | } | |||
772 | ||||
773 | assert(b != NULL, "could not find dominator")do { if (!(b != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 773, "assert(" "b != __null" ") failed", "could not find dominator" ); ::breakpoint(); } } while (0); | |||
774 | return b; | |||
775 | } | |||
776 | ||||
777 | void ComputeLinearScanOrder::compute_dominator(BlockBegin* cur, BlockBegin* parent) { | |||
778 | init_visited(); | |||
779 | compute_dominator_impl(cur, parent); | |||
780 | } | |||
781 | ||||
782 | void ComputeLinearScanOrder::compute_dominator_impl(BlockBegin* cur, BlockBegin* parent) { | |||
783 | // Mark as visited to avoid recursive calls with same parent | |||
784 | set_visited(cur); | |||
785 | ||||
786 | if (cur->dominator() == NULL__null) { | |||
787 | TRACE_LINEAR_SCAN(4, tty->print_cr("DOM: initializing dominator of B%d to B%d", cur->block_id(), parent->block_id()))if (TraceLinearScanLevel >= 4) { tty->print_cr("DOM: initializing dominator of B%d to B%d" , cur->block_id(), parent->block_id()); }; | |||
788 | cur->set_dominator(parent); | |||
789 | ||||
790 | } else if (!(cur->is_set(BlockBegin::linear_scan_loop_header_flag) && parent->is_set(BlockBegin::linear_scan_loop_end_flag))) { | |||
791 | TRACE_LINEAR_SCAN(4, tty->print_cr("DOM: computing dominator of B%d: common dominator of B%d and B%d is B%d", cur->block_id(), parent->block_id(), cur->dominator()->block_id(), common_dominator(cur->dominator(), parent)->block_id()))if (TraceLinearScanLevel >= 4) { tty->print_cr("DOM: computing dominator of B%d: common dominator of B%d and B%d is B%d" , cur->block_id(), parent->block_id(), cur->dominator ()->block_id(), common_dominator(cur->dominator(), parent )->block_id()); }; | |||
792 | // Does not hold for exception blocks | |||
793 | assert(cur->number_of_preds() > 1 || cur->is_set(BlockBegin::exception_entry_flag), "")do { if (!(cur->number_of_preds() > 1 || cur->is_set (BlockBegin::exception_entry_flag))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 793, "assert(" "cur->number_of_preds() > 1 || cur->is_set(BlockBegin::exception_entry_flag)" ") failed", ""); ::breakpoint(); } } while (0); | |||
794 | cur->set_dominator(common_dominator(cur->dominator(), parent)); | |||
795 | } | |||
796 | ||||
797 | // Additional edge to xhandler of all our successors | |||
798 | // range check elimination needs that the state at the end of a | |||
799 | // block be valid in every block it dominates so cur must dominate | |||
800 | // the exception handlers of its successors. | |||
801 | int num_cur_xhandler = cur->number_of_exception_handlers(); | |||
802 | for (int j = 0; j < num_cur_xhandler; j++) { | |||
803 | BlockBegin* xhandler = cur->exception_handler_at(j); | |||
804 | if (!is_visited(xhandler)) { | |||
805 | compute_dominator_impl(xhandler, parent); | |||
806 | } | |||
807 | } | |||
808 | } | |||
809 | ||||
810 | ||||
811 | int ComputeLinearScanOrder::compute_weight(BlockBegin* cur) { | |||
812 | BlockBegin* single_sux = NULL__null; | |||
813 | if (cur->number_of_sux() == 1) { | |||
814 | single_sux = cur->sux_at(0); | |||
815 | } | |||
816 | ||||
817 | // limit loop-depth to 15 bit (only for security reason, it will never be so big) | |||
818 | int weight = (cur->loop_depth() & 0x7FFF) << 16; | |||
819 | ||||
820 | // general macro for short definition of weight flags | |||
821 | // the first instance of INC_WEIGHT_IF has the highest priority | |||
822 | int cur_bit = 15; | |||
823 | #define INC_WEIGHT_IF(condition) if ((condition)) { weight |= (1 << cur_bit); } cur_bit--; | |||
824 | ||||
825 | // this is necessery for the (very rare) case that two successing blocks have | |||
826 | // the same loop depth, but a different loop index (can happen for endless loops | |||
827 | // with exception handlers) | |||
828 | INC_WEIGHT_IF(!cur->is_set(BlockBegin::linear_scan_loop_header_flag)); | |||
829 | ||||
830 | // loop end blocks (blocks that end with a backward branch) are added | |||
831 | // after all other blocks of the loop. | |||
832 | INC_WEIGHT_IF(!cur->is_set(BlockBegin::linear_scan_loop_end_flag)); | |||
833 | ||||
834 | // critical edge split blocks are prefered because than they have a bigger | |||
835 | // proability to be completely empty | |||
836 | INC_WEIGHT_IF(cur->is_set(BlockBegin::critical_edge_split_flag)); | |||
837 | ||||
838 | // exceptions should not be thrown in normal control flow, so these blocks | |||
839 | // are added as late as possible | |||
840 | INC_WEIGHT_IF(cur->end()->as_Throw() == NULL__null && (single_sux == NULL__null || single_sux->end()->as_Throw() == NULL__null)); | |||
841 | INC_WEIGHT_IF(cur->end()->as_Return() == NULL__null && (single_sux == NULL__null || single_sux->end()->as_Return() == NULL__null)); | |||
842 | ||||
843 | // exceptions handlers are added as late as possible | |||
844 | INC_WEIGHT_IF(!cur->is_set(BlockBegin::exception_entry_flag)); | |||
845 | ||||
846 | // guarantee that weight is > 0 | |||
847 | weight |= 1; | |||
848 | ||||
849 | #undef INC_WEIGHT_IF | |||
850 | assert(cur_bit >= 0, "too many flags")do { if (!(cur_bit >= 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 850, "assert(" "cur_bit >= 0" ") failed", "too many flags" ); ::breakpoint(); } } while (0); | |||
851 | assert(weight > 0, "weight cannot become negative")do { if (!(weight > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 851, "assert(" "weight > 0" ") failed", "weight cannot become negative" ); ::breakpoint(); } } while (0); | |||
852 | ||||
853 | return weight; | |||
854 | } | |||
855 | ||||
856 | bool ComputeLinearScanOrder::ready_for_processing(BlockBegin* cur) { | |||
857 | // Discount the edge just traveled. | |||
858 | // When the number drops to zero, all forward branches were processed | |||
859 | if (dec_forward_branches(cur) != 0) { | |||
860 | return false; | |||
861 | } | |||
862 | ||||
863 | assert(_linear_scan_order->find(cur) == -1, "block already processed (block can be ready only once)")do { if (!(_linear_scan_order->find(cur) == -1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 863, "assert(" "_linear_scan_order->find(cur) == -1" ") failed" , "block already processed (block can be ready only once)"); :: breakpoint(); } } while (0); | |||
864 | assert(_work_list.find(cur) == -1, "block already in work-list (block can be ready only once)")do { if (!(_work_list.find(cur) == -1)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 864, "assert(" "_work_list.find(cur) == -1" ") failed", "block already in work-list (block can be ready only once)" ); ::breakpoint(); } } while (0); | |||
865 | return true; | |||
866 | } | |||
867 | ||||
868 | void ComputeLinearScanOrder::sort_into_work_list(BlockBegin* cur) { | |||
869 | assert(_work_list.find(cur) == -1, "block already in work list")do { if (!(_work_list.find(cur) == -1)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 869, "assert(" "_work_list.find(cur) == -1" ") failed", "block already in work list" ); ::breakpoint(); } } while (0); | |||
870 | ||||
871 | int cur_weight = compute_weight(cur); | |||
872 | ||||
873 | // the linear_scan_number is used to cache the weight of a block | |||
874 | cur->set_linear_scan_number(cur_weight); | |||
875 | ||||
876 | #ifndef PRODUCT | |||
877 | if (StressLinearScan) { | |||
878 | _work_list.insert_before(0, cur); | |||
879 | return; | |||
880 | } | |||
881 | #endif | |||
882 | ||||
883 | _work_list.append(NULL__null); // provide space for new element | |||
884 | ||||
885 | int insert_idx = _work_list.length() - 1; | |||
886 | while (insert_idx > 0 && _work_list.at(insert_idx - 1)->linear_scan_number() > cur_weight) { | |||
887 | _work_list.at_put(insert_idx, _work_list.at(insert_idx - 1)); | |||
888 | insert_idx--; | |||
889 | } | |||
890 | _work_list.at_put(insert_idx, cur); | |||
891 | ||||
892 | TRACE_LINEAR_SCAN(3, tty->print_cr("Sorted B%d into worklist. new worklist:", cur->block_id()))if (TraceLinearScanLevel >= 3) { tty->print_cr("Sorted B%d into worklist. new worklist:" , cur->block_id()); }; | |||
893 | TRACE_LINEAR_SCAN(3, for (int i = 0; i < _work_list.length(); i++) tty->print_cr("%8d B%2d weight:%6x", i, _work_list.at(i)->block_id(), _work_list.at(i)->linear_scan_number()))if (TraceLinearScanLevel >= 3) { for (int i = 0; i < _work_list .length(); i++) tty->print_cr("%8d B%2d weight:%6x", i, _work_list .at(i)->block_id(), _work_list.at(i)->linear_scan_number ()); }; | |||
894 | ||||
895 | #ifdef ASSERT1 | |||
896 | for (int i = 0; i < _work_list.length(); i++) { | |||
897 | assert(_work_list.at(i)->linear_scan_number() > 0, "weight not set")do { if (!(_work_list.at(i)->linear_scan_number() > 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 897, "assert(" "_work_list.at(i)->linear_scan_number() > 0" ") failed", "weight not set"); ::breakpoint(); } } while (0); | |||
898 | assert(i == 0 || _work_list.at(i - 1)->linear_scan_number() <= _work_list.at(i)->linear_scan_number(), "incorrect order in worklist")do { if (!(i == 0 || _work_list.at(i - 1)->linear_scan_number () <= _work_list.at(i)->linear_scan_number())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 898, "assert(" "i == 0 || _work_list.at(i - 1)->linear_scan_number() <= _work_list.at(i)->linear_scan_number()" ") failed", "incorrect order in worklist"); ::breakpoint(); } } while (0); | |||
899 | } | |||
900 | #endif | |||
901 | } | |||
902 | ||||
903 | void ComputeLinearScanOrder::append_block(BlockBegin* cur) { | |||
904 | TRACE_LINEAR_SCAN(3, tty->print_cr("appending block B%d (weight 0x%6x) to linear-scan order", cur->block_id(), cur->linear_scan_number()))if (TraceLinearScanLevel >= 3) { tty->print_cr("appending block B%d (weight 0x%6x) to linear-scan order" , cur->block_id(), cur->linear_scan_number()); }; | |||
905 | assert(_linear_scan_order->find(cur) == -1, "cannot add the same block twice")do { if (!(_linear_scan_order->find(cur) == -1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 905, "assert(" "_linear_scan_order->find(cur) == -1" ") failed" , "cannot add the same block twice"); ::breakpoint(); } } while (0); | |||
906 | ||||
907 | // currently, the linear scan order and code emit order are equal. | |||
908 | // therefore the linear_scan_number and the weight of a block must also | |||
909 | // be equal. | |||
910 | cur->set_linear_scan_number(_linear_scan_order->length()); | |||
911 | _linear_scan_order->append(cur); | |||
912 | } | |||
913 | ||||
914 | void ComputeLinearScanOrder::compute_order(BlockBegin* start_block) { | |||
915 | TRACE_LINEAR_SCAN(3, tty->print_cr("----- computing final block order"))if (TraceLinearScanLevel >= 3) { tty->print_cr("----- computing final block order" ); }; | |||
916 | ||||
917 | // the start block is always the first block in the linear scan order | |||
918 | _linear_scan_order = new BlockList(_num_blocks); | |||
919 | append_block(start_block); | |||
920 | ||||
921 | assert(start_block->end()->as_Base() != NULL, "start block must end with Base-instruction")do { if (!(start_block->end()->as_Base() != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 921, "assert(" "start_block->end()->as_Base() != __null" ") failed", "start block must end with Base-instruction"); :: breakpoint(); } } while (0); | |||
922 | BlockBegin* std_entry = ((Base*)start_block->end())->std_entry(); | |||
923 | BlockBegin* osr_entry = ((Base*)start_block->end())->osr_entry(); | |||
924 | ||||
925 | BlockBegin* sux_of_osr_entry = NULL__null; | |||
926 | if (osr_entry != NULL__null) { | |||
927 | // special handling for osr entry: | |||
928 | // ignore the edge between the osr entry and its successor for processing | |||
929 | // the osr entry block is added manually below | |||
930 | assert(osr_entry->number_of_sux() == 1, "osr entry must have exactly one successor")do { if (!(osr_entry->number_of_sux() == 1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 930, "assert(" "osr_entry->number_of_sux() == 1" ") failed" , "osr entry must have exactly one successor"); ::breakpoint( ); } } while (0); | |||
931 | assert(osr_entry->sux_at(0)->number_of_preds() >= 2, "sucessor of osr entry must have two predecessors (otherwise it is not present in normal control flow")do { if (!(osr_entry->sux_at(0)->number_of_preds() >= 2)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 931, "assert(" "osr_entry->sux_at(0)->number_of_preds() >= 2" ") failed", "sucessor of osr entry must have two predecessors (otherwise it is not present in normal control flow" ); ::breakpoint(); } } while (0); | |||
932 | ||||
933 | sux_of_osr_entry = osr_entry->sux_at(0); | |||
934 | dec_forward_branches(sux_of_osr_entry); | |||
935 | ||||
936 | compute_dominator(osr_entry, start_block); | |||
937 | _iterative_dominators = true; | |||
938 | } | |||
939 | compute_dominator(std_entry, start_block); | |||
940 | ||||
941 | // start processing with standard entry block | |||
942 | assert(_work_list.is_empty(), "list must be empty before processing")do { if (!(_work_list.is_empty())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 942, "assert(" "_work_list.is_empty()" ") failed", "list must be empty before processing" ); ::breakpoint(); } } while (0); | |||
943 | ||||
944 | if (ready_for_processing(std_entry)) { | |||
945 | sort_into_work_list(std_entry); | |||
946 | } else { | |||
947 | assert(false, "the std_entry must be ready for processing (otherwise, the method has no start block)")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 947, "assert(" "false" ") failed", "the std_entry must be ready for processing (otherwise, the method has no start block)" ); ::breakpoint(); } } while (0); | |||
948 | } | |||
949 | ||||
950 | do { | |||
951 | BlockBegin* cur = _work_list.pop(); | |||
952 | ||||
953 | if (cur == sux_of_osr_entry) { | |||
954 | // the osr entry block is ignored in normal processing, it is never added to the | |||
955 | // work list. Instead, it is added as late as possible manually here. | |||
956 | append_block(osr_entry); | |||
957 | compute_dominator(cur, osr_entry); | |||
958 | } | |||
959 | append_block(cur); | |||
960 | ||||
961 | int i; | |||
962 | int num_sux = cur->number_of_sux(); | |||
963 | // changed loop order to get "intuitive" order of if- and else-blocks | |||
964 | for (i = 0; i < num_sux; i++) { | |||
965 | BlockBegin* sux = cur->sux_at(i); | |||
966 | compute_dominator(sux, cur); | |||
967 | if (ready_for_processing(sux)) { | |||
968 | sort_into_work_list(sux); | |||
969 | } | |||
970 | } | |||
971 | num_sux = cur->number_of_exception_handlers(); | |||
972 | for (i = 0; i < num_sux; i++) { | |||
973 | BlockBegin* sux = cur->exception_handler_at(i); | |||
974 | if (ready_for_processing(sux)) { | |||
975 | sort_into_work_list(sux); | |||
976 | } | |||
977 | } | |||
978 | } while (_work_list.length() > 0); | |||
979 | } | |||
980 | ||||
981 | ||||
982 | bool ComputeLinearScanOrder::compute_dominators_iter() { | |||
983 | bool changed = false; | |||
984 | int num_blocks = _linear_scan_order->length(); | |||
985 | ||||
986 | assert(_linear_scan_order->at(0)->dominator() == NULL, "must not have dominator")do { if (!(_linear_scan_order->at(0)->dominator() == __null )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 986, "assert(" "_linear_scan_order->at(0)->dominator() == __null" ") failed", "must not have dominator"); ::breakpoint(); } } while (0); | |||
987 | assert(_linear_scan_order->at(0)->number_of_preds() == 0, "must not have predecessors")do { if (!(_linear_scan_order->at(0)->number_of_preds() == 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 987, "assert(" "_linear_scan_order->at(0)->number_of_preds() == 0" ") failed", "must not have predecessors"); ::breakpoint(); } } while (0); | |||
988 | for (int i = 1; i < num_blocks; i++) { | |||
989 | BlockBegin* block = _linear_scan_order->at(i); | |||
990 | ||||
991 | BlockBegin* dominator = block->pred_at(0); | |||
992 | int num_preds = block->number_of_preds(); | |||
993 | ||||
994 | TRACE_LINEAR_SCAN(4, tty->print_cr("DOM: Processing B%d", block->block_id()))if (TraceLinearScanLevel >= 4) { tty->print_cr("DOM: Processing B%d" , block->block_id()); }; | |||
995 | ||||
996 | for (int j = 0; j < num_preds; j++) { | |||
997 | ||||
998 | BlockBegin *pred = block->pred_at(j); | |||
999 | TRACE_LINEAR_SCAN(4, tty->print_cr(" DOM: Subrocessing B%d", pred->block_id()))if (TraceLinearScanLevel >= 4) { tty->print_cr(" DOM: Subrocessing B%d" , pred->block_id()); }; | |||
1000 | ||||
1001 | if (block->is_set(BlockBegin::exception_entry_flag)) { | |||
1002 | dominator = common_dominator(dominator, pred); | |||
1003 | int num_pred_preds = pred->number_of_preds(); | |||
1004 | for (int k = 0; k < num_pred_preds; k++) { | |||
1005 | dominator = common_dominator(dominator, pred->pred_at(k)); | |||
1006 | } | |||
1007 | } else { | |||
1008 | dominator = common_dominator(dominator, pred); | |||
1009 | } | |||
1010 | } | |||
1011 | ||||
1012 | if (dominator != block->dominator()) { | |||
1013 | TRACE_LINEAR_SCAN(4, tty->print_cr("DOM: updating dominator of B%d from B%d to B%d", block->block_id(), block->dominator()->block_id(), dominator->block_id()))if (TraceLinearScanLevel >= 4) { tty->print_cr("DOM: updating dominator of B%d from B%d to B%d" , block->block_id(), block->dominator()->block_id(), dominator->block_id()); }; | |||
1014 | ||||
1015 | block->set_dominator(dominator); | |||
1016 | changed = true; | |||
1017 | } | |||
1018 | } | |||
1019 | return changed; | |||
1020 | } | |||
1021 | ||||
1022 | void ComputeLinearScanOrder::compute_dominators() { | |||
1023 | TRACE_LINEAR_SCAN(3, tty->print_cr("----- computing dominators (iterative computation reqired: %d)", _iterative_dominators))if (TraceLinearScanLevel >= 3) { tty->print_cr("----- computing dominators (iterative computation reqired: %d)" , _iterative_dominators); }; | |||
1024 | ||||
1025 | // iterative computation of dominators is only required for methods with non-natural loops | |||
1026 | // and OSR-methods. For all other methods, the dominators computed when generating the | |||
1027 | // linear scan block order are correct. | |||
1028 | if (_iterative_dominators) { | |||
1029 | do { | |||
1030 | TRACE_LINEAR_SCAN(1, tty->print_cr("DOM: next iteration of fix-point calculation"))if (TraceLinearScanLevel >= 1) { tty->print_cr("DOM: next iteration of fix-point calculation" ); }; | |||
1031 | } while (compute_dominators_iter()); | |||
1032 | } | |||
1033 | ||||
1034 | // check that dominators are correct | |||
1035 | assert(!compute_dominators_iter(), "fix point not reached")do { if (!(!compute_dominators_iter())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1035, "assert(" "!compute_dominators_iter()" ") failed", "fix point not reached" ); ::breakpoint(); } } while (0); | |||
1036 | ||||
1037 | // Add Blocks to dominates-Array | |||
1038 | int num_blocks = _linear_scan_order->length(); | |||
1039 | for (int i = 0; i < num_blocks; i++) { | |||
1040 | BlockBegin* block = _linear_scan_order->at(i); | |||
1041 | ||||
1042 | BlockBegin *dom = block->dominator(); | |||
1043 | if (dom) { | |||
1044 | assert(dom->dominator_depth() != -1, "Dominator must have been visited before")do { if (!(dom->dominator_depth() != -1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1044, "assert(" "dom->dominator_depth() != -1" ") failed" , "Dominator must have been visited before"); ::breakpoint(); } } while (0); | |||
1045 | dom->dominates()->append(block); | |||
1046 | block->set_dominator_depth(dom->dominator_depth() + 1); | |||
1047 | } else { | |||
1048 | block->set_dominator_depth(0); | |||
1049 | } | |||
1050 | } | |||
1051 | } | |||
1052 | ||||
1053 | ||||
1054 | #ifdef ASSERT1 | |||
1055 | void ComputeLinearScanOrder::print_blocks() { | |||
1056 | if (TraceLinearScanLevel >= 2) { | |||
1057 | tty->print_cr("----- loop information:"); | |||
1058 | for (int block_idx = 0; block_idx < _linear_scan_order->length(); block_idx++) { | |||
1059 | BlockBegin* cur = _linear_scan_order->at(block_idx); | |||
1060 | ||||
1061 | tty->print("%4d: B%2d: ", cur->linear_scan_number(), cur->block_id()); | |||
1062 | for (int loop_idx = 0; loop_idx < _num_loops; loop_idx++) { | |||
1063 | tty->print ("%d ", is_block_in_loop(loop_idx, cur)); | |||
1064 | } | |||
1065 | tty->print_cr(" -> loop_index: %2d, loop_depth: %2d", cur->loop_index(), cur->loop_depth()); | |||
1066 | } | |||
1067 | } | |||
1068 | ||||
1069 | if (TraceLinearScanLevel >= 1) { | |||
1070 | tty->print_cr("----- linear-scan block order:"); | |||
1071 | for (int block_idx = 0; block_idx < _linear_scan_order->length(); block_idx++) { | |||
1072 | BlockBegin* cur = _linear_scan_order->at(block_idx); | |||
1073 | tty->print("%4d: B%2d loop: %2d depth: %2d", cur->linear_scan_number(), cur->block_id(), cur->loop_index(), cur->loop_depth()); | |||
1074 | ||||
1075 | tty->print(cur->is_set(BlockBegin::exception_entry_flag) ? " ex" : " "); | |||
1076 | tty->print(cur->is_set(BlockBegin::critical_edge_split_flag) ? " ce" : " "); | |||
1077 | tty->print(cur->is_set(BlockBegin::linear_scan_loop_header_flag) ? " lh" : " "); | |||
1078 | tty->print(cur->is_set(BlockBegin::linear_scan_loop_end_flag) ? " le" : " "); | |||
1079 | ||||
1080 | if (cur->dominator() != NULL__null) { | |||
1081 | tty->print(" dom: B%d ", cur->dominator()->block_id()); | |||
1082 | } else { | |||
1083 | tty->print(" dom: NULL "); | |||
1084 | } | |||
1085 | ||||
1086 | if (cur->number_of_preds() > 0) { | |||
1087 | tty->print(" preds: "); | |||
1088 | for (int j = 0; j < cur->number_of_preds(); j++) { | |||
1089 | BlockBegin* pred = cur->pred_at(j); | |||
1090 | tty->print("B%d ", pred->block_id()); | |||
1091 | } | |||
1092 | } | |||
1093 | if (cur->number_of_sux() > 0) { | |||
1094 | tty->print(" sux: "); | |||
1095 | for (int j = 0; j < cur->number_of_sux(); j++) { | |||
1096 | BlockBegin* sux = cur->sux_at(j); | |||
1097 | tty->print("B%d ", sux->block_id()); | |||
1098 | } | |||
1099 | } | |||
1100 | if (cur->number_of_exception_handlers() > 0) { | |||
1101 | tty->print(" ex: "); | |||
1102 | for (int j = 0; j < cur->number_of_exception_handlers(); j++) { | |||
1103 | BlockBegin* ex = cur->exception_handler_at(j); | |||
1104 | tty->print("B%d ", ex->block_id()); | |||
1105 | } | |||
1106 | } | |||
1107 | tty->cr(); | |||
1108 | } | |||
1109 | } | |||
1110 | } | |||
1111 | ||||
1112 | void ComputeLinearScanOrder::verify() { | |||
1113 | assert(_linear_scan_order->length() == _num_blocks, "wrong number of blocks in list")do { if (!(_linear_scan_order->length() == _num_blocks)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1113, "assert(" "_linear_scan_order->length() == _num_blocks" ") failed", "wrong number of blocks in list"); ::breakpoint( ); } } while (0); | |||
1114 | ||||
1115 | if (StressLinearScan) { | |||
1116 | // blocks are scrambled when StressLinearScan is used | |||
1117 | return; | |||
1118 | } | |||
1119 | ||||
1120 | // check that all successors of a block have a higher linear-scan-number | |||
1121 | // and that all predecessors of a block have a lower linear-scan-number | |||
1122 | // (only backward branches of loops are ignored) | |||
1123 | int i; | |||
1124 | for (i = 0; i < _linear_scan_order->length(); i++) { | |||
1125 | BlockBegin* cur = _linear_scan_order->at(i); | |||
1126 | ||||
1127 | assert(cur->linear_scan_number() == i, "incorrect linear_scan_number")do { if (!(cur->linear_scan_number() == i)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1127, "assert(" "cur->linear_scan_number() == i" ") failed" , "incorrect linear_scan_number"); ::breakpoint(); } } while ( 0); | |||
1128 | assert(cur->linear_scan_number() >= 0 && cur->linear_scan_number() == _linear_scan_order->find(cur), "incorrect linear_scan_number")do { if (!(cur->linear_scan_number() >= 0 && cur ->linear_scan_number() == _linear_scan_order->find(cur) )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1128, "assert(" "cur->linear_scan_number() >= 0 && cur->linear_scan_number() == _linear_scan_order->find(cur)" ") failed", "incorrect linear_scan_number"); ::breakpoint(); } } while (0); | |||
1129 | ||||
1130 | int j; | |||
1131 | for (j = cur->number_of_sux() - 1; j >= 0; j--) { | |||
1132 | BlockBegin* sux = cur->sux_at(j); | |||
1133 | ||||
1134 | assert(sux->linear_scan_number() >= 0 && sux->linear_scan_number() == _linear_scan_order->find(sux), "incorrect linear_scan_number")do { if (!(sux->linear_scan_number() >= 0 && sux ->linear_scan_number() == _linear_scan_order->find(sux) )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1134, "assert(" "sux->linear_scan_number() >= 0 && sux->linear_scan_number() == _linear_scan_order->find(sux)" ") failed", "incorrect linear_scan_number"); ::breakpoint(); } } while (0); | |||
1135 | if (!sux->is_set(BlockBegin::backward_branch_target_flag)) { | |||
1136 | assert(cur->linear_scan_number() < sux->linear_scan_number(), "invalid order")do { if (!(cur->linear_scan_number() < sux->linear_scan_number ())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1136, "assert(" "cur->linear_scan_number() < sux->linear_scan_number()" ") failed", "invalid order"); ::breakpoint(); } } while (0); | |||
1137 | } | |||
1138 | if (cur->loop_depth() == sux->loop_depth()) { | |||
1139 | assert(cur->loop_index() == sux->loop_index() || sux->is_set(BlockBegin::linear_scan_loop_header_flag), "successing blocks with same loop depth must have same loop index")do { if (!(cur->loop_index() == sux->loop_index() || sux ->is_set(BlockBegin::linear_scan_loop_header_flag))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1139, "assert(" "cur->loop_index() == sux->loop_index() || sux->is_set(BlockBegin::linear_scan_loop_header_flag)" ") failed", "successing blocks with same loop depth must have same loop index" ); ::breakpoint(); } } while (0); | |||
1140 | } | |||
1141 | } | |||
1142 | ||||
1143 | for (j = cur->number_of_preds() - 1; j >= 0; j--) { | |||
1144 | BlockBegin* pred = cur->pred_at(j); | |||
1145 | ||||
1146 | assert(pred->linear_scan_number() >= 0 && pred->linear_scan_number() == _linear_scan_order->find(pred), "incorrect linear_scan_number")do { if (!(pred->linear_scan_number() >= 0 && pred ->linear_scan_number() == _linear_scan_order->find(pred ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1146, "assert(" "pred->linear_scan_number() >= 0 && pred->linear_scan_number() == _linear_scan_order->find(pred)" ") failed", "incorrect linear_scan_number"); ::breakpoint(); } } while (0); | |||
1147 | if (!cur->is_set(BlockBegin::backward_branch_target_flag)) { | |||
1148 | assert(cur->linear_scan_number() > pred->linear_scan_number(), "invalid order")do { if (!(cur->linear_scan_number() > pred->linear_scan_number ())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1148, "assert(" "cur->linear_scan_number() > pred->linear_scan_number()" ") failed", "invalid order"); ::breakpoint(); } } while (0); | |||
1149 | } | |||
1150 | if (cur->loop_depth() == pred->loop_depth()) { | |||
1151 | assert(cur->loop_index() == pred->loop_index() || cur->is_set(BlockBegin::linear_scan_loop_header_flag), "successing blocks with same loop depth must have same loop index")do { if (!(cur->loop_index() == pred->loop_index() || cur ->is_set(BlockBegin::linear_scan_loop_header_flag))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1151, "assert(" "cur->loop_index() == pred->loop_index() || cur->is_set(BlockBegin::linear_scan_loop_header_flag)" ") failed", "successing blocks with same loop depth must have same loop index" ); ::breakpoint(); } } while (0); | |||
1152 | } | |||
1153 | ||||
1154 | assert(cur->dominator()->linear_scan_number() <= cur->pred_at(j)->linear_scan_number(), "dominator must be before predecessors")do { if (!(cur->dominator()->linear_scan_number() <= cur->pred_at(j)->linear_scan_number())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1154, "assert(" "cur->dominator()->linear_scan_number() <= cur->pred_at(j)->linear_scan_number()" ") failed", "dominator must be before predecessors"); ::breakpoint (); } } while (0); | |||
1155 | } | |||
1156 | ||||
1157 | // check dominator | |||
1158 | if (i == 0) { | |||
1159 | assert(cur->dominator() == NULL, "first block has no dominator")do { if (!(cur->dominator() == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1159, "assert(" "cur->dominator() == __null" ") failed", "first block has no dominator"); ::breakpoint(); } } while ( 0); | |||
1160 | } else { | |||
1161 | assert(cur->dominator() != NULL, "all but first block must have dominator")do { if (!(cur->dominator() != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1161, "assert(" "cur->dominator() != __null" ") failed", "all but first block must have dominator"); ::breakpoint(); } } while (0); | |||
1162 | } | |||
1163 | // Assertion does not hold for exception handlers | |||
1164 | assert(cur->number_of_preds() != 1 || cur->dominator() == cur->pred_at(0) || cur->is_set(BlockBegin::exception_entry_flag), "Single predecessor must also be dominator")do { if (!(cur->number_of_preds() != 1 || cur->dominator () == cur->pred_at(0) || cur->is_set(BlockBegin::exception_entry_flag ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1164, "assert(" "cur->number_of_preds() != 1 || cur->dominator() == cur->pred_at(0) || cur->is_set(BlockBegin::exception_entry_flag)" ") failed", "Single predecessor must also be dominator"); :: breakpoint(); } } while (0); | |||
1165 | } | |||
1166 | ||||
1167 | // check that all loops are continuous | |||
1168 | for (int loop_idx = 0; loop_idx < _num_loops; loop_idx++) { | |||
1169 | int block_idx = 0; | |||
1170 | assert(!is_block_in_loop(loop_idx, _linear_scan_order->at(block_idx)), "the first block must not be present in any loop")do { if (!(!is_block_in_loop(loop_idx, _linear_scan_order-> at(block_idx)))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1170, "assert(" "!is_block_in_loop(loop_idx, _linear_scan_order->at(block_idx))" ") failed", "the first block must not be present in any loop" ); ::breakpoint(); } } while (0); | |||
1171 | ||||
1172 | // skip blocks before the loop | |||
1173 | while (block_idx < _num_blocks && !is_block_in_loop(loop_idx, _linear_scan_order->at(block_idx))) { | |||
1174 | block_idx++; | |||
1175 | } | |||
1176 | // skip blocks of loop | |||
1177 | while (block_idx < _num_blocks && is_block_in_loop(loop_idx, _linear_scan_order->at(block_idx))) { | |||
1178 | block_idx++; | |||
1179 | } | |||
1180 | // after the first non-loop block, there must not be another loop-block | |||
1181 | while (block_idx < _num_blocks) { | |||
1182 | assert(!is_block_in_loop(loop_idx, _linear_scan_order->at(block_idx)), "loop not continuous in linear-scan order")do { if (!(!is_block_in_loop(loop_idx, _linear_scan_order-> at(block_idx)))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1182, "assert(" "!is_block_in_loop(loop_idx, _linear_scan_order->at(block_idx))" ") failed", "loop not continuous in linear-scan order"); ::breakpoint (); } } while (0); | |||
1183 | block_idx++; | |||
1184 | } | |||
1185 | } | |||
1186 | } | |||
1187 | #endif // ASSERT | |||
1188 | ||||
1189 | ||||
1190 | void IR::compute_code() { | |||
1191 | assert(is_valid(), "IR must be valid")do { if (!(is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1191, "assert(" "is_valid()" ") failed", "IR must be valid" ); ::breakpoint(); } } while (0); | |||
| ||||
1192 | ||||
1193 | ComputeLinearScanOrder compute_order(compilation(), start()); | |||
1194 | _num_loops = compute_order.num_loops(); | |||
1195 | _code = compute_order.linear_scan_order(); | |||
1196 | } | |||
1197 | ||||
1198 | ||||
1199 | void IR::compute_use_counts() { | |||
1200 | // make sure all values coming out of this block get evaluated. | |||
1201 | int num_blocks = _code->length(); | |||
1202 | for (int i = 0; i < num_blocks; i++) { | |||
1203 | _code->at(i)->end()->state()->pin_stack_for_linear_scan(); | |||
1204 | } | |||
1205 | ||||
1206 | // compute use counts | |||
1207 | UseCountComputer::compute(_code); | |||
1208 | } | |||
1209 | ||||
1210 | ||||
1211 | void IR::iterate_preorder(BlockClosure* closure) { | |||
1212 | assert(is_valid(), "IR must be valid")do { if (!(is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1212, "assert(" "is_valid()" ") failed", "IR must be valid" ); ::breakpoint(); } } while (0); | |||
1213 | start()->iterate_preorder(closure); | |||
1214 | } | |||
1215 | ||||
1216 | ||||
1217 | void IR::iterate_postorder(BlockClosure* closure) { | |||
1218 | assert(is_valid(), "IR must be valid")do { if (!(is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1218, "assert(" "is_valid()" ") failed", "IR must be valid" ); ::breakpoint(); } } while (0); | |||
1219 | start()->iterate_postorder(closure); | |||
1220 | } | |||
1221 | ||||
1222 | void IR::iterate_linear_scan_order(BlockClosure* closure) { | |||
1223 | linear_scan_order()->iterate_forward(closure); | |||
1224 | } | |||
1225 | ||||
1226 | ||||
1227 | #ifndef PRODUCT | |||
1228 | class BlockPrinter: public BlockClosure { | |||
1229 | private: | |||
1230 | InstructionPrinter* _ip; | |||
1231 | bool _cfg_only; | |||
1232 | bool _live_only; | |||
1233 | ||||
1234 | public: | |||
1235 | BlockPrinter(InstructionPrinter* ip, bool cfg_only, bool live_only = false) { | |||
1236 | _ip = ip; | |||
1237 | _cfg_only = cfg_only; | |||
1238 | _live_only = live_only; | |||
1239 | } | |||
1240 | ||||
1241 | virtual void block_do(BlockBegin* block) { | |||
1242 | if (_cfg_only) { | |||
1243 | _ip->print_instr(block); tty->cr(); | |||
1244 | } else { | |||
1245 | block->print_block(*_ip, _live_only); | |||
1246 | } | |||
1247 | } | |||
1248 | }; | |||
1249 | ||||
1250 | ||||
1251 | void IR::print(BlockBegin* start, bool cfg_only, bool live_only) { | |||
1252 | ttyLocker ttyl; | |||
1253 | InstructionPrinter ip(!cfg_only); | |||
1254 | BlockPrinter bp(&ip, cfg_only, live_only); | |||
1255 | start->iterate_preorder(&bp); | |||
1256 | tty->cr(); | |||
1257 | } | |||
1258 | ||||
1259 | void IR::print(bool cfg_only, bool live_only) { | |||
1260 | if (is_valid()) { | |||
1261 | print(start(), cfg_only, live_only); | |||
1262 | } else { | |||
1263 | tty->print_cr("invalid IR"); | |||
1264 | } | |||
1265 | } | |||
1266 | ||||
1267 | class EndNotNullValidator : public BlockClosure { | |||
1268 | public: | |||
1269 | EndNotNullValidator(IR* hir) { | |||
1270 | hir->start()->iterate_postorder(this); | |||
1271 | } | |||
1272 | ||||
1273 | void block_do(BlockBegin* block) { | |||
1274 | assert(block->end() != NULL, "Expect block end to exist.")do { if (!(block->end() != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1274, "assert(" "block->end() != __null" ") failed", "Expect block end to exist." ); ::breakpoint(); } } while (0); | |||
1275 | } | |||
1276 | }; | |||
1277 | ||||
1278 | typedef GrowableArray<BlockList*> BlockListList; | |||
1279 | ||||
1280 | class PredecessorValidator : public BlockClosure { | |||
1281 | private: | |||
1282 | BlockListList* _predecessors; // Each index i will hold predecessors of block with id i | |||
1283 | BlockList* _blocks; | |||
1284 | ||||
1285 | static int cmp(BlockBegin** a, BlockBegin** b) { | |||
1286 | return (*a)->block_id() - (*b)->block_id(); | |||
1287 | } | |||
1288 | ||||
1289 | public: | |||
1290 | PredecessorValidator(IR* hir) { | |||
1291 | ResourceMark rm; | |||
1292 | _predecessors = new BlockListList(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), NULL__null); | |||
1293 | _blocks = new BlockList(BlockBegin::number_of_blocks()); | |||
1294 | ||||
1295 | hir->start()->iterate_preorder(this); | |||
1296 | if (hir->code() != NULL__null) { | |||
1297 | assert(hir->code()->length() == _blocks->length(), "must match")do { if (!(hir->code()->length() == _blocks->length( ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1297, "assert(" "hir->code()->length() == _blocks->length()" ") failed", "must match"); ::breakpoint(); } } while (0); | |||
1298 | for (int i = 0; i < _blocks->length(); i++) { | |||
1299 | assert(hir->code()->contains(_blocks->at(i)), "should be in both lists")do { if (!(hir->code()->contains(_blocks->at(i)))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1299, "assert(" "hir->code()->contains(_blocks->at(i))" ") failed", "should be in both lists"); ::breakpoint(); } } while (0); | |||
1300 | } | |||
1301 | } | |||
1302 | ||||
1303 | for (int i = 0; i < _blocks->length(); i++) { | |||
1304 | BlockBegin* block = _blocks->at(i); | |||
1305 | verify_block_preds_against_collected_preds(block); | |||
1306 | } | |||
1307 | } | |||
1308 | ||||
1309 | virtual void block_do(BlockBegin* block) { | |||
1310 | _blocks->append(block); | |||
1311 | verify_successor_xentry_flag(block); | |||
1312 | collect_predecessors(block); | |||
1313 | } | |||
1314 | ||||
1315 | private: | |||
1316 | void verify_successor_xentry_flag(const BlockBegin* block) const { | |||
1317 | for (int i = 0; i < block->end()->number_of_sux(); i++) { | |||
1318 | assert(!block->end()->sux_at(i)->is_set(BlockBegin::exception_entry_flag), "must not be xhandler")do { if (!(!block->end()->sux_at(i)->is_set(BlockBegin ::exception_entry_flag))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1318, "assert(" "!block->end()->sux_at(i)->is_set(BlockBegin::exception_entry_flag)" ") failed", "must not be xhandler"); ::breakpoint(); } } while (0); | |||
1319 | } | |||
1320 | for (int i = 0; i < block->number_of_exception_handlers(); i++) { | |||
1321 | assert(block->exception_handler_at(i)->is_set(BlockBegin::exception_entry_flag), "must be xhandler")do { if (!(block->exception_handler_at(i)->is_set(BlockBegin ::exception_entry_flag))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1321, "assert(" "block->exception_handler_at(i)->is_set(BlockBegin::exception_entry_flag)" ") failed", "must be xhandler"); ::breakpoint(); } } while ( 0); | |||
1322 | } | |||
1323 | } | |||
1324 | ||||
1325 | void collect_predecessors(BlockBegin* block) { | |||
1326 | for (int i = 0; i < block->end()->number_of_sux(); i++) { | |||
1327 | collect_predecessor(block, block->end()->sux_at(i)); | |||
1328 | } | |||
1329 | for (int i = 0; i < block->number_of_exception_handlers(); i++) { | |||
1330 | collect_predecessor(block, block->exception_handler_at(i)); | |||
1331 | } | |||
1332 | } | |||
1333 | ||||
1334 | void collect_predecessor(BlockBegin* const pred, const BlockBegin* sux) { | |||
1335 | BlockList* preds = _predecessors->at_grow(sux->block_id(), NULL__null); | |||
1336 | if (preds == NULL__null) { | |||
1337 | preds = new BlockList(); | |||
1338 | _predecessors->at_put(sux->block_id(), preds); | |||
1339 | } | |||
1340 | preds->append(pred); | |||
1341 | } | |||
1342 | ||||
1343 | void verify_block_preds_against_collected_preds(const BlockBegin* block) const { | |||
1344 | BlockList* preds = _predecessors->at(block->block_id()); | |||
1345 | if (preds == NULL__null) { | |||
1346 | assert(block->number_of_preds() == 0, "should be the same")do { if (!(block->number_of_preds() == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1346, "assert(" "block->number_of_preds() == 0" ") failed" , "should be the same"); ::breakpoint(); } } while (0); | |||
1347 | return; | |||
1348 | } | |||
1349 | assert(preds->length() == block->number_of_preds(), "should be the same")do { if (!(preds->length() == block->number_of_preds()) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1349, "assert(" "preds->length() == block->number_of_preds()" ") failed", "should be the same"); ::breakpoint(); } } while (0); | |||
1350 | ||||
1351 | // clone the pred list so we can mutate it | |||
1352 | BlockList* pred_copy = new BlockList(); | |||
1353 | for (int j = 0; j < block->number_of_preds(); j++) { | |||
1354 | pred_copy->append(block->pred_at(j)); | |||
1355 | } | |||
1356 | // sort them in the same order | |||
1357 | preds->sort(cmp); | |||
1358 | pred_copy->sort(cmp); | |||
1359 | for (int j = 0; j < block->number_of_preds(); j++) { | |||
1360 | assert(preds->at(j) == pred_copy->at(j), "must match")do { if (!(preds->at(j) == pred_copy->at(j))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1360, "assert(" "preds->at(j) == pred_copy->at(j)" ") failed" , "must match"); ::breakpoint(); } } while (0); | |||
1361 | } | |||
1362 | } | |||
1363 | }; | |||
1364 | ||||
1365 | class VerifyBlockBeginField : public BlockClosure { | |||
1366 | ||||
1367 | public: | |||
1368 | ||||
1369 | virtual void block_do(BlockBegin *block) { | |||
1370 | for ( Instruction *cur = block; cur != NULL__null; cur = cur->next()) { | |||
1371 | assert(cur->block() == block, "Block begin is not correct")do { if (!(cur->block() == block)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1371, "assert(" "cur->block() == block" ") failed", "Block begin is not correct" ); ::breakpoint(); } } while (0); | |||
1372 | } | |||
1373 | } | |||
1374 | }; | |||
1375 | ||||
1376 | void IR::verify() { | |||
1377 | #ifdef ASSERT1 | |||
1378 | PredecessorValidator pv(this); | |||
1379 | EndNotNullValidator(this); | |||
1380 | VerifyBlockBeginField verifier; | |||
1381 | this->iterate_postorder(&verifier); | |||
1382 | #endif | |||
1383 | } | |||
1384 | ||||
1385 | #endif // PRODUCT | |||
1386 | ||||
1387 | void SubstitutionResolver::visit(Value* v) { | |||
1388 | Value v0 = *v; | |||
1389 | if (v0) { | |||
1390 | Value vs = v0->subst(); | |||
1391 | if (vs != v0) { | |||
1392 | *v = v0->subst(); | |||
1393 | } | |||
1394 | } | |||
1395 | } | |||
1396 | ||||
1397 | #ifdef ASSERT1 | |||
1398 | class SubstitutionChecker: public ValueVisitor { | |||
1399 | void visit(Value* v) { | |||
1400 | Value v0 = *v; | |||
1401 | if (v0) { | |||
1402 | Value vs = v0->subst(); | |||
1403 | assert(vs == v0, "missed substitution")do { if (!(vs == v0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1403, "assert(" "vs == v0" ") failed", "missed substitution" ); ::breakpoint(); } } while (0); | |||
1404 | } | |||
1405 | } | |||
1406 | }; | |||
1407 | #endif | |||
1408 | ||||
1409 | ||||
1410 | void SubstitutionResolver::block_do(BlockBegin* block) { | |||
1411 | Instruction* last = NULL__null; | |||
1412 | for (Instruction* n = block; n != NULL__null;) { | |||
1413 | n->values_do(this); | |||
1414 | // need to remove this instruction from the instruction stream | |||
1415 | if (n->subst() != n) { | |||
1416 | guarantee(last != NULL, "must have last")do { if (!(last != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_IR.cpp" , 1416, "guarantee(" "last != NULL" ") failed", "must have last" ); ::breakpoint(); } } while (0); | |||
1417 | last->set_next(n->next()); | |||
1418 | } else { | |||
1419 | last = n; | |||
1420 | } | |||
1421 | n = last->next(); | |||
1422 | } | |||
1423 | ||||
1424 | #ifdef ASSERT1 | |||
1425 | SubstitutionChecker check_substitute; | |||
1426 | if (block->state()) block->state()->values_do(&check_substitute); | |||
1427 | block->block_values_do(&check_substitute); | |||
1428 | if (block->end() && block->end()->state()) block->end()->state()->values_do(&check_substitute); | |||
1429 | #endif | |||
1430 | } |