| File: | jdk/src/hotspot/share/c1/c1_IR.cpp | 
| Warning: | line 904, column 3 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 | } |