File: | jdk/src/hotspot/share/ci/ciTypeFlow.cpp |
Warning: | line 2356, column 11 Although the value stored to 'code' is used in the enclosing expression, the value is never actually read from 'code' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 2000, 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 "ci/ciConstant.hpp" |
27 | #include "ci/ciField.hpp" |
28 | #include "ci/ciMethod.hpp" |
29 | #include "ci/ciMethodData.hpp" |
30 | #include "ci/ciObjArrayKlass.hpp" |
31 | #include "ci/ciStreams.hpp" |
32 | #include "ci/ciTypeArrayKlass.hpp" |
33 | #include "ci/ciTypeFlow.hpp" |
34 | #include "compiler/compileLog.hpp" |
35 | #include "interpreter/bytecode.hpp" |
36 | #include "interpreter/bytecodes.hpp" |
37 | #include "memory/allocation.inline.hpp" |
38 | #include "memory/resourceArea.hpp" |
39 | #include "oops/oop.inline.hpp" |
40 | #include "opto/compile.hpp" |
41 | #include "opto/node.hpp" |
42 | #include "runtime/deoptimization.hpp" |
43 | #include "utilities/growableArray.hpp" |
44 | |
45 | // ciTypeFlow::JsrSet |
46 | // |
47 | // A JsrSet represents some set of JsrRecords. This class |
48 | // is used to record a set of all jsr routines which we permit |
49 | // execution to return (ret) from. |
50 | // |
51 | // During abstract interpretation, JsrSets are used to determine |
52 | // whether two paths which reach a given block are unique, and |
53 | // should be cloned apart, or are compatible, and should merge |
54 | // together. |
55 | |
56 | // ------------------------------------------------------------------ |
57 | // ciTypeFlow::JsrSet::JsrSet |
58 | |
59 | // Allocate growable array storage in Arena. |
60 | ciTypeFlow::JsrSet::JsrSet(Arena* arena, int default_len) : _set(arena, default_len, 0, NULL__null) { |
61 | assert(arena != NULL, "invariant")do { if (!(arena != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 61, "assert(" "arena != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
62 | } |
63 | |
64 | // Allocate growable array storage in current ResourceArea. |
65 | ciTypeFlow::JsrSet::JsrSet(int default_len) : _set(default_len, 0, NULL__null) {} |
66 | |
67 | // ------------------------------------------------------------------ |
68 | // ciTypeFlow::JsrSet::copy_into |
69 | void ciTypeFlow::JsrSet::copy_into(JsrSet* jsrs) { |
70 | int len = size(); |
71 | jsrs->_set.clear(); |
72 | for (int i = 0; i < len; i++) { |
73 | jsrs->_set.append(_set.at(i)); |
74 | } |
75 | } |
76 | |
77 | // ------------------------------------------------------------------ |
78 | // ciTypeFlow::JsrSet::is_compatible_with |
79 | // |
80 | // !!!! MISGIVINGS ABOUT THIS... disregard |
81 | // |
82 | // Is this JsrSet compatible with some other JsrSet? |
83 | // |
84 | // In set-theoretic terms, a JsrSet can be viewed as a partial function |
85 | // from entry addresses to return addresses. Two JsrSets A and B are |
86 | // compatible iff |
87 | // |
88 | // For any x, |
89 | // A(x) defined and B(x) defined implies A(x) == B(x) |
90 | // |
91 | // Less formally, two JsrSets are compatible when they have identical |
92 | // return addresses for any entry addresses they share in common. |
93 | bool ciTypeFlow::JsrSet::is_compatible_with(JsrSet* other) { |
94 | // Walk through both sets in parallel. If the same entry address |
95 | // appears in both sets, then the return address must match for |
96 | // the sets to be compatible. |
97 | int size1 = size(); |
98 | int size2 = other->size(); |
99 | |
100 | // Special case. If nothing is on the jsr stack, then there can |
101 | // be no ret. |
102 | if (size2 == 0) { |
103 | return true; |
104 | } else if (size1 != size2) { |
105 | return false; |
106 | } else { |
107 | for (int i = 0; i < size1; i++) { |
108 | JsrRecord* record1 = record_at(i); |
109 | JsrRecord* record2 = other->record_at(i); |
110 | if (record1->entry_address() != record2->entry_address() || |
111 | record1->return_address() != record2->return_address()) { |
112 | return false; |
113 | } |
114 | } |
115 | return true; |
116 | } |
117 | |
118 | #if 0 |
119 | int pos1 = 0; |
120 | int pos2 = 0; |
121 | int size1 = size(); |
122 | int size2 = other->size(); |
123 | while (pos1 < size1 && pos2 < size2) { |
124 | JsrRecord* record1 = record_at(pos1); |
125 | JsrRecord* record2 = other->record_at(pos2); |
126 | int entry1 = record1->entry_address(); |
127 | int entry2 = record2->entry_address(); |
128 | if (entry1 < entry2) { |
129 | pos1++; |
130 | } else if (entry1 > entry2) { |
131 | pos2++; |
132 | } else { |
133 | if (record1->return_address() == record2->return_address()) { |
134 | pos1++; |
135 | pos2++; |
136 | } else { |
137 | // These two JsrSets are incompatible. |
138 | return false; |
139 | } |
140 | } |
141 | } |
142 | // The two JsrSets agree. |
143 | return true; |
144 | #endif |
145 | } |
146 | |
147 | // ------------------------------------------------------------------ |
148 | // ciTypeFlow::JsrSet::insert_jsr_record |
149 | // |
150 | // Insert the given JsrRecord into the JsrSet, maintaining the order |
151 | // of the set and replacing any element with the same entry address. |
152 | void ciTypeFlow::JsrSet::insert_jsr_record(JsrRecord* record) { |
153 | int len = size(); |
154 | int entry = record->entry_address(); |
155 | int pos = 0; |
156 | for ( ; pos < len; pos++) { |
157 | JsrRecord* current = record_at(pos); |
158 | if (entry == current->entry_address()) { |
159 | // Stomp over this entry. |
160 | _set.at_put(pos, record); |
161 | assert(size() == len, "must be same size")do { if (!(size() == len)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 161, "assert(" "size() == len" ") failed", "must be same size" ); ::breakpoint(); } } while (0); |
162 | return; |
163 | } else if (entry < current->entry_address()) { |
164 | break; |
165 | } |
166 | } |
167 | |
168 | // Insert the record into the list. |
169 | JsrRecord* swap = record; |
170 | JsrRecord* temp = NULL__null; |
171 | for ( ; pos < len; pos++) { |
172 | temp = _set.at(pos); |
173 | _set.at_put(pos, swap); |
174 | swap = temp; |
175 | } |
176 | _set.append(swap); |
177 | assert(size() == len+1, "must be larger")do { if (!(size() == len+1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 177, "assert(" "size() == len+1" ") failed", "must be larger" ); ::breakpoint(); } } while (0); |
178 | } |
179 | |
180 | // ------------------------------------------------------------------ |
181 | // ciTypeFlow::JsrSet::remove_jsr_record |
182 | // |
183 | // Remove the JsrRecord with the given return address from the JsrSet. |
184 | void ciTypeFlow::JsrSet::remove_jsr_record(int return_address) { |
185 | int len = size(); |
186 | for (int i = 0; i < len; i++) { |
187 | if (record_at(i)->return_address() == return_address) { |
188 | // We have found the proper entry. Remove it from the |
189 | // JsrSet and exit. |
190 | for (int j = i + 1; j < len ; j++) { |
191 | _set.at_put(j - 1, _set.at(j)); |
192 | } |
193 | _set.trunc_to(len - 1); |
194 | assert(size() == len-1, "must be smaller")do { if (!(size() == len-1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 194, "assert(" "size() == len-1" ") failed", "must be smaller" ); ::breakpoint(); } } while (0); |
195 | return; |
196 | } |
197 | } |
198 | assert(false, "verify: returning from invalid subroutine")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 198, "assert(" "false" ") failed", "verify: returning from invalid subroutine" ); ::breakpoint(); } } while (0); |
199 | } |
200 | |
201 | // ------------------------------------------------------------------ |
202 | // ciTypeFlow::JsrSet::apply_control |
203 | // |
204 | // Apply the effect of a control-flow bytecode on the JsrSet. The |
205 | // only bytecodes that modify the JsrSet are jsr and ret. |
206 | void ciTypeFlow::JsrSet::apply_control(ciTypeFlow* analyzer, |
207 | ciBytecodeStream* str, |
208 | ciTypeFlow::StateVector* state) { |
209 | Bytecodes::Code code = str->cur_bc(); |
210 | if (code == Bytecodes::_jsr) { |
211 | JsrRecord* record = |
212 | analyzer->make_jsr_record(str->get_dest(), str->next_bci()); |
213 | insert_jsr_record(record); |
214 | } else if (code == Bytecodes::_jsr_w) { |
215 | JsrRecord* record = |
216 | analyzer->make_jsr_record(str->get_far_dest(), str->next_bci()); |
217 | insert_jsr_record(record); |
218 | } else if (code == Bytecodes::_ret) { |
219 | Cell local = state->local(str->get_index()); |
220 | ciType* return_address = state->type_at(local); |
221 | assert(return_address->is_return_address(), "verify: wrong type")do { if (!(return_address->is_return_address())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 221, "assert(" "return_address->is_return_address()" ") failed" , "verify: wrong type"); ::breakpoint(); } } while (0); |
222 | if (size() == 0) { |
223 | // Ret-state underflow: Hit a ret w/o any previous jsrs. Bail out. |
224 | // This can happen when a loop is inside a finally clause (4614060). |
225 | analyzer->record_failure("OSR in finally clause"); |
226 | return; |
227 | } |
228 | remove_jsr_record(return_address->as_return_address()->bci()); |
229 | } |
230 | } |
231 | |
232 | #ifndef PRODUCT |
233 | // ------------------------------------------------------------------ |
234 | // ciTypeFlow::JsrSet::print_on |
235 | void ciTypeFlow::JsrSet::print_on(outputStream* st) const { |
236 | st->print("{ "); |
237 | int num_elements = size(); |
238 | if (num_elements > 0) { |
239 | int i = 0; |
240 | for( ; i < num_elements - 1; i++) { |
241 | _set.at(i)->print_on(st); |
242 | st->print(", "); |
243 | } |
244 | _set.at(i)->print_on(st); |
245 | st->print(" "); |
246 | } |
247 | st->print("}"); |
248 | } |
249 | #endif |
250 | |
251 | // ciTypeFlow::StateVector |
252 | // |
253 | // A StateVector summarizes the type information at some point in |
254 | // the program. |
255 | |
256 | // ------------------------------------------------------------------ |
257 | // ciTypeFlow::StateVector::type_meet |
258 | // |
259 | // Meet two types. |
260 | // |
261 | // The semi-lattice of types use by this analysis are modeled on those |
262 | // of the verifier. The lattice is as follows: |
263 | // |
264 | // top_type() >= all non-extremal types >= bottom_type |
265 | // and |
266 | // Every primitive type is comparable only with itself. The meet of |
267 | // reference types is determined by their kind: instance class, |
268 | // interface, or array class. The meet of two types of the same |
269 | // kind is their least common ancestor. The meet of two types of |
270 | // different kinds is always java.lang.Object. |
271 | ciType* ciTypeFlow::StateVector::type_meet_internal(ciType* t1, ciType* t2, ciTypeFlow* analyzer) { |
272 | assert(t1 != t2, "checked in caller")do { if (!(t1 != t2)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 272, "assert(" "t1 != t2" ") failed", "checked in caller"); ::breakpoint(); } } while (0); |
273 | if (t1->equals(top_type())) { |
274 | return t2; |
275 | } else if (t2->equals(top_type())) { |
276 | return t1; |
277 | } else if (t1->is_primitive_type() || t2->is_primitive_type()) { |
278 | // Special case null_type. null_type meet any reference type T |
279 | // is T. null_type meet null_type is null_type. |
280 | if (t1->equals(null_type())) { |
281 | if (!t2->is_primitive_type() || t2->equals(null_type())) { |
282 | return t2; |
283 | } |
284 | } else if (t2->equals(null_type())) { |
285 | if (!t1->is_primitive_type()) { |
286 | return t1; |
287 | } |
288 | } |
289 | |
290 | // At least one of the two types is a non-top primitive type. |
291 | // The other type is not equal to it. Fall to bottom. |
292 | return bottom_type(); |
293 | } else { |
294 | // Both types are non-top non-primitive types. That is, |
295 | // both types are either instanceKlasses or arrayKlasses. |
296 | ciKlass* object_klass = analyzer->env()->Object_klass(); |
297 | ciKlass* k1 = t1->as_klass(); |
298 | ciKlass* k2 = t2->as_klass(); |
299 | if (k1->equals(object_klass) || k2->equals(object_klass)) { |
300 | return object_klass; |
301 | } else if (!k1->is_loaded() || !k2->is_loaded()) { |
302 | // Unloaded classes fall to java.lang.Object at a merge. |
303 | return object_klass; |
304 | } else if (k1->is_interface() != k2->is_interface()) { |
305 | // When an interface meets a non-interface, we get Object; |
306 | // This is what the verifier does. |
307 | return object_klass; |
308 | } else if (k1->is_array_klass() || k2->is_array_klass()) { |
309 | // When an array meets a non-array, we get Object. |
310 | // When objArray meets typeArray, we also get Object. |
311 | // And when typeArray meets different typeArray, we again get Object. |
312 | // But when objArray meets objArray, we look carefully at element types. |
313 | if (k1->is_obj_array_klass() && k2->is_obj_array_klass()) { |
314 | // Meet the element types, then construct the corresponding array type. |
315 | ciKlass* elem1 = k1->as_obj_array_klass()->element_klass(); |
316 | ciKlass* elem2 = k2->as_obj_array_klass()->element_klass(); |
317 | ciKlass* elem = type_meet_internal(elem1, elem2, analyzer)->as_klass(); |
318 | // Do an easy shortcut if one type is a super of the other. |
319 | if (elem == elem1) { |
320 | assert(k1 == ciObjArrayKlass::make(elem), "shortcut is OK")do { if (!(k1 == ciObjArrayKlass::make(elem))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 320, "assert(" "k1 == ciObjArrayKlass::make(elem)" ") failed" , "shortcut is OK"); ::breakpoint(); } } while (0); |
321 | return k1; |
322 | } else if (elem == elem2) { |
323 | assert(k2 == ciObjArrayKlass::make(elem), "shortcut is OK")do { if (!(k2 == ciObjArrayKlass::make(elem))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 323, "assert(" "k2 == ciObjArrayKlass::make(elem)" ") failed" , "shortcut is OK"); ::breakpoint(); } } while (0); |
324 | return k2; |
325 | } else { |
326 | return ciObjArrayKlass::make(elem); |
327 | } |
328 | } else { |
329 | return object_klass; |
330 | } |
331 | } else { |
332 | // Must be two plain old instance klasses. |
333 | assert(k1->is_instance_klass(), "previous cases handle non-instances")do { if (!(k1->is_instance_klass())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 333, "assert(" "k1->is_instance_klass()" ") failed", "previous cases handle non-instances" ); ::breakpoint(); } } while (0); |
334 | assert(k2->is_instance_klass(), "previous cases handle non-instances")do { if (!(k2->is_instance_klass())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 334, "assert(" "k2->is_instance_klass()" ") failed", "previous cases handle non-instances" ); ::breakpoint(); } } while (0); |
335 | return k1->least_common_ancestor(k2); |
336 | } |
337 | } |
338 | } |
339 | |
340 | |
341 | // ------------------------------------------------------------------ |
342 | // ciTypeFlow::StateVector::StateVector |
343 | // |
344 | // Build a new state vector |
345 | ciTypeFlow::StateVector::StateVector(ciTypeFlow* analyzer) { |
346 | _outer = analyzer; |
347 | _stack_size = -1; |
348 | _monitor_count = -1; |
349 | // Allocate the _types array |
350 | int max_cells = analyzer->max_cells(); |
351 | _types = (ciType**)analyzer->arena()->Amalloc(sizeof(ciType*) * max_cells); |
352 | for (int i=0; i<max_cells; i++) { |
353 | _types[i] = top_type(); |
354 | } |
355 | _trap_bci = -1; |
356 | _trap_index = 0; |
357 | _def_locals.clear(); |
358 | } |
359 | |
360 | |
361 | // ------------------------------------------------------------------ |
362 | // ciTypeFlow::get_start_state |
363 | // |
364 | // Set this vector to the method entry state. |
365 | const ciTypeFlow::StateVector* ciTypeFlow::get_start_state() { |
366 | StateVector* state = new StateVector(this); |
367 | if (is_osr_flow()) { |
368 | ciTypeFlow* non_osr_flow = method()->get_flow_analysis(); |
369 | if (non_osr_flow->failing()) { |
370 | record_failure(non_osr_flow->failure_reason()); |
371 | return NULL__null; |
372 | } |
373 | JsrSet* jsrs = new JsrSet(4); |
374 | Block* non_osr_block = non_osr_flow->existing_block_at(start_bci(), jsrs); |
375 | if (non_osr_block == NULL__null) { |
376 | record_failure("cannot reach OSR point"); |
377 | return NULL__null; |
378 | } |
379 | // load up the non-OSR state at this point |
380 | non_osr_block->copy_state_into(state); |
381 | int non_osr_start = non_osr_block->start(); |
382 | if (non_osr_start != start_bci()) { |
383 | // must flow forward from it |
384 | if (CITraceTypeFlow) { |
385 | tty->print_cr(">> Interpreting pre-OSR block %d:", non_osr_start); |
386 | } |
387 | Block* block = block_at(non_osr_start, jsrs); |
388 | assert(block->limit() == start_bci(), "must flow forward to start")do { if (!(block->limit() == start_bci())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 388, "assert(" "block->limit() == start_bci()" ") failed" , "must flow forward to start"); ::breakpoint(); } } while (0 ); |
389 | flow_block(block, state, jsrs); |
390 | } |
391 | return state; |
392 | // Note: The code below would be an incorrect for an OSR flow, |
393 | // even if it were possible for an OSR entry point to be at bci zero. |
394 | } |
395 | // "Push" the method signature into the first few locals. |
396 | state->set_stack_size(-max_locals()); |
397 | if (!method()->is_static()) { |
398 | state->push(method()->holder()); |
399 | assert(state->tos() == state->local(0), "")do { if (!(state->tos() == state->local(0))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 399, "assert(" "state->tos() == state->local(0)" ") failed" , ""); ::breakpoint(); } } while (0); |
400 | } |
401 | for (ciSignatureStream str(method()->signature()); |
402 | !str.at_return_type(); |
403 | str.next()) { |
404 | state->push_translate(str.type()); |
405 | } |
406 | // Set the rest of the locals to bottom. |
407 | Cell cell = state->next_cell(state->tos()); |
408 | state->set_stack_size(0); |
409 | int limit = state->limit_cell(); |
410 | for (; cell < limit; cell = state->next_cell(cell)) { |
411 | state->set_type_at(cell, state->bottom_type()); |
412 | } |
413 | // Lock an object, if necessary. |
414 | state->set_monitor_count(method()->is_synchronized() ? 1 : 0); |
415 | return state; |
416 | } |
417 | |
418 | // ------------------------------------------------------------------ |
419 | // ciTypeFlow::StateVector::copy_into |
420 | // |
421 | // Copy our value into some other StateVector |
422 | void ciTypeFlow::StateVector::copy_into(ciTypeFlow::StateVector* copy) |
423 | const { |
424 | copy->set_stack_size(stack_size()); |
425 | copy->set_monitor_count(monitor_count()); |
426 | Cell limit = limit_cell(); |
427 | for (Cell c = start_cell(); c < limit; c = next_cell(c)) { |
428 | copy->set_type_at(c, type_at(c)); |
429 | } |
430 | } |
431 | |
432 | // ------------------------------------------------------------------ |
433 | // ciTypeFlow::StateVector::meet |
434 | // |
435 | // Meets this StateVector with another, destructively modifying this |
436 | // one. Returns true if any modification takes place. |
437 | bool ciTypeFlow::StateVector::meet(const ciTypeFlow::StateVector* incoming) { |
438 | if (monitor_count() == -1) { |
439 | set_monitor_count(incoming->monitor_count()); |
440 | } |
441 | assert(monitor_count() == incoming->monitor_count(), "monitors must match")do { if (!(monitor_count() == incoming->monitor_count())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 441, "assert(" "monitor_count() == incoming->monitor_count()" ") failed", "monitors must match"); ::breakpoint(); } } while (0); |
442 | |
443 | if (stack_size() == -1) { |
444 | set_stack_size(incoming->stack_size()); |
445 | Cell limit = limit_cell(); |
446 | #ifdef ASSERT1 |
447 | { for (Cell c = start_cell(); c < limit; c = next_cell(c)) { |
448 | assert(type_at(c) == top_type(), "")do { if (!(type_at(c) == top_type())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 448, "assert(" "type_at(c) == top_type()" ") failed", ""); :: breakpoint(); } } while (0); |
449 | } } |
450 | #endif |
451 | // Make a simple copy of the incoming state. |
452 | for (Cell c = start_cell(); c < limit; c = next_cell(c)) { |
453 | set_type_at(c, incoming->type_at(c)); |
454 | } |
455 | return true; // it is always different the first time |
456 | } |
457 | #ifdef ASSERT1 |
458 | if (stack_size() != incoming->stack_size()) { |
459 | _outer->method()->print_codes(); |
460 | tty->print_cr("!!!! Stack size conflict"); |
461 | tty->print_cr("Current state:"); |
462 | print_on(tty); |
463 | tty->print_cr("Incoming state:"); |
464 | ((StateVector*)incoming)->print_on(tty); |
465 | } |
466 | #endif |
467 | assert(stack_size() == incoming->stack_size(), "sanity")do { if (!(stack_size() == incoming->stack_size())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 467, "assert(" "stack_size() == incoming->stack_size()" ") failed" , "sanity"); ::breakpoint(); } } while (0); |
468 | |
469 | bool different = false; |
470 | Cell limit = limit_cell(); |
471 | for (Cell c = start_cell(); c < limit; c = next_cell(c)) { |
472 | ciType* t1 = type_at(c); |
473 | ciType* t2 = incoming->type_at(c); |
474 | if (!t1->equals(t2)) { |
475 | ciType* new_type = type_meet(t1, t2); |
476 | if (!t1->equals(new_type)) { |
477 | set_type_at(c, new_type); |
478 | different = true; |
479 | } |
480 | } |
481 | } |
482 | return different; |
483 | } |
484 | |
485 | // ------------------------------------------------------------------ |
486 | // ciTypeFlow::StateVector::meet_exception |
487 | // |
488 | // Meets this StateVector with another, destructively modifying this |
489 | // one. The incoming state is coming via an exception. Returns true |
490 | // if any modification takes place. |
491 | bool ciTypeFlow::StateVector::meet_exception(ciInstanceKlass* exc, |
492 | const ciTypeFlow::StateVector* incoming) { |
493 | if (monitor_count() == -1) { |
494 | set_monitor_count(incoming->monitor_count()); |
495 | } |
496 | assert(monitor_count() == incoming->monitor_count(), "monitors must match")do { if (!(monitor_count() == incoming->monitor_count())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 496, "assert(" "monitor_count() == incoming->monitor_count()" ") failed", "monitors must match"); ::breakpoint(); } } while (0); |
497 | |
498 | if (stack_size() == -1) { |
499 | set_stack_size(1); |
500 | } |
501 | |
502 | assert(stack_size() == 1, "must have one-element stack")do { if (!(stack_size() == 1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 502, "assert(" "stack_size() == 1" ") failed", "must have one-element stack" ); ::breakpoint(); } } while (0); |
503 | |
504 | bool different = false; |
505 | |
506 | // Meet locals from incoming array. |
507 | Cell limit = local(_outer->max_locals()-1); |
508 | for (Cell c = start_cell(); c <= limit; c = next_cell(c)) { |
509 | ciType* t1 = type_at(c); |
510 | ciType* t2 = incoming->type_at(c); |
511 | if (!t1->equals(t2)) { |
512 | ciType* new_type = type_meet(t1, t2); |
513 | if (!t1->equals(new_type)) { |
514 | set_type_at(c, new_type); |
515 | different = true; |
516 | } |
517 | } |
518 | } |
519 | |
520 | // Handle stack separately. When an exception occurs, the |
521 | // only stack entry is the exception instance. |
522 | ciType* tos_type = type_at_tos(); |
523 | if (!tos_type->equals(exc)) { |
524 | ciType* new_type = type_meet(tos_type, exc); |
525 | if (!tos_type->equals(new_type)) { |
526 | set_type_at_tos(new_type); |
527 | different = true; |
528 | } |
529 | } |
530 | |
531 | return different; |
532 | } |
533 | |
534 | // ------------------------------------------------------------------ |
535 | // ciTypeFlow::StateVector::push_translate |
536 | void ciTypeFlow::StateVector::push_translate(ciType* type) { |
537 | BasicType basic_type = type->basic_type(); |
538 | if (basic_type == T_BOOLEAN || basic_type == T_CHAR || |
539 | basic_type == T_BYTE || basic_type == T_SHORT) { |
540 | push_int(); |
541 | } else { |
542 | push(type); |
543 | if (type->is_two_word()) { |
544 | push(half_type(type)); |
545 | } |
546 | } |
547 | } |
548 | |
549 | // ------------------------------------------------------------------ |
550 | // ciTypeFlow::StateVector::do_aaload |
551 | void ciTypeFlow::StateVector::do_aaload(ciBytecodeStream* str) { |
552 | pop_int(); |
553 | ciObjArrayKlass* array_klass = pop_objArray(); |
554 | if (array_klass == NULL__null) { |
555 | // Did aaload on a null reference; push a null and ignore the exception. |
556 | // This instruction will never continue normally. All we have to do |
557 | // is report a value that will meet correctly with any downstream |
558 | // reference types on paths that will truly be executed. This null type |
559 | // meets with any reference type to yield that same reference type. |
560 | // (The compiler will generate an unconditional exception here.) |
561 | push(null_type()); |
562 | return; |
563 | } |
564 | if (!array_klass->is_loaded()) { |
565 | // Only fails for some -Xcomp runs |
566 | trap(str, array_klass, |
567 | Deoptimization::make_trap_request |
568 | (Deoptimization::Reason_unloaded, |
569 | Deoptimization::Action_reinterpret)); |
570 | return; |
571 | } |
572 | ciKlass* element_klass = array_klass->element_klass(); |
573 | if (!element_klass->is_loaded() && element_klass->is_instance_klass()) { |
574 | Untested("unloaded array element class in ciTypeFlow")do { report_untested("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 574, "unloaded array element class in ciTypeFlow"); ::breakpoint (); } while (0);; |
575 | trap(str, element_klass, |
576 | Deoptimization::make_trap_request |
577 | (Deoptimization::Reason_unloaded, |
578 | Deoptimization::Action_reinterpret)); |
579 | } else { |
580 | push_object(element_klass); |
581 | } |
582 | } |
583 | |
584 | |
585 | // ------------------------------------------------------------------ |
586 | // ciTypeFlow::StateVector::do_checkcast |
587 | void ciTypeFlow::StateVector::do_checkcast(ciBytecodeStream* str) { |
588 | bool will_link; |
589 | ciKlass* klass = str->get_klass(will_link); |
590 | if (!will_link) { |
591 | // VM's interpreter will not load 'klass' if object is NULL. |
592 | // Type flow after this block may still be needed in two situations: |
593 | // 1) C2 uses do_null_assert() and continues compilation for later blocks |
594 | // 2) C2 does an OSR compile in a later block (see bug 4778368). |
595 | pop_object(); |
596 | do_null_assert(klass); |
597 | } else { |
598 | pop_object(); |
599 | push_object(klass); |
600 | } |
601 | } |
602 | |
603 | // ------------------------------------------------------------------ |
604 | // ciTypeFlow::StateVector::do_getfield |
605 | void ciTypeFlow::StateVector::do_getfield(ciBytecodeStream* str) { |
606 | // could add assert here for type of object. |
607 | pop_object(); |
608 | do_getstatic(str); |
609 | } |
610 | |
611 | // ------------------------------------------------------------------ |
612 | // ciTypeFlow::StateVector::do_getstatic |
613 | void ciTypeFlow::StateVector::do_getstatic(ciBytecodeStream* str) { |
614 | bool will_link; |
615 | ciField* field = str->get_field(will_link); |
616 | if (!will_link) { |
617 | trap(str, field->holder(), str->get_field_holder_index()); |
618 | } else { |
619 | ciType* field_type = field->type(); |
620 | if (!field_type->is_loaded()) { |
621 | // Normally, we need the field's type to be loaded if we are to |
622 | // do anything interesting with its value. |
623 | // We used to do this: trap(str, str->get_field_signature_index()); |
624 | // |
625 | // There is one good reason not to trap here. Execution can |
626 | // get past this "getfield" or "getstatic" if the value of |
627 | // the field is null. As long as the value is null, the class |
628 | // does not need to be loaded! The compiler must assume that |
629 | // the value of the unloaded class reference is null; if the code |
630 | // ever sees a non-null value, loading has occurred. |
631 | // |
632 | // This actually happens often enough to be annoying. If the |
633 | // compiler throws an uncommon trap at this bytecode, you can |
634 | // get an endless loop of recompilations, when all the code |
635 | // needs to do is load a series of null values. Also, a trap |
636 | // here can make an OSR entry point unreachable, triggering the |
637 | // assert on non_osr_block in ciTypeFlow::get_start_state. |
638 | // (See bug 4379915.) |
639 | do_null_assert(field_type->as_klass()); |
640 | } else { |
641 | push_translate(field_type); |
642 | } |
643 | } |
644 | } |
645 | |
646 | // ------------------------------------------------------------------ |
647 | // ciTypeFlow::StateVector::do_invoke |
648 | void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str, |
649 | bool has_receiver) { |
650 | bool will_link; |
651 | ciSignature* declared_signature = NULL__null; |
652 | ciMethod* callee = str->get_method(will_link, &declared_signature); |
653 | assert(declared_signature != NULL, "cannot be null")do { if (!(declared_signature != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 653, "assert(" "declared_signature != __null" ") failed", "cannot be null" ); ::breakpoint(); } } while (0); |
654 | if (!will_link) { |
655 | // We weren't able to find the method. |
656 | if (str->cur_bc() == Bytecodes::_invokedynamic) { |
657 | trap(str, NULL__null, |
658 | Deoptimization::make_trap_request |
659 | (Deoptimization::Reason_uninitialized, |
660 | Deoptimization::Action_reinterpret)); |
661 | } else { |
662 | ciKlass* unloaded_holder = callee->holder(); |
663 | trap(str, unloaded_holder, str->get_method_holder_index()); |
664 | } |
665 | } else { |
666 | // We are using the declared signature here because it might be |
667 | // different from the callee signature (Cf. invokedynamic and |
668 | // invokehandle). |
669 | ciSignatureStream sigstr(declared_signature); |
670 | const int arg_size = declared_signature->size(); |
671 | const int stack_base = stack_size() - arg_size; |
672 | int i = 0; |
673 | for( ; !sigstr.at_return_type(); sigstr.next()) { |
674 | ciType* type = sigstr.type(); |
675 | ciType* stack_type = type_at(stack(stack_base + i++)); |
676 | // Do I want to check this type? |
677 | // assert(stack_type->is_subtype_of(type), "bad type for field value"); |
678 | if (type->is_two_word()) { |
679 | ciType* stack_type2 = type_at(stack(stack_base + i++)); |
680 | assert(stack_type2->equals(half_type(type)), "must be 2nd half")do { if (!(stack_type2->equals(half_type(type)))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 680, "assert(" "stack_type2->equals(half_type(type))" ") failed" , "must be 2nd half"); ::breakpoint(); } } while (0); |
681 | } |
682 | } |
683 | assert(arg_size == i, "must match")do { if (!(arg_size == i)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 683, "assert(" "arg_size == i" ") failed", "must match"); :: breakpoint(); } } while (0); |
684 | for (int j = 0; j < arg_size; j++) { |
685 | pop(); |
686 | } |
687 | if (has_receiver) { |
688 | // Check this? |
689 | pop_object(); |
690 | } |
691 | assert(!sigstr.is_done(), "must have return type")do { if (!(!sigstr.is_done())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 691, "assert(" "!sigstr.is_done()" ") failed", "must have return type" ); ::breakpoint(); } } while (0); |
692 | ciType* return_type = sigstr.type(); |
693 | if (!return_type->is_void()) { |
694 | if (!return_type->is_loaded()) { |
695 | // As in do_getstatic(), generally speaking, we need the return type to |
696 | // be loaded if we are to do anything interesting with its value. |
697 | // We used to do this: trap(str, str->get_method_signature_index()); |
698 | // |
699 | // We do not trap here since execution can get past this invoke if |
700 | // the return value is null. As long as the value is null, the class |
701 | // does not need to be loaded! The compiler must assume that |
702 | // the value of the unloaded class reference is null; if the code |
703 | // ever sees a non-null value, loading has occurred. |
704 | // |
705 | // See do_getstatic() for similar explanation, as well as bug 4684993. |
706 | do_null_assert(return_type->as_klass()); |
707 | } else { |
708 | push_translate(return_type); |
709 | } |
710 | } |
711 | } |
712 | } |
713 | |
714 | // ------------------------------------------------------------------ |
715 | // ciTypeFlow::StateVector::do_jsr |
716 | void ciTypeFlow::StateVector::do_jsr(ciBytecodeStream* str) { |
717 | push(ciReturnAddress::make(str->next_bci())); |
718 | } |
719 | |
720 | // ------------------------------------------------------------------ |
721 | // ciTypeFlow::StateVector::do_ldc |
722 | void ciTypeFlow::StateVector::do_ldc(ciBytecodeStream* str) { |
723 | ciConstant con = str->get_constant(); |
724 | if (con.is_valid()) { |
725 | BasicType basic_type = con.basic_type(); |
726 | if (is_reference_type(basic_type)) { |
727 | ciObject* obj = con.as_object(); |
728 | if (obj->is_null_object()) { |
729 | push_null(); |
730 | } else { |
731 | assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass")do { if (!(obj->is_instance() || obj->is_array())) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 731, "assert(" "obj->is_instance() || obj->is_array()" ") failed", "must be java_mirror of klass"); ::breakpoint(); } } while (0); |
732 | push_object(obj->klass()); |
733 | } |
734 | } else { |
735 | push_translate(ciType::make(basic_type)); |
736 | } |
737 | } else { |
738 | if (str->is_unresolved_klass_in_error()) { |
739 | trap(str, NULL__null, Deoptimization::make_trap_request(Deoptimization::Reason_unhandled, |
740 | Deoptimization::Action_none)); |
741 | } else { |
742 | // OutOfMemoryError in the CI while loading constant |
743 | push_null(); |
744 | outer()->record_failure("ldc did not link"); |
745 | } |
746 | } |
747 | } |
748 | |
749 | // ------------------------------------------------------------------ |
750 | // ciTypeFlow::StateVector::do_multianewarray |
751 | void ciTypeFlow::StateVector::do_multianewarray(ciBytecodeStream* str) { |
752 | int dimensions = str->get_dimensions(); |
753 | bool will_link; |
754 | ciArrayKlass* array_klass = str->get_klass(will_link)->as_array_klass(); |
755 | if (!will_link) { |
756 | trap(str, array_klass, str->get_klass_index()); |
757 | } else { |
758 | for (int i = 0; i < dimensions; i++) { |
759 | pop_int(); |
760 | } |
761 | push_object(array_klass); |
762 | } |
763 | } |
764 | |
765 | // ------------------------------------------------------------------ |
766 | // ciTypeFlow::StateVector::do_new |
767 | void ciTypeFlow::StateVector::do_new(ciBytecodeStream* str) { |
768 | bool will_link; |
769 | ciKlass* klass = str->get_klass(will_link); |
770 | if (!will_link || str->is_unresolved_klass()) { |
771 | trap(str, klass, str->get_klass_index()); |
772 | } else { |
773 | push_object(klass); |
774 | } |
775 | } |
776 | |
777 | // ------------------------------------------------------------------ |
778 | // ciTypeFlow::StateVector::do_newarray |
779 | void ciTypeFlow::StateVector::do_newarray(ciBytecodeStream* str) { |
780 | pop_int(); |
781 | ciKlass* klass = ciTypeArrayKlass::make((BasicType)str->get_index()); |
782 | push_object(klass); |
783 | } |
784 | |
785 | // ------------------------------------------------------------------ |
786 | // ciTypeFlow::StateVector::do_putfield |
787 | void ciTypeFlow::StateVector::do_putfield(ciBytecodeStream* str) { |
788 | do_putstatic(str); |
789 | if (_trap_bci != -1) return; // unloaded field holder, etc. |
790 | // could add assert here for type of object. |
791 | pop_object(); |
792 | } |
793 | |
794 | // ------------------------------------------------------------------ |
795 | // ciTypeFlow::StateVector::do_putstatic |
796 | void ciTypeFlow::StateVector::do_putstatic(ciBytecodeStream* str) { |
797 | bool will_link; |
798 | ciField* field = str->get_field(will_link); |
799 | if (!will_link) { |
800 | trap(str, field->holder(), str->get_field_holder_index()); |
801 | } else { |
802 | ciType* field_type = field->type(); |
803 | ciType* type = pop_value(); |
804 | // Do I want to check this type? |
805 | // assert(type->is_subtype_of(field_type), "bad type for field value"); |
806 | if (field_type->is_two_word()) { |
807 | ciType* type2 = pop_value(); |
808 | assert(type2->is_two_word(), "must be 2nd half")do { if (!(type2->is_two_word())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 808, "assert(" "type2->is_two_word()" ") failed", "must be 2nd half" ); ::breakpoint(); } } while (0); |
809 | assert(type == half_type(type2), "must be 2nd half")do { if (!(type == half_type(type2))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 809, "assert(" "type == half_type(type2)" ") failed", "must be 2nd half" ); ::breakpoint(); } } while (0); |
810 | } |
811 | } |
812 | } |
813 | |
814 | // ------------------------------------------------------------------ |
815 | // ciTypeFlow::StateVector::do_ret |
816 | void ciTypeFlow::StateVector::do_ret(ciBytecodeStream* str) { |
817 | Cell index = local(str->get_index()); |
818 | |
819 | ciType* address = type_at(index); |
820 | assert(address->is_return_address(), "bad return address")do { if (!(address->is_return_address())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 820, "assert(" "address->is_return_address()" ") failed" , "bad return address"); ::breakpoint(); } } while (0); |
821 | set_type_at(index, bottom_type()); |
822 | } |
823 | |
824 | // ------------------------------------------------------------------ |
825 | // ciTypeFlow::StateVector::trap |
826 | // |
827 | // Stop interpretation of this path with a trap. |
828 | void ciTypeFlow::StateVector::trap(ciBytecodeStream* str, ciKlass* klass, int index) { |
829 | _trap_bci = str->cur_bci(); |
830 | _trap_index = index; |
831 | |
832 | // Log information about this trap: |
833 | CompileLog* log = outer()->env()->log(); |
834 | if (log != NULL__null) { |
835 | int mid = log->identify(outer()->method()); |
836 | int kid = (klass == NULL__null)? -1: log->identify(klass); |
837 | log->begin_elem("uncommon_trap method='%d' bci='%d'", mid, str->cur_bci()); |
838 | char buf[100]; |
839 | log->print(" %s", Deoptimization::format_trap_request(buf, sizeof(buf), |
840 | index)); |
841 | if (kid >= 0) |
842 | log->print(" klass='%d'", kid); |
843 | log->end_elem(); |
844 | } |
845 | } |
846 | |
847 | // ------------------------------------------------------------------ |
848 | // ciTypeFlow::StateVector::do_null_assert |
849 | // Corresponds to graphKit::do_null_assert. |
850 | void ciTypeFlow::StateVector::do_null_assert(ciKlass* unloaded_klass) { |
851 | if (unloaded_klass->is_loaded()) { |
852 | // We failed to link, but we can still compute with this class, |
853 | // since it is loaded somewhere. The compiler will uncommon_trap |
854 | // if the object is not null, but the typeflow pass can not assume |
855 | // that the object will be null, otherwise it may incorrectly tell |
856 | // the parser that an object is known to be null. 4761344, 4807707 |
857 | push_object(unloaded_klass); |
858 | } else { |
859 | // The class is not loaded anywhere. It is safe to model the |
860 | // null in the typestates, because we can compile in a null check |
861 | // which will deoptimize us if someone manages to load the |
862 | // class later. |
863 | push_null(); |
864 | } |
865 | } |
866 | |
867 | |
868 | // ------------------------------------------------------------------ |
869 | // ciTypeFlow::StateVector::apply_one_bytecode |
870 | // |
871 | // Apply the effect of one bytecode to this StateVector |
872 | bool ciTypeFlow::StateVector::apply_one_bytecode(ciBytecodeStream* str) { |
873 | _trap_bci = -1; |
874 | _trap_index = 0; |
875 | |
876 | if (CITraceTypeFlow) { |
877 | tty->print_cr(">> Interpreting bytecode %d:%s", str->cur_bci(), |
878 | Bytecodes::name(str->cur_bc())); |
879 | } |
880 | |
881 | switch(str->cur_bc()) { |
882 | case Bytecodes::_aaload: do_aaload(str); break; |
883 | |
884 | case Bytecodes::_aastore: |
885 | { |
886 | pop_object(); |
887 | pop_int(); |
888 | pop_objArray(); |
889 | break; |
890 | } |
891 | case Bytecodes::_aconst_null: |
892 | { |
893 | push_null(); |
894 | break; |
895 | } |
896 | case Bytecodes::_aload: load_local_object(str->get_index()); break; |
897 | case Bytecodes::_aload_0: load_local_object(0); break; |
898 | case Bytecodes::_aload_1: load_local_object(1); break; |
899 | case Bytecodes::_aload_2: load_local_object(2); break; |
900 | case Bytecodes::_aload_3: load_local_object(3); break; |
901 | |
902 | case Bytecodes::_anewarray: |
903 | { |
904 | pop_int(); |
905 | bool will_link; |
906 | ciKlass* element_klass = str->get_klass(will_link); |
907 | if (!will_link) { |
908 | trap(str, element_klass, str->get_klass_index()); |
909 | } else { |
910 | push_object(ciObjArrayKlass::make(element_klass)); |
911 | } |
912 | break; |
913 | } |
914 | case Bytecodes::_areturn: |
915 | case Bytecodes::_ifnonnull: |
916 | case Bytecodes::_ifnull: |
917 | { |
918 | pop_object(); |
919 | break; |
920 | } |
921 | case Bytecodes::_monitorenter: |
922 | { |
923 | pop_object(); |
924 | set_monitor_count(monitor_count() + 1); |
925 | break; |
926 | } |
927 | case Bytecodes::_monitorexit: |
928 | { |
929 | pop_object(); |
930 | assert(monitor_count() > 0, "must be a monitor to exit from")do { if (!(monitor_count() > 0)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 930, "assert(" "monitor_count() > 0" ") failed", "must be a monitor to exit from" ); ::breakpoint(); } } while (0); |
931 | set_monitor_count(monitor_count() - 1); |
932 | break; |
933 | } |
934 | case Bytecodes::_arraylength: |
935 | { |
936 | pop_array(); |
937 | push_int(); |
938 | break; |
939 | } |
940 | case Bytecodes::_astore: store_local_object(str->get_index()); break; |
941 | case Bytecodes::_astore_0: store_local_object(0); break; |
942 | case Bytecodes::_astore_1: store_local_object(1); break; |
943 | case Bytecodes::_astore_2: store_local_object(2); break; |
944 | case Bytecodes::_astore_3: store_local_object(3); break; |
945 | |
946 | case Bytecodes::_athrow: |
947 | { |
948 | NEEDS_CLEANUP; |
949 | pop_object(); |
950 | break; |
951 | } |
952 | case Bytecodes::_baload: |
953 | case Bytecodes::_caload: |
954 | case Bytecodes::_iaload: |
955 | case Bytecodes::_saload: |
956 | { |
957 | pop_int(); |
958 | ciTypeArrayKlass* array_klass = pop_typeArray(); |
959 | // Put assert here for right type? |
960 | push_int(); |
961 | break; |
962 | } |
963 | case Bytecodes::_bastore: |
964 | case Bytecodes::_castore: |
965 | case Bytecodes::_iastore: |
966 | case Bytecodes::_sastore: |
967 | { |
968 | pop_int(); |
969 | pop_int(); |
970 | pop_typeArray(); |
971 | // assert here? |
972 | break; |
973 | } |
974 | case Bytecodes::_bipush: |
975 | case Bytecodes::_iconst_m1: |
976 | case Bytecodes::_iconst_0: |
977 | case Bytecodes::_iconst_1: |
978 | case Bytecodes::_iconst_2: |
979 | case Bytecodes::_iconst_3: |
980 | case Bytecodes::_iconst_4: |
981 | case Bytecodes::_iconst_5: |
982 | case Bytecodes::_sipush: |
983 | { |
984 | push_int(); |
985 | break; |
986 | } |
987 | case Bytecodes::_checkcast: do_checkcast(str); break; |
988 | |
989 | case Bytecodes::_d2f: |
990 | { |
991 | pop_double(); |
992 | push_float(); |
993 | break; |
994 | } |
995 | case Bytecodes::_d2i: |
996 | { |
997 | pop_double(); |
998 | push_int(); |
999 | break; |
1000 | } |
1001 | case Bytecodes::_d2l: |
1002 | { |
1003 | pop_double(); |
1004 | push_long(); |
1005 | break; |
1006 | } |
1007 | case Bytecodes::_dadd: |
1008 | case Bytecodes::_ddiv: |
1009 | case Bytecodes::_dmul: |
1010 | case Bytecodes::_drem: |
1011 | case Bytecodes::_dsub: |
1012 | { |
1013 | pop_double(); |
1014 | pop_double(); |
1015 | push_double(); |
1016 | break; |
1017 | } |
1018 | case Bytecodes::_daload: |
1019 | { |
1020 | pop_int(); |
1021 | ciTypeArrayKlass* array_klass = pop_typeArray(); |
1022 | // Put assert here for right type? |
1023 | push_double(); |
1024 | break; |
1025 | } |
1026 | case Bytecodes::_dastore: |
1027 | { |
1028 | pop_double(); |
1029 | pop_int(); |
1030 | pop_typeArray(); |
1031 | // assert here? |
1032 | break; |
1033 | } |
1034 | case Bytecodes::_dcmpg: |
1035 | case Bytecodes::_dcmpl: |
1036 | { |
1037 | pop_double(); |
1038 | pop_double(); |
1039 | push_int(); |
1040 | break; |
1041 | } |
1042 | case Bytecodes::_dconst_0: |
1043 | case Bytecodes::_dconst_1: |
1044 | { |
1045 | push_double(); |
1046 | break; |
1047 | } |
1048 | case Bytecodes::_dload: load_local_double(str->get_index()); break; |
1049 | case Bytecodes::_dload_0: load_local_double(0); break; |
1050 | case Bytecodes::_dload_1: load_local_double(1); break; |
1051 | case Bytecodes::_dload_2: load_local_double(2); break; |
1052 | case Bytecodes::_dload_3: load_local_double(3); break; |
1053 | |
1054 | case Bytecodes::_dneg: |
1055 | { |
1056 | pop_double(); |
1057 | push_double(); |
1058 | break; |
1059 | } |
1060 | case Bytecodes::_dreturn: |
1061 | { |
1062 | pop_double(); |
1063 | break; |
1064 | } |
1065 | case Bytecodes::_dstore: store_local_double(str->get_index()); break; |
1066 | case Bytecodes::_dstore_0: store_local_double(0); break; |
1067 | case Bytecodes::_dstore_1: store_local_double(1); break; |
1068 | case Bytecodes::_dstore_2: store_local_double(2); break; |
1069 | case Bytecodes::_dstore_3: store_local_double(3); break; |
1070 | |
1071 | case Bytecodes::_dup: |
1072 | { |
1073 | push(type_at_tos()); |
1074 | break; |
1075 | } |
1076 | case Bytecodes::_dup_x1: |
1077 | { |
1078 | ciType* value1 = pop_value(); |
1079 | ciType* value2 = pop_value(); |
1080 | push(value1); |
1081 | push(value2); |
1082 | push(value1); |
1083 | break; |
1084 | } |
1085 | case Bytecodes::_dup_x2: |
1086 | { |
1087 | ciType* value1 = pop_value(); |
1088 | ciType* value2 = pop_value(); |
1089 | ciType* value3 = pop_value(); |
1090 | push(value1); |
1091 | push(value3); |
1092 | push(value2); |
1093 | push(value1); |
1094 | break; |
1095 | } |
1096 | case Bytecodes::_dup2: |
1097 | { |
1098 | ciType* value1 = pop_value(); |
1099 | ciType* value2 = pop_value(); |
1100 | push(value2); |
1101 | push(value1); |
1102 | push(value2); |
1103 | push(value1); |
1104 | break; |
1105 | } |
1106 | case Bytecodes::_dup2_x1: |
1107 | { |
1108 | ciType* value1 = pop_value(); |
1109 | ciType* value2 = pop_value(); |
1110 | ciType* value3 = pop_value(); |
1111 | push(value2); |
1112 | push(value1); |
1113 | push(value3); |
1114 | push(value2); |
1115 | push(value1); |
1116 | break; |
1117 | } |
1118 | case Bytecodes::_dup2_x2: |
1119 | { |
1120 | ciType* value1 = pop_value(); |
1121 | ciType* value2 = pop_value(); |
1122 | ciType* value3 = pop_value(); |
1123 | ciType* value4 = pop_value(); |
1124 | push(value2); |
1125 | push(value1); |
1126 | push(value4); |
1127 | push(value3); |
1128 | push(value2); |
1129 | push(value1); |
1130 | break; |
1131 | } |
1132 | case Bytecodes::_f2d: |
1133 | { |
1134 | pop_float(); |
1135 | push_double(); |
1136 | break; |
1137 | } |
1138 | case Bytecodes::_f2i: |
1139 | { |
1140 | pop_float(); |
1141 | push_int(); |
1142 | break; |
1143 | } |
1144 | case Bytecodes::_f2l: |
1145 | { |
1146 | pop_float(); |
1147 | push_long(); |
1148 | break; |
1149 | } |
1150 | case Bytecodes::_fadd: |
1151 | case Bytecodes::_fdiv: |
1152 | case Bytecodes::_fmul: |
1153 | case Bytecodes::_frem: |
1154 | case Bytecodes::_fsub: |
1155 | { |
1156 | pop_float(); |
1157 | pop_float(); |
1158 | push_float(); |
1159 | break; |
1160 | } |
1161 | case Bytecodes::_faload: |
1162 | { |
1163 | pop_int(); |
1164 | ciTypeArrayKlass* array_klass = pop_typeArray(); |
1165 | // Put assert here. |
1166 | push_float(); |
1167 | break; |
1168 | } |
1169 | case Bytecodes::_fastore: |
1170 | { |
1171 | pop_float(); |
1172 | pop_int(); |
1173 | ciTypeArrayKlass* array_klass = pop_typeArray(); |
1174 | // Put assert here. |
1175 | break; |
1176 | } |
1177 | case Bytecodes::_fcmpg: |
1178 | case Bytecodes::_fcmpl: |
1179 | { |
1180 | pop_float(); |
1181 | pop_float(); |
1182 | push_int(); |
1183 | break; |
1184 | } |
1185 | case Bytecodes::_fconst_0: |
1186 | case Bytecodes::_fconst_1: |
1187 | case Bytecodes::_fconst_2: |
1188 | { |
1189 | push_float(); |
1190 | break; |
1191 | } |
1192 | case Bytecodes::_fload: load_local_float(str->get_index()); break; |
1193 | case Bytecodes::_fload_0: load_local_float(0); break; |
1194 | case Bytecodes::_fload_1: load_local_float(1); break; |
1195 | case Bytecodes::_fload_2: load_local_float(2); break; |
1196 | case Bytecodes::_fload_3: load_local_float(3); break; |
1197 | |
1198 | case Bytecodes::_fneg: |
1199 | { |
1200 | pop_float(); |
1201 | push_float(); |
1202 | break; |
1203 | } |
1204 | case Bytecodes::_freturn: |
1205 | { |
1206 | pop_float(); |
1207 | break; |
1208 | } |
1209 | case Bytecodes::_fstore: store_local_float(str->get_index()); break; |
1210 | case Bytecodes::_fstore_0: store_local_float(0); break; |
1211 | case Bytecodes::_fstore_1: store_local_float(1); break; |
1212 | case Bytecodes::_fstore_2: store_local_float(2); break; |
1213 | case Bytecodes::_fstore_3: store_local_float(3); break; |
1214 | |
1215 | case Bytecodes::_getfield: do_getfield(str); break; |
1216 | case Bytecodes::_getstatic: do_getstatic(str); break; |
1217 | |
1218 | case Bytecodes::_goto: |
1219 | case Bytecodes::_goto_w: |
1220 | case Bytecodes::_nop: |
1221 | case Bytecodes::_return: |
1222 | { |
1223 | // do nothing. |
1224 | break; |
1225 | } |
1226 | case Bytecodes::_i2b: |
1227 | case Bytecodes::_i2c: |
1228 | case Bytecodes::_i2s: |
1229 | case Bytecodes::_ineg: |
1230 | { |
1231 | pop_int(); |
1232 | push_int(); |
1233 | break; |
1234 | } |
1235 | case Bytecodes::_i2d: |
1236 | { |
1237 | pop_int(); |
1238 | push_double(); |
1239 | break; |
1240 | } |
1241 | case Bytecodes::_i2f: |
1242 | { |
1243 | pop_int(); |
1244 | push_float(); |
1245 | break; |
1246 | } |
1247 | case Bytecodes::_i2l: |
1248 | { |
1249 | pop_int(); |
1250 | push_long(); |
1251 | break; |
1252 | } |
1253 | case Bytecodes::_iadd: |
1254 | case Bytecodes::_iand: |
1255 | case Bytecodes::_idiv: |
1256 | case Bytecodes::_imul: |
1257 | case Bytecodes::_ior: |
1258 | case Bytecodes::_irem: |
1259 | case Bytecodes::_ishl: |
1260 | case Bytecodes::_ishr: |
1261 | case Bytecodes::_isub: |
1262 | case Bytecodes::_iushr: |
1263 | case Bytecodes::_ixor: |
1264 | { |
1265 | pop_int(); |
1266 | pop_int(); |
1267 | push_int(); |
1268 | break; |
1269 | } |
1270 | case Bytecodes::_if_acmpeq: |
1271 | case Bytecodes::_if_acmpne: |
1272 | { |
1273 | pop_object(); |
1274 | pop_object(); |
1275 | break; |
1276 | } |
1277 | case Bytecodes::_if_icmpeq: |
1278 | case Bytecodes::_if_icmpge: |
1279 | case Bytecodes::_if_icmpgt: |
1280 | case Bytecodes::_if_icmple: |
1281 | case Bytecodes::_if_icmplt: |
1282 | case Bytecodes::_if_icmpne: |
1283 | { |
1284 | pop_int(); |
1285 | pop_int(); |
1286 | break; |
1287 | } |
1288 | case Bytecodes::_ifeq: |
1289 | case Bytecodes::_ifle: |
1290 | case Bytecodes::_iflt: |
1291 | case Bytecodes::_ifge: |
1292 | case Bytecodes::_ifgt: |
1293 | case Bytecodes::_ifne: |
1294 | case Bytecodes::_ireturn: |
1295 | case Bytecodes::_lookupswitch: |
1296 | case Bytecodes::_tableswitch: |
1297 | { |
1298 | pop_int(); |
1299 | break; |
1300 | } |
1301 | case Bytecodes::_iinc: |
1302 | { |
1303 | int lnum = str->get_index(); |
1304 | check_int(local(lnum)); |
1305 | store_to_local(lnum); |
1306 | break; |
1307 | } |
1308 | case Bytecodes::_iload: load_local_int(str->get_index()); break; |
1309 | case Bytecodes::_iload_0: load_local_int(0); break; |
1310 | case Bytecodes::_iload_1: load_local_int(1); break; |
1311 | case Bytecodes::_iload_2: load_local_int(2); break; |
1312 | case Bytecodes::_iload_3: load_local_int(3); break; |
1313 | |
1314 | case Bytecodes::_instanceof: |
1315 | { |
1316 | // Check for uncommon trap: |
1317 | do_checkcast(str); |
1318 | pop_object(); |
1319 | push_int(); |
1320 | break; |
1321 | } |
1322 | case Bytecodes::_invokeinterface: do_invoke(str, true); break; |
1323 | case Bytecodes::_invokespecial: do_invoke(str, true); break; |
1324 | case Bytecodes::_invokestatic: do_invoke(str, false); break; |
1325 | case Bytecodes::_invokevirtual: do_invoke(str, true); break; |
1326 | case Bytecodes::_invokedynamic: do_invoke(str, false); break; |
1327 | |
1328 | case Bytecodes::_istore: store_local_int(str->get_index()); break; |
1329 | case Bytecodes::_istore_0: store_local_int(0); break; |
1330 | case Bytecodes::_istore_1: store_local_int(1); break; |
1331 | case Bytecodes::_istore_2: store_local_int(2); break; |
1332 | case Bytecodes::_istore_3: store_local_int(3); break; |
1333 | |
1334 | case Bytecodes::_jsr: |
1335 | case Bytecodes::_jsr_w: do_jsr(str); break; |
1336 | |
1337 | case Bytecodes::_l2d: |
1338 | { |
1339 | pop_long(); |
1340 | push_double(); |
1341 | break; |
1342 | } |
1343 | case Bytecodes::_l2f: |
1344 | { |
1345 | pop_long(); |
1346 | push_float(); |
1347 | break; |
1348 | } |
1349 | case Bytecodes::_l2i: |
1350 | { |
1351 | pop_long(); |
1352 | push_int(); |
1353 | break; |
1354 | } |
1355 | case Bytecodes::_ladd: |
1356 | case Bytecodes::_land: |
1357 | case Bytecodes::_ldiv: |
1358 | case Bytecodes::_lmul: |
1359 | case Bytecodes::_lor: |
1360 | case Bytecodes::_lrem: |
1361 | case Bytecodes::_lsub: |
1362 | case Bytecodes::_lxor: |
1363 | { |
1364 | pop_long(); |
1365 | pop_long(); |
1366 | push_long(); |
1367 | break; |
1368 | } |
1369 | case Bytecodes::_laload: |
1370 | { |
1371 | pop_int(); |
1372 | ciTypeArrayKlass* array_klass = pop_typeArray(); |
1373 | // Put assert here for right type? |
1374 | push_long(); |
1375 | break; |
1376 | } |
1377 | case Bytecodes::_lastore: |
1378 | { |
1379 | pop_long(); |
1380 | pop_int(); |
1381 | pop_typeArray(); |
1382 | // assert here? |
1383 | break; |
1384 | } |
1385 | case Bytecodes::_lcmp: |
1386 | { |
1387 | pop_long(); |
1388 | pop_long(); |
1389 | push_int(); |
1390 | break; |
1391 | } |
1392 | case Bytecodes::_lconst_0: |
1393 | case Bytecodes::_lconst_1: |
1394 | { |
1395 | push_long(); |
1396 | break; |
1397 | } |
1398 | case Bytecodes::_ldc: |
1399 | case Bytecodes::_ldc_w: |
1400 | case Bytecodes::_ldc2_w: |
1401 | { |
1402 | do_ldc(str); |
1403 | break; |
1404 | } |
1405 | |
1406 | case Bytecodes::_lload: load_local_long(str->get_index()); break; |
1407 | case Bytecodes::_lload_0: load_local_long(0); break; |
1408 | case Bytecodes::_lload_1: load_local_long(1); break; |
1409 | case Bytecodes::_lload_2: load_local_long(2); break; |
1410 | case Bytecodes::_lload_3: load_local_long(3); break; |
1411 | |
1412 | case Bytecodes::_lneg: |
1413 | { |
1414 | pop_long(); |
1415 | push_long(); |
1416 | break; |
1417 | } |
1418 | case Bytecodes::_lreturn: |
1419 | { |
1420 | pop_long(); |
1421 | break; |
1422 | } |
1423 | case Bytecodes::_lshl: |
1424 | case Bytecodes::_lshr: |
1425 | case Bytecodes::_lushr: |
1426 | { |
1427 | pop_int(); |
1428 | pop_long(); |
1429 | push_long(); |
1430 | break; |
1431 | } |
1432 | case Bytecodes::_lstore: store_local_long(str->get_index()); break; |
1433 | case Bytecodes::_lstore_0: store_local_long(0); break; |
1434 | case Bytecodes::_lstore_1: store_local_long(1); break; |
1435 | case Bytecodes::_lstore_2: store_local_long(2); break; |
1436 | case Bytecodes::_lstore_3: store_local_long(3); break; |
1437 | |
1438 | case Bytecodes::_multianewarray: do_multianewarray(str); break; |
1439 | |
1440 | case Bytecodes::_new: do_new(str); break; |
1441 | |
1442 | case Bytecodes::_newarray: do_newarray(str); break; |
1443 | |
1444 | case Bytecodes::_pop: |
1445 | { |
1446 | pop(); |
1447 | break; |
1448 | } |
1449 | case Bytecodes::_pop2: |
1450 | { |
1451 | pop(); |
1452 | pop(); |
1453 | break; |
1454 | } |
1455 | |
1456 | case Bytecodes::_putfield: do_putfield(str); break; |
1457 | case Bytecodes::_putstatic: do_putstatic(str); break; |
1458 | |
1459 | case Bytecodes::_ret: do_ret(str); break; |
1460 | |
1461 | case Bytecodes::_swap: |
1462 | { |
1463 | ciType* value1 = pop_value(); |
1464 | ciType* value2 = pop_value(); |
1465 | push(value1); |
1466 | push(value2); |
1467 | break; |
1468 | } |
1469 | case Bytecodes::_wide: |
1470 | default: |
1471 | { |
1472 | // The iterator should skip this. |
1473 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1473); ::breakpoint(); } while (0); |
1474 | break; |
1475 | } |
1476 | } |
1477 | |
1478 | if (CITraceTypeFlow) { |
1479 | print_on(tty); |
1480 | } |
1481 | |
1482 | return (_trap_bci != -1); |
1483 | } |
1484 | |
1485 | #ifndef PRODUCT |
1486 | // ------------------------------------------------------------------ |
1487 | // ciTypeFlow::StateVector::print_cell_on |
1488 | void ciTypeFlow::StateVector::print_cell_on(outputStream* st, Cell c) const { |
1489 | ciType* type = type_at(c); |
1490 | if (type == top_type()) { |
1491 | st->print("top"); |
1492 | } else if (type == bottom_type()) { |
1493 | st->print("bottom"); |
1494 | } else if (type == null_type()) { |
1495 | st->print("null"); |
1496 | } else if (type == long2_type()) { |
1497 | st->print("long2"); |
1498 | } else if (type == double2_type()) { |
1499 | st->print("double2"); |
1500 | } else if (is_int(type)) { |
1501 | st->print("int"); |
1502 | } else if (is_long(type)) { |
1503 | st->print("long"); |
1504 | } else if (is_float(type)) { |
1505 | st->print("float"); |
1506 | } else if (is_double(type)) { |
1507 | st->print("double"); |
1508 | } else if (type->is_return_address()) { |
1509 | st->print("address(%d)", type->as_return_address()->bci()); |
1510 | } else { |
1511 | if (type->is_klass()) { |
1512 | type->as_klass()->name()->print_symbol_on(st); |
1513 | } else { |
1514 | st->print("UNEXPECTED TYPE"); |
1515 | type->print(); |
1516 | } |
1517 | } |
1518 | } |
1519 | |
1520 | // ------------------------------------------------------------------ |
1521 | // ciTypeFlow::StateVector::print_on |
1522 | void ciTypeFlow::StateVector::print_on(outputStream* st) const { |
1523 | int num_locals = _outer->max_locals(); |
1524 | int num_stack = stack_size(); |
1525 | int num_monitors = monitor_count(); |
1526 | st->print_cr(" State : locals %d, stack %d, monitors %d", num_locals, num_stack, num_monitors); |
1527 | if (num_stack >= 0) { |
1528 | int i; |
1529 | for (i = 0; i < num_locals; i++) { |
1530 | st->print(" local %2d : ", i); |
1531 | print_cell_on(st, local(i)); |
1532 | st->cr(); |
1533 | } |
1534 | for (i = 0; i < num_stack; i++) { |
1535 | st->print(" stack %2d : ", i); |
1536 | print_cell_on(st, stack(i)); |
1537 | st->cr(); |
1538 | } |
1539 | } |
1540 | } |
1541 | #endif |
1542 | |
1543 | |
1544 | // ------------------------------------------------------------------ |
1545 | // ciTypeFlow::SuccIter::next |
1546 | // |
1547 | void ciTypeFlow::SuccIter::next() { |
1548 | int succ_ct = _pred->successors()->length(); |
1549 | int next = _index + 1; |
1550 | if (next < succ_ct) { |
1551 | _index = next; |
1552 | _succ = _pred->successors()->at(next); |
1553 | return; |
1554 | } |
1555 | for (int i = next - succ_ct; i < _pred->exceptions()->length(); i++) { |
1556 | // Do not compile any code for unloaded exception types. |
1557 | // Following compiler passes are responsible for doing this also. |
1558 | ciInstanceKlass* exception_klass = _pred->exc_klasses()->at(i); |
1559 | if (exception_klass->is_loaded()) { |
1560 | _index = next; |
1561 | _succ = _pred->exceptions()->at(i); |
1562 | return; |
1563 | } |
1564 | next++; |
1565 | } |
1566 | _index = -1; |
1567 | _succ = NULL__null; |
1568 | } |
1569 | |
1570 | // ------------------------------------------------------------------ |
1571 | // ciTypeFlow::SuccIter::set_succ |
1572 | // |
1573 | void ciTypeFlow::SuccIter::set_succ(Block* succ) { |
1574 | int succ_ct = _pred->successors()->length(); |
1575 | if (_index < succ_ct) { |
1576 | _pred->successors()->at_put(_index, succ); |
1577 | } else { |
1578 | int idx = _index - succ_ct; |
1579 | _pred->exceptions()->at_put(idx, succ); |
1580 | } |
1581 | } |
1582 | |
1583 | // ciTypeFlow::Block |
1584 | // |
1585 | // A basic block. |
1586 | |
1587 | // ------------------------------------------------------------------ |
1588 | // ciTypeFlow::Block::Block |
1589 | ciTypeFlow::Block::Block(ciTypeFlow* outer, |
1590 | ciBlock *ciblk, |
1591 | ciTypeFlow::JsrSet* jsrs) : _predecessors(outer->arena(), 1, 0, NULL__null) { |
1592 | _ciblock = ciblk; |
1593 | _exceptions = NULL__null; |
1594 | _exc_klasses = NULL__null; |
1595 | _successors = NULL__null; |
1596 | _state = new (outer->arena()) StateVector(outer); |
1597 | JsrSet* new_jsrs = |
1598 | new (outer->arena()) JsrSet(outer->arena(), jsrs->size()); |
1599 | jsrs->copy_into(new_jsrs); |
1600 | _jsrs = new_jsrs; |
1601 | _next = NULL__null; |
1602 | _on_work_list = false; |
1603 | _backedge_copy = false; |
1604 | _has_monitorenter = false; |
1605 | _trap_bci = -1; |
1606 | _trap_index = 0; |
1607 | df_init(); |
1608 | |
1609 | if (CITraceTypeFlow) { |
1610 | tty->print_cr(">> Created new block"); |
1611 | print_on(tty); |
1612 | } |
1613 | |
1614 | assert(this->outer() == outer, "outer link set up")do { if (!(this->outer() == outer)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1614, "assert(" "this->outer() == outer" ") failed", "outer link set up" ); ::breakpoint(); } } while (0); |
1615 | assert(!outer->have_block_count(), "must not have mapped blocks yet")do { if (!(!outer->have_block_count())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1615, "assert(" "!outer->have_block_count()" ") failed", "must not have mapped blocks yet"); ::breakpoint(); } } while (0); |
1616 | } |
1617 | |
1618 | // ------------------------------------------------------------------ |
1619 | // ciTypeFlow::Block::df_init |
1620 | void ciTypeFlow::Block::df_init() { |
1621 | _pre_order = -1; assert(!has_pre_order(), "")do { if (!(!has_pre_order())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1621, "assert(" "!has_pre_order()" ") failed", ""); ::breakpoint (); } } while (0); |
1622 | _post_order = -1; assert(!has_post_order(), "")do { if (!(!has_post_order())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1622, "assert(" "!has_post_order()" ") failed", ""); ::breakpoint (); } } while (0); |
1623 | _loop = NULL__null; |
1624 | _irreducible_entry = false; |
1625 | _rpo_next = NULL__null; |
1626 | } |
1627 | |
1628 | // ------------------------------------------------------------------ |
1629 | // ciTypeFlow::Block::successors |
1630 | // |
1631 | // Get the successors for this Block. |
1632 | GrowableArray<ciTypeFlow::Block*>* |
1633 | ciTypeFlow::Block::successors(ciBytecodeStream* str, |
1634 | ciTypeFlow::StateVector* state, |
1635 | ciTypeFlow::JsrSet* jsrs) { |
1636 | if (_successors == NULL__null) { |
1637 | if (CITraceTypeFlow) { |
1638 | tty->print(">> Computing successors for block "); |
1639 | print_value_on(tty); |
1640 | tty->cr(); |
1641 | } |
1642 | |
1643 | ciTypeFlow* analyzer = outer(); |
1644 | Arena* arena = analyzer->arena(); |
1645 | Block* block = NULL__null; |
1646 | bool has_successor = !has_trap() && |
1647 | (control() != ciBlock::fall_through_bci || limit() < analyzer->code_size()); |
1648 | if (!has_successor) { |
1649 | _successors = |
1650 | new (arena) GrowableArray<Block*>(arena, 1, 0, NULL__null); |
1651 | // No successors |
1652 | } else if (control() == ciBlock::fall_through_bci) { |
1653 | assert(str->cur_bci() == limit(), "bad block end")do { if (!(str->cur_bci() == limit())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1653, "assert(" "str->cur_bci() == limit()" ") failed", "bad block end" ); ::breakpoint(); } } while (0); |
1654 | // This block simply falls through to the next. |
1655 | _successors = |
1656 | new (arena) GrowableArray<Block*>(arena, 1, 0, NULL__null); |
1657 | |
1658 | Block* block = analyzer->block_at(limit(), _jsrs); |
1659 | assert(_successors->length() == FALL_THROUGH, "")do { if (!(_successors->length() == FALL_THROUGH)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1659, "assert(" "_successors->length() == FALL_THROUGH" ") failed" , ""); ::breakpoint(); } } while (0); |
1660 | _successors->append(block); |
1661 | } else { |
1662 | int current_bci = str->cur_bci(); |
1663 | int next_bci = str->next_bci(); |
1664 | int branch_bci = -1; |
1665 | Block* target = NULL__null; |
1666 | assert(str->next_bci() == limit(), "bad block end")do { if (!(str->next_bci() == limit())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1666, "assert(" "str->next_bci() == limit()" ") failed", "bad block end"); ::breakpoint(); } } while (0); |
1667 | // This block is not a simple fall-though. Interpret |
1668 | // the current bytecode to find our successors. |
1669 | switch (str->cur_bc()) { |
1670 | case Bytecodes::_ifeq: case Bytecodes::_ifne: |
1671 | case Bytecodes::_iflt: case Bytecodes::_ifge: |
1672 | case Bytecodes::_ifgt: case Bytecodes::_ifle: |
1673 | case Bytecodes::_if_icmpeq: case Bytecodes::_if_icmpne: |
1674 | case Bytecodes::_if_icmplt: case Bytecodes::_if_icmpge: |
1675 | case Bytecodes::_if_icmpgt: case Bytecodes::_if_icmple: |
1676 | case Bytecodes::_if_acmpeq: case Bytecodes::_if_acmpne: |
1677 | case Bytecodes::_ifnull: case Bytecodes::_ifnonnull: |
1678 | // Our successors are the branch target and the next bci. |
1679 | branch_bci = str->get_dest(); |
1680 | _successors = |
1681 | new (arena) GrowableArray<Block*>(arena, 2, 0, NULL__null); |
1682 | assert(_successors->length() == IF_NOT_TAKEN, "")do { if (!(_successors->length() == IF_NOT_TAKEN)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1682, "assert(" "_successors->length() == IF_NOT_TAKEN" ") failed" , ""); ::breakpoint(); } } while (0); |
1683 | _successors->append(analyzer->block_at(next_bci, jsrs)); |
1684 | assert(_successors->length() == IF_TAKEN, "")do { if (!(_successors->length() == IF_TAKEN)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1684, "assert(" "_successors->length() == IF_TAKEN" ") failed" , ""); ::breakpoint(); } } while (0); |
1685 | _successors->append(analyzer->block_at(branch_bci, jsrs)); |
1686 | break; |
1687 | |
1688 | case Bytecodes::_goto: |
1689 | branch_bci = str->get_dest(); |
1690 | _successors = |
1691 | new (arena) GrowableArray<Block*>(arena, 1, 0, NULL__null); |
1692 | assert(_successors->length() == GOTO_TARGET, "")do { if (!(_successors->length() == GOTO_TARGET)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1692, "assert(" "_successors->length() == GOTO_TARGET" ") failed" , ""); ::breakpoint(); } } while (0); |
1693 | _successors->append(analyzer->block_at(branch_bci, jsrs)); |
1694 | break; |
1695 | |
1696 | case Bytecodes::_jsr: |
1697 | branch_bci = str->get_dest(); |
1698 | _successors = |
1699 | new (arena) GrowableArray<Block*>(arena, 1, 0, NULL__null); |
1700 | assert(_successors->length() == GOTO_TARGET, "")do { if (!(_successors->length() == GOTO_TARGET)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1700, "assert(" "_successors->length() == GOTO_TARGET" ") failed" , ""); ::breakpoint(); } } while (0); |
1701 | _successors->append(analyzer->block_at(branch_bci, jsrs)); |
1702 | break; |
1703 | |
1704 | case Bytecodes::_goto_w: |
1705 | case Bytecodes::_jsr_w: |
1706 | _successors = |
1707 | new (arena) GrowableArray<Block*>(arena, 1, 0, NULL__null); |
1708 | assert(_successors->length() == GOTO_TARGET, "")do { if (!(_successors->length() == GOTO_TARGET)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1708, "assert(" "_successors->length() == GOTO_TARGET" ") failed" , ""); ::breakpoint(); } } while (0); |
1709 | _successors->append(analyzer->block_at(str->get_far_dest(), jsrs)); |
1710 | break; |
1711 | |
1712 | case Bytecodes::_tableswitch: { |
1713 | Bytecode_tableswitch tableswitch(str); |
1714 | |
1715 | int len = tableswitch.length(); |
1716 | _successors = |
1717 | new (arena) GrowableArray<Block*>(arena, len+1, 0, NULL__null); |
1718 | int bci = current_bci + tableswitch.default_offset(); |
1719 | Block* block = analyzer->block_at(bci, jsrs); |
1720 | assert(_successors->length() == SWITCH_DEFAULT, "")do { if (!(_successors->length() == SWITCH_DEFAULT)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1720, "assert(" "_successors->length() == SWITCH_DEFAULT" ") failed", ""); ::breakpoint(); } } while (0); |
1721 | _successors->append(block); |
1722 | while (--len >= 0) { |
1723 | int bci = current_bci + tableswitch.dest_offset_at(len); |
1724 | block = analyzer->block_at(bci, jsrs); |
1725 | assert(_successors->length() >= SWITCH_CASES, "")do { if (!(_successors->length() >= SWITCH_CASES)) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1725, "assert(" "_successors->length() >= SWITCH_CASES" ") failed", ""); ::breakpoint(); } } while (0); |
1726 | _successors->append_if_missing(block); |
1727 | } |
1728 | break; |
1729 | } |
1730 | |
1731 | case Bytecodes::_lookupswitch: { |
1732 | Bytecode_lookupswitch lookupswitch(str); |
1733 | |
1734 | int npairs = lookupswitch.number_of_pairs(); |
1735 | _successors = |
1736 | new (arena) GrowableArray<Block*>(arena, npairs+1, 0, NULL__null); |
1737 | int bci = current_bci + lookupswitch.default_offset(); |
1738 | Block* block = analyzer->block_at(bci, jsrs); |
1739 | assert(_successors->length() == SWITCH_DEFAULT, "")do { if (!(_successors->length() == SWITCH_DEFAULT)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1739, "assert(" "_successors->length() == SWITCH_DEFAULT" ") failed", ""); ::breakpoint(); } } while (0); |
1740 | _successors->append(block); |
1741 | while(--npairs >= 0) { |
1742 | LookupswitchPair pair = lookupswitch.pair_at(npairs); |
1743 | int bci = current_bci + pair.offset(); |
1744 | Block* block = analyzer->block_at(bci, jsrs); |
1745 | assert(_successors->length() >= SWITCH_CASES, "")do { if (!(_successors->length() >= SWITCH_CASES)) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1745, "assert(" "_successors->length() >= SWITCH_CASES" ") failed", ""); ::breakpoint(); } } while (0); |
1746 | _successors->append_if_missing(block); |
1747 | } |
1748 | break; |
1749 | } |
1750 | |
1751 | case Bytecodes::_athrow: case Bytecodes::_ireturn: |
1752 | case Bytecodes::_lreturn: case Bytecodes::_freturn: |
1753 | case Bytecodes::_dreturn: case Bytecodes::_areturn: |
1754 | case Bytecodes::_return: |
1755 | _successors = |
1756 | new (arena) GrowableArray<Block*>(arena, 1, 0, NULL__null); |
1757 | // No successors |
1758 | break; |
1759 | |
1760 | case Bytecodes::_ret: { |
1761 | _successors = |
1762 | new (arena) GrowableArray<Block*>(arena, 1, 0, NULL__null); |
1763 | |
1764 | Cell local = state->local(str->get_index()); |
1765 | ciType* return_address = state->type_at(local); |
1766 | assert(return_address->is_return_address(), "verify: wrong type")do { if (!(return_address->is_return_address())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1766, "assert(" "return_address->is_return_address()" ") failed" , "verify: wrong type"); ::breakpoint(); } } while (0); |
1767 | int bci = return_address->as_return_address()->bci(); |
1768 | assert(_successors->length() == GOTO_TARGET, "")do { if (!(_successors->length() == GOTO_TARGET)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1768, "assert(" "_successors->length() == GOTO_TARGET" ") failed" , ""); ::breakpoint(); } } while (0); |
1769 | _successors->append(analyzer->block_at(bci, jsrs)); |
1770 | break; |
1771 | } |
1772 | |
1773 | case Bytecodes::_wide: |
1774 | default: |
1775 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1775); ::breakpoint(); } while (0); |
1776 | break; |
1777 | } |
1778 | } |
1779 | |
1780 | // Set predecessor information |
1781 | for (int i = 0; i < _successors->length(); i++) { |
1782 | Block* block = _successors->at(i); |
1783 | block->predecessors()->append(this); |
1784 | } |
1785 | } |
1786 | return _successors; |
1787 | } |
1788 | |
1789 | // ------------------------------------------------------------------ |
1790 | // ciTypeFlow::Block:compute_exceptions |
1791 | // |
1792 | // Compute the exceptional successors and types for this Block. |
1793 | void ciTypeFlow::Block::compute_exceptions() { |
1794 | assert(_exceptions == NULL && _exc_klasses == NULL, "repeat")do { if (!(_exceptions == __null && _exc_klasses == __null )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1794, "assert(" "_exceptions == __null && _exc_klasses == __null" ") failed", "repeat"); ::breakpoint(); } } while (0); |
1795 | |
1796 | if (CITraceTypeFlow) { |
1797 | tty->print(">> Computing exceptions for block "); |
1798 | print_value_on(tty); |
1799 | tty->cr(); |
1800 | } |
1801 | |
1802 | ciTypeFlow* analyzer = outer(); |
1803 | Arena* arena = analyzer->arena(); |
1804 | |
1805 | // Any bci in the block will do. |
1806 | ciExceptionHandlerStream str(analyzer->method(), start()); |
1807 | |
1808 | // Allocate our growable arrays. |
1809 | int exc_count = str.count(); |
1810 | _exceptions = new (arena) GrowableArray<Block*>(arena, exc_count, 0, NULL__null); |
1811 | _exc_klasses = new (arena) GrowableArray<ciInstanceKlass*>(arena, exc_count, |
1812 | 0, NULL__null); |
1813 | |
1814 | for ( ; !str.is_done(); str.next()) { |
1815 | ciExceptionHandler* handler = str.handler(); |
1816 | int bci = handler->handler_bci(); |
1817 | ciInstanceKlass* klass = NULL__null; |
1818 | if (bci == -1) { |
1819 | // There is no catch all. It is possible to exit the method. |
1820 | break; |
1821 | } |
1822 | if (handler->is_catch_all()) { |
1823 | klass = analyzer->env()->Throwable_klass(); |
1824 | } else { |
1825 | klass = handler->catch_klass(); |
1826 | } |
1827 | Block* block = analyzer->block_at(bci, _jsrs); |
1828 | _exceptions->append(block); |
1829 | block->predecessors()->append(this); |
1830 | _exc_klasses->append(klass); |
1831 | } |
1832 | } |
1833 | |
1834 | // ------------------------------------------------------------------ |
1835 | // ciTypeFlow::Block::set_backedge_copy |
1836 | // Use this only to make a pre-existing public block into a backedge copy. |
1837 | void ciTypeFlow::Block::set_backedge_copy(bool z) { |
1838 | assert(z || (z == is_backedge_copy()), "cannot make a backedge copy public")do { if (!(z || (z == is_backedge_copy()))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1838, "assert(" "z || (z == is_backedge_copy())" ") failed" , "cannot make a backedge copy public"); ::breakpoint(); } } while (0); |
1839 | _backedge_copy = z; |
1840 | } |
1841 | |
1842 | // ------------------------------------------------------------------ |
1843 | // ciTypeFlow::Block::is_clonable_exit |
1844 | // |
1845 | // At most 2 normal successors, one of which continues looping, |
1846 | // and all exceptional successors must exit. |
1847 | bool ciTypeFlow::Block::is_clonable_exit(ciTypeFlow::Loop* lp) { |
1848 | int normal_cnt = 0; |
1849 | int in_loop_cnt = 0; |
1850 | for (SuccIter iter(this); !iter.done(); iter.next()) { |
1851 | Block* succ = iter.succ(); |
1852 | if (iter.is_normal_ctrl()) { |
1853 | if (++normal_cnt > 2) return false; |
1854 | if (lp->contains(succ->loop())) { |
1855 | if (++in_loop_cnt > 1) return false; |
1856 | } |
1857 | } else { |
1858 | if (lp->contains(succ->loop())) return false; |
1859 | } |
1860 | } |
1861 | return in_loop_cnt == 1; |
1862 | } |
1863 | |
1864 | // ------------------------------------------------------------------ |
1865 | // ciTypeFlow::Block::looping_succ |
1866 | // |
1867 | ciTypeFlow::Block* ciTypeFlow::Block::looping_succ(ciTypeFlow::Loop* lp) { |
1868 | assert(successors()->length() <= 2, "at most 2 normal successors")do { if (!(successors()->length() <= 2)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1868, "assert(" "successors()->length() <= 2" ") failed" , "at most 2 normal successors"); ::breakpoint(); } } while ( 0); |
1869 | for (SuccIter iter(this); !iter.done(); iter.next()) { |
1870 | Block* succ = iter.succ(); |
1871 | if (lp->contains(succ->loop())) { |
1872 | return succ; |
1873 | } |
1874 | } |
1875 | return NULL__null; |
1876 | } |
1877 | |
1878 | #ifndef PRODUCT |
1879 | // ------------------------------------------------------------------ |
1880 | // ciTypeFlow::Block::print_value_on |
1881 | void ciTypeFlow::Block::print_value_on(outputStream* st) const { |
1882 | if (has_pre_order()) st->print("#%-2d ", pre_order()); |
1883 | if (has_rpo()) st->print("rpo#%-2d ", rpo()); |
1884 | st->print("[%d - %d)", start(), limit()); |
1885 | if (is_loop_head()) st->print(" lphd"); |
1886 | if (is_irreducible_entry()) st->print(" irred"); |
1887 | if (_jsrs->size() > 0) { st->print("/"); _jsrs->print_on(st); } |
1888 | if (is_backedge_copy()) st->print("/backedge_copy"); |
1889 | } |
1890 | |
1891 | // ------------------------------------------------------------------ |
1892 | // ciTypeFlow::Block::print_on |
1893 | void ciTypeFlow::Block::print_on(outputStream* st) const { |
1894 | if ((Verbose || WizardMode) && (limit() >= 0)) { |
1895 | // Don't print 'dummy' blocks (i.e. blocks with limit() '-1') |
1896 | outer()->method()->print_codes_on(start(), limit(), st); |
1897 | } |
1898 | st->print_cr(" ==================================================== "); |
1899 | st->print (" "); |
1900 | print_value_on(st); |
1901 | st->print(" Stored locals: "); def_locals()->print_on(st, outer()->method()->max_locals()); tty->cr(); |
1902 | if (loop() && loop()->parent() != NULL__null) { |
1903 | st->print(" loops:"); |
1904 | Loop* lp = loop(); |
1905 | do { |
1906 | st->print(" %d<-%d", lp->head()->pre_order(),lp->tail()->pre_order()); |
1907 | if (lp->is_irreducible()) st->print("(ir)"); |
1908 | lp = lp->parent(); |
1909 | } while (lp->parent() != NULL__null); |
1910 | } |
1911 | st->cr(); |
1912 | _state->print_on(st); |
1913 | if (_successors == NULL__null) { |
1914 | st->print_cr(" No successor information"); |
1915 | } else { |
1916 | int num_successors = _successors->length(); |
1917 | st->print_cr(" Successors : %d", num_successors); |
1918 | for (int i = 0; i < num_successors; i++) { |
1919 | Block* successor = _successors->at(i); |
1920 | st->print(" "); |
1921 | successor->print_value_on(st); |
1922 | st->cr(); |
1923 | } |
1924 | } |
1925 | if (_predecessors.is_empty()) { |
1926 | st->print_cr(" No predecessor information"); |
1927 | } else { |
1928 | int num_predecessors = _predecessors.length(); |
1929 | st->print_cr(" Predecessors : %d", num_predecessors); |
1930 | for (int i = 0; i < num_predecessors; i++) { |
1931 | Block* predecessor = _predecessors.at(i); |
1932 | st->print(" "); |
1933 | predecessor->print_value_on(st); |
1934 | st->cr(); |
1935 | } |
1936 | } |
1937 | if (_exceptions == NULL__null) { |
1938 | st->print_cr(" No exception information"); |
1939 | } else { |
1940 | int num_exceptions = _exceptions->length(); |
1941 | st->print_cr(" Exceptions : %d", num_exceptions); |
1942 | for (int i = 0; i < num_exceptions; i++) { |
1943 | Block* exc_succ = _exceptions->at(i); |
1944 | ciInstanceKlass* exc_klass = _exc_klasses->at(i); |
1945 | st->print(" "); |
1946 | exc_succ->print_value_on(st); |
1947 | st->print(" -- "); |
1948 | exc_klass->name()->print_symbol_on(st); |
1949 | st->cr(); |
1950 | } |
1951 | } |
1952 | if (has_trap()) { |
1953 | st->print_cr(" Traps on %d with trap index %d", trap_bci(), trap_index()); |
1954 | } |
1955 | st->print_cr(" ==================================================== "); |
1956 | } |
1957 | #endif |
1958 | |
1959 | #ifndef PRODUCT |
1960 | // ------------------------------------------------------------------ |
1961 | // ciTypeFlow::LocalSet::print_on |
1962 | void ciTypeFlow::LocalSet::print_on(outputStream* st, int limit) const { |
1963 | st->print("{"); |
1964 | for (int i = 0; i < max; i++) { |
1965 | if (test(i)) st->print(" %d", i); |
1966 | } |
1967 | if (limit > max) { |
1968 | st->print(" %d..%d ", max, limit); |
1969 | } |
1970 | st->print(" }"); |
1971 | } |
1972 | #endif |
1973 | |
1974 | // ciTypeFlow |
1975 | // |
1976 | // This is a pass over the bytecodes which computes the following: |
1977 | // basic block structure |
1978 | // interpreter type-states (a la the verifier) |
1979 | |
1980 | // ------------------------------------------------------------------ |
1981 | // ciTypeFlow::ciTypeFlow |
1982 | ciTypeFlow::ciTypeFlow(ciEnv* env, ciMethod* method, int osr_bci) { |
1983 | _env = env; |
1984 | _method = method; |
1985 | _has_irreducible_entry = false; |
1986 | _osr_bci = osr_bci; |
1987 | _failure_reason = NULL__null; |
1988 | assert(0 <= start_bci() && start_bci() < code_size() , "correct osr_bci argument: 0 <= %d < %d", start_bci(), code_size())do { if (!(0 <= start_bci() && start_bci() < code_size ())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 1988, "assert(" "0 <= start_bci() && start_bci() < code_size()" ") failed", "correct osr_bci argument: 0 <= %d < %d", start_bci (), code_size()); ::breakpoint(); } } while (0); |
1989 | _work_list = NULL__null; |
1990 | |
1991 | int ciblock_count = _method->get_method_blocks()->num_blocks(); |
1992 | _idx_to_blocklist = NEW_ARENA_ARRAY(arena(), GrowableArray<Block*>*, ciblock_count)(GrowableArray<Block*>**) (arena())->Amalloc((ciblock_count ) * sizeof(GrowableArray<Block*>*)); |
1993 | for (int i = 0; i < ciblock_count; i++) { |
1994 | _idx_to_blocklist[i] = NULL__null; |
1995 | } |
1996 | _block_map = NULL__null; // until all blocks are seen |
1997 | _jsr_records = NULL__null; |
1998 | } |
1999 | |
2000 | // ------------------------------------------------------------------ |
2001 | // ciTypeFlow::work_list_next |
2002 | // |
2003 | // Get the next basic block from our work list. |
2004 | ciTypeFlow::Block* ciTypeFlow::work_list_next() { |
2005 | assert(!work_list_empty(), "work list must not be empty")do { if (!(!work_list_empty())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2005, "assert(" "!work_list_empty()" ") failed", "work list must not be empty" ); ::breakpoint(); } } while (0); |
2006 | Block* next_block = _work_list; |
2007 | _work_list = next_block->next(); |
2008 | next_block->set_next(NULL__null); |
2009 | next_block->set_on_work_list(false); |
2010 | return next_block; |
2011 | } |
2012 | |
2013 | // ------------------------------------------------------------------ |
2014 | // ciTypeFlow::add_to_work_list |
2015 | // |
2016 | // Add a basic block to our work list. |
2017 | // List is sorted by decreasing postorder sort (same as increasing RPO) |
2018 | void ciTypeFlow::add_to_work_list(ciTypeFlow::Block* block) { |
2019 | assert(!block->is_on_work_list(), "must not already be on work list")do { if (!(!block->is_on_work_list())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2019, "assert(" "!block->is_on_work_list()" ") failed", "must not already be on work list" ); ::breakpoint(); } } while (0); |
2020 | |
2021 | if (CITraceTypeFlow) { |
2022 | tty->print(">> Adding block "); |
2023 | block->print_value_on(tty); |
2024 | tty->print_cr(" to the work list : "); |
2025 | } |
2026 | |
2027 | block->set_on_work_list(true); |
2028 | |
2029 | // decreasing post order sort |
2030 | |
2031 | Block* prev = NULL__null; |
2032 | Block* current = _work_list; |
2033 | int po = block->post_order(); |
2034 | while (current != NULL__null) { |
2035 | if (!current->has_post_order() || po > current->post_order()) |
2036 | break; |
2037 | prev = current; |
2038 | current = current->next(); |
2039 | } |
2040 | if (prev == NULL__null) { |
2041 | block->set_next(_work_list); |
2042 | _work_list = block; |
2043 | } else { |
2044 | block->set_next(current); |
2045 | prev->set_next(block); |
2046 | } |
2047 | |
2048 | if (CITraceTypeFlow) { |
2049 | tty->cr(); |
2050 | } |
2051 | } |
2052 | |
2053 | // ------------------------------------------------------------------ |
2054 | // ciTypeFlow::block_at |
2055 | // |
2056 | // Return the block beginning at bci which has a JsrSet compatible |
2057 | // with jsrs. |
2058 | ciTypeFlow::Block* ciTypeFlow::block_at(int bci, ciTypeFlow::JsrSet* jsrs, CreateOption option) { |
2059 | // First find the right ciBlock. |
2060 | if (CITraceTypeFlow) { |
2061 | tty->print(">> Requesting block for %d/", bci); |
2062 | jsrs->print_on(tty); |
2063 | tty->cr(); |
2064 | } |
2065 | |
2066 | ciBlock* ciblk = _method->get_method_blocks()->block_containing(bci); |
2067 | assert(ciblk->start_bci() == bci, "bad ciBlock boundaries")do { if (!(ciblk->start_bci() == bci)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2067, "assert(" "ciblk->start_bci() == bci" ") failed", "bad ciBlock boundaries" ); ::breakpoint(); } } while (0); |
2068 | Block* block = get_block_for(ciblk->index(), jsrs, option); |
2069 | |
2070 | assert(block == NULL? (option == no_create): block->is_backedge_copy() == (option == create_backedge_copy), "create option consistent with result")do { if (!(block == __null? (option == no_create): block-> is_backedge_copy() == (option == create_backedge_copy))) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2070, "assert(" "block == __null? (option == no_create): block->is_backedge_copy() == (option == create_backedge_copy)" ") failed", "create option consistent with result"); ::breakpoint (); } } while (0); |
2071 | |
2072 | if (CITraceTypeFlow) { |
2073 | if (block != NULL__null) { |
2074 | tty->print(">> Found block "); |
2075 | block->print_value_on(tty); |
2076 | tty->cr(); |
2077 | } else { |
2078 | tty->print_cr(">> No such block."); |
2079 | } |
2080 | } |
2081 | |
2082 | return block; |
2083 | } |
2084 | |
2085 | // ------------------------------------------------------------------ |
2086 | // ciTypeFlow::make_jsr_record |
2087 | // |
2088 | // Make a JsrRecord for a given (entry, return) pair, if such a record |
2089 | // does not already exist. |
2090 | ciTypeFlow::JsrRecord* ciTypeFlow::make_jsr_record(int entry_address, |
2091 | int return_address) { |
2092 | if (_jsr_records == NULL__null) { |
2093 | _jsr_records = new (arena()) GrowableArray<JsrRecord*>(arena(), |
2094 | 2, |
2095 | 0, |
2096 | NULL__null); |
2097 | } |
2098 | JsrRecord* record = NULL__null; |
2099 | int len = _jsr_records->length(); |
2100 | for (int i = 0; i < len; i++) { |
2101 | JsrRecord* record = _jsr_records->at(i); |
2102 | if (record->entry_address() == entry_address && |
2103 | record->return_address() == return_address) { |
2104 | return record; |
2105 | } |
2106 | } |
2107 | |
2108 | record = new (arena()) JsrRecord(entry_address, return_address); |
2109 | _jsr_records->append(record); |
2110 | return record; |
2111 | } |
2112 | |
2113 | // ------------------------------------------------------------------ |
2114 | // ciTypeFlow::flow_exceptions |
2115 | // |
2116 | // Merge the current state into all exceptional successors at the |
2117 | // current point in the code. |
2118 | void ciTypeFlow::flow_exceptions(GrowableArray<ciTypeFlow::Block*>* exceptions, |
2119 | GrowableArray<ciInstanceKlass*>* exc_klasses, |
2120 | ciTypeFlow::StateVector* state) { |
2121 | int len = exceptions->length(); |
2122 | assert(exc_klasses->length() == len, "must have same length")do { if (!(exc_klasses->length() == len)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2122, "assert(" "exc_klasses->length() == len" ") failed" , "must have same length"); ::breakpoint(); } } while (0); |
2123 | for (int i = 0; i < len; i++) { |
2124 | Block* block = exceptions->at(i); |
2125 | ciInstanceKlass* exception_klass = exc_klasses->at(i); |
2126 | |
2127 | if (!exception_klass->is_loaded()) { |
2128 | // Do not compile any code for unloaded exception types. |
2129 | // Following compiler passes are responsible for doing this also. |
2130 | continue; |
2131 | } |
2132 | |
2133 | if (block->meet_exception(exception_klass, state)) { |
2134 | // Block was modified and has PO. Add it to the work list. |
2135 | if (block->has_post_order() && |
2136 | !block->is_on_work_list()) { |
2137 | add_to_work_list(block); |
2138 | } |
2139 | } |
2140 | } |
2141 | } |
2142 | |
2143 | // ------------------------------------------------------------------ |
2144 | // ciTypeFlow::flow_successors |
2145 | // |
2146 | // Merge the current state into all successors at the current point |
2147 | // in the code. |
2148 | void ciTypeFlow::flow_successors(GrowableArray<ciTypeFlow::Block*>* successors, |
2149 | ciTypeFlow::StateVector* state) { |
2150 | int len = successors->length(); |
2151 | for (int i = 0; i < len; i++) { |
2152 | Block* block = successors->at(i); |
2153 | if (block->meet(state)) { |
2154 | // Block was modified and has PO. Add it to the work list. |
2155 | if (block->has_post_order() && |
2156 | !block->is_on_work_list()) { |
2157 | add_to_work_list(block); |
2158 | } |
2159 | } |
2160 | } |
2161 | } |
2162 | |
2163 | // ------------------------------------------------------------------ |
2164 | // ciTypeFlow::can_trap |
2165 | // |
2166 | // Tells if a given instruction is able to generate an exception edge. |
2167 | bool ciTypeFlow::can_trap(ciBytecodeStream& str) { |
2168 | // Cf. GenerateOopMap::do_exception_edge. |
2169 | if (!Bytecodes::can_trap(str.cur_bc())) return false; |
2170 | |
2171 | switch (str.cur_bc()) { |
2172 | // %%% FIXME: ldc of Class can generate an exception |
2173 | case Bytecodes::_ldc: |
2174 | case Bytecodes::_ldc_w: |
2175 | case Bytecodes::_ldc2_w: |
2176 | return str.is_unresolved_klass_in_error(); |
2177 | |
2178 | case Bytecodes::_aload_0: |
2179 | // These bytecodes can trap for rewriting. We need to assume that |
2180 | // they do not throw exceptions to make the monitor analysis work. |
2181 | return false; |
2182 | |
2183 | case Bytecodes::_ireturn: |
2184 | case Bytecodes::_lreturn: |
2185 | case Bytecodes::_freturn: |
2186 | case Bytecodes::_dreturn: |
2187 | case Bytecodes::_areturn: |
2188 | case Bytecodes::_return: |
2189 | // We can assume the monitor stack is empty in this analysis. |
2190 | return false; |
2191 | |
2192 | case Bytecodes::_monitorexit: |
2193 | // We can assume monitors are matched in this analysis. |
2194 | return false; |
2195 | |
2196 | default: |
2197 | return true; |
2198 | } |
2199 | } |
2200 | |
2201 | // ------------------------------------------------------------------ |
2202 | // ciTypeFlow::clone_loop_heads |
2203 | // |
2204 | // Clone the loop heads |
2205 | bool ciTypeFlow::clone_loop_heads(Loop* lp, StateVector* temp_vector, JsrSet* temp_set) { |
2206 | bool rslt = false; |
2207 | for (PreorderLoops iter(loop_tree_root()); !iter.done(); iter.next()) { |
2208 | lp = iter.current(); |
2209 | Block* head = lp->head(); |
2210 | if (lp == loop_tree_root() || |
2211 | lp->is_irreducible() || |
2212 | !head->is_clonable_exit(lp)) |
2213 | continue; |
2214 | |
2215 | // Avoid BoxLock merge. |
2216 | if (EliminateNestedLocks && head->has_monitorenter()) |
2217 | continue; |
2218 | |
2219 | // check not already cloned |
2220 | if (head->backedge_copy_count() != 0) |
2221 | continue; |
2222 | |
2223 | // Don't clone head of OSR loop to get correct types in start block. |
2224 | if (is_osr_flow() && head->start() == start_bci()) |
2225 | continue; |
2226 | |
2227 | // check _no_ shared head below us |
2228 | Loop* ch; |
2229 | for (ch = lp->child(); ch != NULL__null && ch->head() != head; ch = ch->sibling()); |
2230 | if (ch != NULL__null) |
2231 | continue; |
2232 | |
2233 | // Clone head |
2234 | Block* new_head = head->looping_succ(lp); |
2235 | Block* clone = clone_loop_head(lp, temp_vector, temp_set); |
2236 | // Update lp's info |
2237 | clone->set_loop(lp); |
2238 | lp->set_head(new_head); |
2239 | lp->set_tail(clone); |
2240 | // And move original head into outer loop |
2241 | head->set_loop(lp->parent()); |
2242 | |
2243 | rslt = true; |
2244 | } |
2245 | return rslt; |
2246 | } |
2247 | |
2248 | // ------------------------------------------------------------------ |
2249 | // ciTypeFlow::clone_loop_head |
2250 | // |
2251 | // Clone lp's head and replace tail's successors with clone. |
2252 | // |
2253 | // | |
2254 | // v |
2255 | // head <-> body |
2256 | // | |
2257 | // v |
2258 | // exit |
2259 | // |
2260 | // new_head |
2261 | // |
2262 | // | |
2263 | // v |
2264 | // head ----------\ |
2265 | // | | |
2266 | // | v |
2267 | // | clone <-> body |
2268 | // | | |
2269 | // | /--/ |
2270 | // | | |
2271 | // v v |
2272 | // exit |
2273 | // |
2274 | ciTypeFlow::Block* ciTypeFlow::clone_loop_head(Loop* lp, StateVector* temp_vector, JsrSet* temp_set) { |
2275 | Block* head = lp->head(); |
2276 | Block* tail = lp->tail(); |
2277 | if (CITraceTypeFlow) { |
2278 | tty->print(">> Requesting clone of loop head "); head->print_value_on(tty); |
2279 | tty->print(" for predecessor "); tail->print_value_on(tty); |
2280 | tty->cr(); |
2281 | } |
2282 | Block* clone = block_at(head->start(), head->jsrs(), create_backedge_copy); |
2283 | assert(clone->backedge_copy_count() == 1, "one backedge copy for all back edges")do { if (!(clone->backedge_copy_count() == 1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2283, "assert(" "clone->backedge_copy_count() == 1" ") failed" , "one backedge copy for all back edges"); ::breakpoint(); } } while (0); |
2284 | |
2285 | assert(!clone->has_pre_order(), "just created")do { if (!(!clone->has_pre_order())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2285, "assert(" "!clone->has_pre_order()" ") failed", "just created" ); ::breakpoint(); } } while (0); |
2286 | clone->set_next_pre_order(); |
2287 | |
2288 | // Insert clone after (orig) tail in reverse post order |
2289 | clone->set_rpo_next(tail->rpo_next()); |
2290 | tail->set_rpo_next(clone); |
2291 | |
2292 | // tail->head becomes tail->clone |
2293 | for (SuccIter iter(tail); !iter.done(); iter.next()) { |
2294 | if (iter.succ() == head) { |
2295 | iter.set_succ(clone); |
2296 | // Update predecessor information |
2297 | head->predecessors()->remove(tail); |
2298 | clone->predecessors()->append(tail); |
2299 | } |
2300 | } |
2301 | flow_block(tail, temp_vector, temp_set); |
2302 | if (head == tail) { |
2303 | // For self-loops, clone->head becomes clone->clone |
2304 | flow_block(clone, temp_vector, temp_set); |
2305 | for (SuccIter iter(clone); !iter.done(); iter.next()) { |
2306 | if (iter.succ() == head) { |
2307 | iter.set_succ(clone); |
2308 | // Update predecessor information |
2309 | head->predecessors()->remove(clone); |
2310 | clone->predecessors()->append(clone); |
2311 | break; |
2312 | } |
2313 | } |
2314 | } |
2315 | flow_block(clone, temp_vector, temp_set); |
2316 | |
2317 | return clone; |
2318 | } |
2319 | |
2320 | // ------------------------------------------------------------------ |
2321 | // ciTypeFlow::flow_block |
2322 | // |
2323 | // Interpret the effects of the bytecodes on the incoming state |
2324 | // vector of a basic block. Push the changed state to succeeding |
2325 | // basic blocks. |
2326 | void ciTypeFlow::flow_block(ciTypeFlow::Block* block, |
2327 | ciTypeFlow::StateVector* state, |
2328 | ciTypeFlow::JsrSet* jsrs) { |
2329 | if (CITraceTypeFlow) { |
2330 | tty->print("\n>> ANALYZING BLOCK : "); |
2331 | tty->cr(); |
2332 | block->print_on(tty); |
2333 | } |
2334 | assert(block->has_pre_order(), "pre-order is assigned before 1st flow")do { if (!(block->has_pre_order())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2334, "assert(" "block->has_pre_order()" ") failed", "pre-order is assigned before 1st flow" ); ::breakpoint(); } } while (0); |
2335 | |
2336 | int start = block->start(); |
2337 | int limit = block->limit(); |
2338 | int control = block->control(); |
2339 | if (control != ciBlock::fall_through_bci) { |
2340 | limit = control; |
2341 | } |
2342 | |
2343 | // Grab the state from the current block. |
2344 | block->copy_state_into(state); |
2345 | state->def_locals()->clear(); |
2346 | |
2347 | GrowableArray<Block*>* exceptions = block->exceptions(); |
2348 | GrowableArray<ciInstanceKlass*>* exc_klasses = block->exc_klasses(); |
2349 | bool has_exceptions = exceptions->length() > 0; |
2350 | |
2351 | bool exceptions_used = false; |
2352 | |
2353 | ciBytecodeStream str(method()); |
2354 | str.reset_to_bci(start); |
2355 | Bytecodes::Code code; |
2356 | while ((code = str.next()) != ciBytecodeStream::EOBC() && |
Although the value stored to 'code' is used in the enclosing expression, the value is never actually read from 'code' | |
2357 | str.cur_bci() < limit) { |
2358 | // Check for exceptional control flow from this point. |
2359 | if (has_exceptions && can_trap(str)) { |
2360 | flow_exceptions(exceptions, exc_klasses, state); |
2361 | exceptions_used = true; |
2362 | } |
2363 | // Apply the effects of the current bytecode to our state. |
2364 | bool res = state->apply_one_bytecode(&str); |
2365 | |
2366 | // Watch for bailouts. |
2367 | if (failing()) return; |
2368 | |
2369 | if (str.cur_bc() == Bytecodes::_monitorenter) { |
2370 | block->set_has_monitorenter(); |
2371 | } |
2372 | |
2373 | if (res) { |
2374 | |
2375 | // We have encountered a trap. Record it in this block. |
2376 | block->set_trap(state->trap_bci(), state->trap_index()); |
2377 | |
2378 | if (CITraceTypeFlow) { |
2379 | tty->print_cr(">> Found trap"); |
2380 | block->print_on(tty); |
2381 | } |
2382 | |
2383 | // Save set of locals defined in this block |
2384 | block->def_locals()->add(state->def_locals()); |
2385 | |
2386 | // Record (no) successors. |
2387 | block->successors(&str, state, jsrs); |
2388 | |
2389 | assert(!has_exceptions || exceptions_used, "Not removing exceptions")do { if (!(!has_exceptions || exceptions_used)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2389, "assert(" "!has_exceptions || exceptions_used" ") failed" , "Not removing exceptions"); ::breakpoint(); } } while (0); |
2390 | |
2391 | // Discontinue interpretation of this Block. |
2392 | return; |
2393 | } |
2394 | } |
2395 | |
2396 | GrowableArray<Block*>* successors = NULL__null; |
2397 | if (control != ciBlock::fall_through_bci) { |
2398 | // Check for exceptional control flow from this point. |
2399 | if (has_exceptions && can_trap(str)) { |
2400 | flow_exceptions(exceptions, exc_klasses, state); |
2401 | exceptions_used = true; |
2402 | } |
2403 | |
2404 | // Fix the JsrSet to reflect effect of the bytecode. |
2405 | block->copy_jsrs_into(jsrs); |
2406 | jsrs->apply_control(this, &str, state); |
2407 | |
2408 | // Find successor edges based on old state and new JsrSet. |
2409 | successors = block->successors(&str, state, jsrs); |
2410 | |
2411 | // Apply the control changes to the state. |
2412 | state->apply_one_bytecode(&str); |
2413 | } else { |
2414 | // Fall through control |
2415 | successors = block->successors(&str, NULL__null, NULL__null); |
2416 | } |
2417 | |
2418 | // Save set of locals defined in this block |
2419 | block->def_locals()->add(state->def_locals()); |
2420 | |
2421 | // Remove untaken exception paths |
2422 | if (!exceptions_used) |
2423 | exceptions->clear(); |
2424 | |
2425 | // Pass our state to successors. |
2426 | flow_successors(successors, state); |
2427 | } |
2428 | |
2429 | // ------------------------------------------------------------------ |
2430 | // ciTypeFlow::PreOrderLoops::next |
2431 | // |
2432 | // Advance to next loop tree using a preorder, left-to-right traversal. |
2433 | void ciTypeFlow::PreorderLoops::next() { |
2434 | assert(!done(), "must not be done.")do { if (!(!done())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2434, "assert(" "!done()" ") failed", "must not be done."); ::breakpoint(); } } while (0); |
2435 | if (_current->child() != NULL__null) { |
2436 | _current = _current->child(); |
2437 | } else if (_current->sibling() != NULL__null) { |
2438 | _current = _current->sibling(); |
2439 | } else { |
2440 | while (_current != _root && _current->sibling() == NULL__null) { |
2441 | _current = _current->parent(); |
2442 | } |
2443 | if (_current == _root) { |
2444 | _current = NULL__null; |
2445 | assert(done(), "must be done.")do { if (!(done())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2445, "assert(" "done()" ") failed", "must be done."); ::breakpoint (); } } while (0); |
2446 | } else { |
2447 | assert(_current->sibling() != NULL, "must be more to do")do { if (!(_current->sibling() != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2447, "assert(" "_current->sibling() != __null" ") failed" , "must be more to do"); ::breakpoint(); } } while (0); |
2448 | _current = _current->sibling(); |
2449 | } |
2450 | } |
2451 | } |
2452 | |
2453 | // ------------------------------------------------------------------ |
2454 | // ciTypeFlow::Loop::sorted_merge |
2455 | // |
2456 | // Merge the branch lp into this branch, sorting on the loop head |
2457 | // pre_orders. Returns the leaf of the merged branch. |
2458 | // Child and sibling pointers will be setup later. |
2459 | // Sort is (looking from leaf towards the root) |
2460 | // descending on primary key: loop head's pre_order, and |
2461 | // ascending on secondary key: loop tail's pre_order. |
2462 | ciTypeFlow::Loop* ciTypeFlow::Loop::sorted_merge(Loop* lp) { |
2463 | Loop* leaf = this; |
2464 | Loop* prev = NULL__null; |
2465 | Loop* current = leaf; |
2466 | while (lp != NULL__null) { |
2467 | int lp_pre_order = lp->head()->pre_order(); |
2468 | // Find insertion point for "lp" |
2469 | while (current != NULL__null) { |
2470 | if (current == lp) |
2471 | return leaf; // Already in list |
2472 | if (current->head()->pre_order() < lp_pre_order) |
2473 | break; |
2474 | if (current->head()->pre_order() == lp_pre_order && |
2475 | current->tail()->pre_order() > lp->tail()->pre_order()) { |
2476 | break; |
2477 | } |
2478 | prev = current; |
2479 | current = current->parent(); |
2480 | } |
2481 | Loop* next_lp = lp->parent(); // Save future list of items to insert |
2482 | // Insert lp before current |
2483 | lp->set_parent(current); |
2484 | if (prev != NULL__null) { |
2485 | prev->set_parent(lp); |
2486 | } else { |
2487 | leaf = lp; |
2488 | } |
2489 | prev = lp; // Inserted item is new prev[ious] |
2490 | lp = next_lp; // Next item to insert |
2491 | } |
2492 | return leaf; |
2493 | } |
2494 | |
2495 | // ------------------------------------------------------------------ |
2496 | // ciTypeFlow::build_loop_tree |
2497 | // |
2498 | // Incrementally build loop tree. |
2499 | void ciTypeFlow::build_loop_tree(Block* blk) { |
2500 | assert(!blk->is_post_visited(), "precondition")do { if (!(!blk->is_post_visited())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2500, "assert(" "!blk->is_post_visited()" ") failed", "precondition" ); ::breakpoint(); } } while (0); |
2501 | Loop* innermost = NULL__null; // merge of loop tree branches over all successors |
2502 | |
2503 | for (SuccIter iter(blk); !iter.done(); iter.next()) { |
2504 | Loop* lp = NULL__null; |
2505 | Block* succ = iter.succ(); |
2506 | if (!succ->is_post_visited()) { |
2507 | // Found backedge since predecessor post visited, but successor is not |
2508 | assert(succ->pre_order() <= blk->pre_order(), "should be backedge")do { if (!(succ->pre_order() <= blk->pre_order())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2508, "assert(" "succ->pre_order() <= blk->pre_order()" ") failed", "should be backedge"); ::breakpoint(); } } while (0); |
2509 | |
2510 | // Create a LoopNode to mark this loop. |
2511 | lp = new (arena()) Loop(succ, blk); |
2512 | if (succ->loop() == NULL__null) |
2513 | succ->set_loop(lp); |
2514 | // succ->loop will be updated to innermost loop on a later call, when blk==succ |
2515 | |
2516 | } else { // Nested loop |
2517 | lp = succ->loop(); |
2518 | |
2519 | // If succ is loop head, find outer loop. |
2520 | while (lp != NULL__null && lp->head() == succ) { |
2521 | lp = lp->parent(); |
2522 | } |
2523 | if (lp == NULL__null) { |
2524 | // Infinite loop, it's parent is the root |
2525 | lp = loop_tree_root(); |
2526 | } |
2527 | } |
2528 | |
2529 | // Check for irreducible loop. |
2530 | // Successor has already been visited. If the successor's loop head |
2531 | // has already been post-visited, then this is another entry into the loop. |
2532 | while (lp->head()->is_post_visited() && lp != loop_tree_root()) { |
2533 | _has_irreducible_entry = true; |
2534 | lp->set_irreducible(succ); |
2535 | if (!succ->is_on_work_list()) { |
2536 | // Assume irreducible entries need more data flow |
2537 | add_to_work_list(succ); |
2538 | } |
2539 | Loop* plp = lp->parent(); |
2540 | if (plp == NULL__null) { |
2541 | // This only happens for some irreducible cases. The parent |
2542 | // will be updated during a later pass. |
2543 | break; |
2544 | } |
2545 | lp = plp; |
2546 | } |
2547 | |
2548 | // Merge loop tree branch for all successors. |
2549 | innermost = innermost == NULL__null ? lp : innermost->sorted_merge(lp); |
2550 | |
2551 | } // end loop |
2552 | |
2553 | if (innermost == NULL__null) { |
2554 | assert(blk->successors()->length() == 0, "CFG exit")do { if (!(blk->successors()->length() == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2554, "assert(" "blk->successors()->length() == 0" ") failed" , "CFG exit"); ::breakpoint(); } } while (0); |
2555 | blk->set_loop(loop_tree_root()); |
2556 | } else if (innermost->head() == blk) { |
2557 | // If loop header, complete the tree pointers |
2558 | if (blk->loop() != innermost) { |
2559 | #ifdef ASSERT1 |
2560 | assert(blk->loop()->head() == innermost->head(), "same head")do { if (!(blk->loop()->head() == innermost->head()) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2560, "assert(" "blk->loop()->head() == innermost->head()" ") failed", "same head"); ::breakpoint(); } } while (0); |
2561 | Loop* dl; |
2562 | for (dl = innermost; dl != NULL__null && dl != blk->loop(); dl = dl->parent()); |
2563 | assert(dl == blk->loop(), "blk->loop() already in innermost list")do { if (!(dl == blk->loop())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2563, "assert(" "dl == blk->loop()" ") failed", "blk->loop() already in innermost list" ); ::breakpoint(); } } while (0); |
2564 | #endif |
2565 | blk->set_loop(innermost); |
2566 | } |
2567 | innermost->def_locals()->add(blk->def_locals()); |
2568 | Loop* l = innermost; |
2569 | Loop* p = l->parent(); |
2570 | while (p && l->head() == blk) { |
2571 | l->set_sibling(p->child()); // Put self on parents 'next child' |
2572 | p->set_child(l); // Make self the first child of parent |
2573 | p->def_locals()->add(l->def_locals()); |
2574 | l = p; // Walk up the parent chain |
2575 | p = l->parent(); |
2576 | } |
2577 | } else { |
2578 | blk->set_loop(innermost); |
2579 | innermost->def_locals()->add(blk->def_locals()); |
2580 | } |
2581 | } |
2582 | |
2583 | // ------------------------------------------------------------------ |
2584 | // ciTypeFlow::Loop::contains |
2585 | // |
2586 | // Returns true if lp is nested loop. |
2587 | bool ciTypeFlow::Loop::contains(ciTypeFlow::Loop* lp) const { |
2588 | assert(lp != NULL, "")do { if (!(lp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2588, "assert(" "lp != __null" ") failed", ""); ::breakpoint (); } } while (0); |
2589 | if (this == lp || head() == lp->head()) return true; |
2590 | int depth1 = depth(); |
2591 | int depth2 = lp->depth(); |
2592 | if (depth1 > depth2) |
2593 | return false; |
2594 | while (depth1 < depth2) { |
2595 | depth2--; |
2596 | lp = lp->parent(); |
2597 | } |
2598 | return this == lp; |
2599 | } |
2600 | |
2601 | // ------------------------------------------------------------------ |
2602 | // ciTypeFlow::Loop::depth |
2603 | // |
2604 | // Loop depth |
2605 | int ciTypeFlow::Loop::depth() const { |
2606 | int dp = 0; |
2607 | for (Loop* lp = this->parent(); lp != NULL__null; lp = lp->parent()) |
2608 | dp++; |
2609 | return dp; |
2610 | } |
2611 | |
2612 | #ifndef PRODUCT |
2613 | // ------------------------------------------------------------------ |
2614 | // ciTypeFlow::Loop::print |
2615 | void ciTypeFlow::Loop::print(outputStream* st, int indent) const { |
2616 | for (int i = 0; i < indent; i++) st->print(" "); |
2617 | st->print("%d<-%d %s", |
2618 | is_root() ? 0 : this->head()->pre_order(), |
2619 | is_root() ? 0 : this->tail()->pre_order(), |
2620 | is_irreducible()?" irr":""); |
2621 | st->print(" defs: "); |
2622 | def_locals()->print_on(st, _head->outer()->method()->max_locals()); |
2623 | st->cr(); |
2624 | for (Loop* ch = child(); ch != NULL__null; ch = ch->sibling()) |
2625 | ch->print(st, indent+2); |
2626 | } |
2627 | #endif |
2628 | |
2629 | // ------------------------------------------------------------------ |
2630 | // ciTypeFlow::df_flow_types |
2631 | // |
2632 | // Perform the depth first type flow analysis. Helper for flow_types. |
2633 | void ciTypeFlow::df_flow_types(Block* start, |
2634 | bool do_flow, |
2635 | StateVector* temp_vector, |
2636 | JsrSet* temp_set) { |
2637 | int dft_len = 100; |
2638 | GrowableArray<Block*> stk(dft_len); |
2639 | |
2640 | ciBlock* dummy = _method->get_method_blocks()->make_dummy_block(); |
2641 | JsrSet* root_set = new JsrSet(0); |
2642 | Block* root_head = new (arena()) Block(this, dummy, root_set); |
2643 | Block* root_tail = new (arena()) Block(this, dummy, root_set); |
2644 | root_head->set_pre_order(0); |
2645 | root_head->set_post_order(0); |
2646 | root_tail->set_pre_order(max_jint); |
2647 | root_tail->set_post_order(max_jint); |
2648 | set_loop_tree_root(new (arena()) Loop(root_head, root_tail)); |
2649 | |
2650 | stk.push(start); |
2651 | |
2652 | _next_pre_order = 0; // initialize pre_order counter |
2653 | _rpo_list = NULL__null; |
2654 | int next_po = 0; // initialize post_order counter |
2655 | |
2656 | // Compute RPO and the control flow graph |
2657 | int size; |
2658 | while ((size = stk.length()) > 0) { |
2659 | Block* blk = stk.top(); // Leave node on stack |
2660 | if (!blk->is_visited()) { |
2661 | // forward arc in graph |
2662 | assert (!blk->has_pre_order(), "")do { if (!(!blk->has_pre_order())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2662, "assert(" "!blk->has_pre_order()" ") failed", ""); ::breakpoint(); } } while (0); |
2663 | blk->set_next_pre_order(); |
2664 | |
2665 | if (_next_pre_order >= (int)Compile::current()->max_node_limit() / 2) { |
2666 | // Too many basic blocks. Bail out. |
2667 | // This can happen when try/finally constructs are nested to depth N, |
2668 | // and there is O(2**N) cloning of jsr bodies. See bug 4697245! |
2669 | // "MaxNodeLimit / 2" is used because probably the parser will |
2670 | // generate at least twice that many nodes and bail out. |
2671 | record_failure("too many basic blocks"); |
2672 | return; |
2673 | } |
2674 | if (do_flow) { |
2675 | flow_block(blk, temp_vector, temp_set); |
2676 | if (failing()) return; // Watch for bailouts. |
2677 | } |
2678 | } else if (!blk->is_post_visited()) { |
2679 | // cross or back arc |
2680 | for (SuccIter iter(blk); !iter.done(); iter.next()) { |
2681 | Block* succ = iter.succ(); |
2682 | if (!succ->is_visited()) { |
2683 | stk.push(succ); |
2684 | } |
2685 | } |
2686 | if (stk.length() == size) { |
2687 | // There were no additional children, post visit node now |
2688 | stk.pop(); // Remove node from stack |
2689 | |
2690 | build_loop_tree(blk); |
2691 | blk->set_post_order(next_po++); // Assign post order |
2692 | prepend_to_rpo_list(blk); |
2693 | assert(blk->is_post_visited(), "")do { if (!(blk->is_post_visited())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2693, "assert(" "blk->is_post_visited()" ") failed", "") ; ::breakpoint(); } } while (0); |
2694 | |
2695 | if (blk->is_loop_head() && !blk->is_on_work_list()) { |
2696 | // Assume loop heads need more data flow |
2697 | add_to_work_list(blk); |
2698 | } |
2699 | } |
2700 | } else { |
2701 | stk.pop(); // Remove post-visited node from stack |
2702 | } |
2703 | } |
2704 | } |
2705 | |
2706 | // ------------------------------------------------------------------ |
2707 | // ciTypeFlow::flow_types |
2708 | // |
2709 | // Perform the type flow analysis, creating and cloning Blocks as |
2710 | // necessary. |
2711 | void ciTypeFlow::flow_types() { |
2712 | ResourceMark rm; |
2713 | StateVector* temp_vector = new StateVector(this); |
2714 | JsrSet* temp_set = new JsrSet(4); |
2715 | |
2716 | // Create the method entry block. |
2717 | Block* start = block_at(start_bci(), temp_set); |
2718 | |
2719 | // Load the initial state into it. |
2720 | const StateVector* start_state = get_start_state(); |
2721 | if (failing()) return; |
2722 | start->meet(start_state); |
2723 | |
2724 | // Depth first visit |
2725 | df_flow_types(start, true /*do flow*/, temp_vector, temp_set); |
2726 | |
2727 | if (failing()) return; |
2728 | assert(_rpo_list == start, "must be start")do { if (!(_rpo_list == start)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2728, "assert(" "_rpo_list == start" ") failed", "must be start" ); ::breakpoint(); } } while (0); |
2729 | |
2730 | // Any loops found? |
2731 | if (loop_tree_root()->child() != NULL__null && |
2732 | env()->comp_level() >= CompLevel_full_optimization) { |
2733 | // Loop optimizations are not performed on Tier1 compiles. |
2734 | |
2735 | bool changed = clone_loop_heads(loop_tree_root(), temp_vector, temp_set); |
2736 | |
2737 | // If some loop heads were cloned, recompute postorder and loop tree |
2738 | if (changed) { |
2739 | loop_tree_root()->set_child(NULL__null); |
2740 | for (Block* blk = _rpo_list; blk != NULL__null;) { |
2741 | Block* next = blk->rpo_next(); |
2742 | blk->df_init(); |
2743 | blk = next; |
2744 | } |
2745 | df_flow_types(start, false /*no flow*/, temp_vector, temp_set); |
2746 | } |
2747 | } |
2748 | |
2749 | if (CITraceTypeFlow) { |
2750 | tty->print_cr("\nLoop tree"); |
2751 | loop_tree_root()->print(); |
2752 | } |
2753 | |
2754 | // Continue flow analysis until fixed point reached |
2755 | |
2756 | debug_only(int max_block = _next_pre_order;)int max_block = _next_pre_order; |
2757 | |
2758 | while (!work_list_empty()) { |
2759 | Block* blk = work_list_next(); |
2760 | assert (blk->has_post_order(), "post order assigned above")do { if (!(blk->has_post_order())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2760, "assert(" "blk->has_post_order()" ") failed", "post order assigned above" ); ::breakpoint(); } } while (0); |
2761 | |
2762 | flow_block(blk, temp_vector, temp_set); |
2763 | |
2764 | assert (max_block == _next_pre_order, "no new blocks")do { if (!(max_block == _next_pre_order)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2764, "assert(" "max_block == _next_pre_order" ") failed", "no new blocks" ); ::breakpoint(); } } while (0); |
2765 | assert (!failing(), "no more bailouts")do { if (!(!failing())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2765, "assert(" "!failing()" ") failed", "no more bailouts" ); ::breakpoint(); } } while (0); |
2766 | } |
2767 | } |
2768 | |
2769 | // ------------------------------------------------------------------ |
2770 | // ciTypeFlow::map_blocks |
2771 | // |
2772 | // Create the block map, which indexes blocks in reverse post-order. |
2773 | void ciTypeFlow::map_blocks() { |
2774 | assert(_block_map == NULL, "single initialization")do { if (!(_block_map == __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2774, "assert(" "_block_map == __null" ") failed", "single initialization" ); ::breakpoint(); } } while (0); |
2775 | int block_ct = _next_pre_order; |
2776 | _block_map = NEW_ARENA_ARRAY(arena(), Block*, block_ct)(Block**) (arena())->Amalloc((block_ct) * sizeof(Block*)); |
2777 | assert(block_ct == block_count(), "")do { if (!(block_ct == block_count())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2777, "assert(" "block_ct == block_count()" ") failed", "") ; ::breakpoint(); } } while (0); |
2778 | |
2779 | Block* blk = _rpo_list; |
2780 | for (int m = 0; m < block_ct; m++) { |
2781 | int rpo = blk->rpo(); |
2782 | assert(rpo == m, "should be sequential")do { if (!(rpo == m)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2782, "assert(" "rpo == m" ") failed", "should be sequential" ); ::breakpoint(); } } while (0); |
2783 | _block_map[rpo] = blk; |
2784 | blk = blk->rpo_next(); |
2785 | } |
2786 | assert(blk == NULL, "should be done")do { if (!(blk == __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2786, "assert(" "blk == __null" ") failed", "should be done" ); ::breakpoint(); } } while (0); |
2787 | |
2788 | for (int j = 0; j < block_ct; j++) { |
2789 | assert(_block_map[j] != NULL, "must not drop any blocks")do { if (!(_block_map[j] != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2789, "assert(" "_block_map[j] != __null" ") failed", "must not drop any blocks" ); ::breakpoint(); } } while (0); |
2790 | Block* block = _block_map[j]; |
2791 | // Remove dead blocks from successor lists: |
2792 | for (int e = 0; e <= 1; e++) { |
2793 | GrowableArray<Block*>* l = e? block->exceptions(): block->successors(); |
2794 | for (int k = 0; k < l->length(); k++) { |
2795 | Block* s = l->at(k); |
2796 | if (!s->has_post_order()) { |
2797 | if (CITraceTypeFlow) { |
2798 | tty->print("Removing dead %s successor of #%d: ", (e? "exceptional": "normal"), block->pre_order()); |
2799 | s->print_value_on(tty); |
2800 | tty->cr(); |
2801 | } |
2802 | l->remove(s); |
2803 | --k; |
2804 | } |
2805 | } |
2806 | } |
2807 | } |
2808 | } |
2809 | |
2810 | // ------------------------------------------------------------------ |
2811 | // ciTypeFlow::get_block_for |
2812 | // |
2813 | // Find a block with this ciBlock which has a compatible JsrSet. |
2814 | // If no such block exists, create it, unless the option is no_create. |
2815 | // If the option is create_backedge_copy, always create a fresh backedge copy. |
2816 | ciTypeFlow::Block* ciTypeFlow::get_block_for(int ciBlockIndex, ciTypeFlow::JsrSet* jsrs, CreateOption option) { |
2817 | Arena* a = arena(); |
2818 | GrowableArray<Block*>* blocks = _idx_to_blocklist[ciBlockIndex]; |
2819 | if (blocks == NULL__null) { |
2820 | // Query only? |
2821 | if (option == no_create) return NULL__null; |
2822 | |
2823 | // Allocate the growable array. |
2824 | blocks = new (a) GrowableArray<Block*>(a, 4, 0, NULL__null); |
2825 | _idx_to_blocklist[ciBlockIndex] = blocks; |
2826 | } |
2827 | |
2828 | if (option != create_backedge_copy) { |
2829 | int len = blocks->length(); |
2830 | for (int i = 0; i < len; i++) { |
2831 | Block* block = blocks->at(i); |
2832 | if (!block->is_backedge_copy() && block->is_compatible_with(jsrs)) { |
2833 | return block; |
2834 | } |
2835 | } |
2836 | } |
2837 | |
2838 | // Query only? |
2839 | if (option == no_create) return NULL__null; |
2840 | |
2841 | // We did not find a compatible block. Create one. |
2842 | Block* new_block = new (a) Block(this, _method->get_method_blocks()->block(ciBlockIndex), jsrs); |
2843 | if (option == create_backedge_copy) new_block->set_backedge_copy(true); |
2844 | blocks->append(new_block); |
2845 | return new_block; |
2846 | } |
2847 | |
2848 | // ------------------------------------------------------------------ |
2849 | // ciTypeFlow::backedge_copy_count |
2850 | // |
2851 | int ciTypeFlow::backedge_copy_count(int ciBlockIndex, ciTypeFlow::JsrSet* jsrs) const { |
2852 | GrowableArray<Block*>* blocks = _idx_to_blocklist[ciBlockIndex]; |
2853 | |
2854 | if (blocks == NULL__null) { |
2855 | return 0; |
2856 | } |
2857 | |
2858 | int count = 0; |
2859 | int len = blocks->length(); |
2860 | for (int i = 0; i < len; i++) { |
2861 | Block* block = blocks->at(i); |
2862 | if (block->is_backedge_copy() && block->is_compatible_with(jsrs)) { |
2863 | count++; |
2864 | } |
2865 | } |
2866 | |
2867 | return count; |
2868 | } |
2869 | |
2870 | // ------------------------------------------------------------------ |
2871 | // ciTypeFlow::do_flow |
2872 | // |
2873 | // Perform type inference flow analysis. |
2874 | void ciTypeFlow::do_flow() { |
2875 | if (CITraceTypeFlow) { |
2876 | tty->print_cr("\nPerforming flow analysis on method"); |
2877 | method()->print(); |
2878 | if (is_osr_flow()) tty->print(" at OSR bci %d", start_bci()); |
2879 | tty->cr(); |
2880 | method()->print_codes(); |
2881 | } |
2882 | if (CITraceTypeFlow) { |
2883 | tty->print_cr("Initial CI Blocks"); |
2884 | print_on(tty); |
2885 | } |
2886 | flow_types(); |
2887 | // Watch for bailouts. |
2888 | if (failing()) { |
2889 | return; |
2890 | } |
2891 | |
2892 | map_blocks(); |
2893 | |
2894 | if (CIPrintTypeFlow || CITraceTypeFlow) { |
2895 | rpo_print_on(tty); |
2896 | } |
2897 | } |
2898 | |
2899 | // ------------------------------------------------------------------ |
2900 | // ciTypeFlow::is_dominated_by |
2901 | // |
2902 | // Determine if the instruction at bci is dominated by the instruction at dom_bci. |
2903 | bool ciTypeFlow::is_dominated_by(int bci, int dom_bci) { |
2904 | assert(!method()->has_jsrs(), "jsrs are not supported")do { if (!(!method()->has_jsrs())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciTypeFlow.cpp" , 2904, "assert(" "!method()->has_jsrs()" ") failed", "jsrs are not supported" ); ::breakpoint(); } } while (0); |
2905 | |
2906 | ResourceMark rm; |
2907 | JsrSet* jsrs = new ciTypeFlow::JsrSet(); |
2908 | int index = _method->get_method_blocks()->block_containing(bci)->index(); |
2909 | int dom_index = _method->get_method_blocks()->block_containing(dom_bci)->index(); |
2910 | Block* block = get_block_for(index, jsrs, ciTypeFlow::no_create); |
2911 | Block* dom_block = get_block_for(dom_index, jsrs, ciTypeFlow::no_create); |
2912 | |
2913 | // Start block dominates all other blocks |
2914 | if (start_block()->rpo() == dom_block->rpo()) { |
2915 | return true; |
2916 | } |
2917 | |
2918 | // Dominated[i] is true if block i is dominated by dom_block |
2919 | int num_blocks = block_count(); |
2920 | bool* dominated = NEW_RESOURCE_ARRAY(bool, num_blocks)(bool*) resource_allocate_bytes((num_blocks) * sizeof(bool)); |
2921 | for (int i = 0; i < num_blocks; ++i) { |
2922 | dominated[i] = true; |
2923 | } |
2924 | dominated[start_block()->rpo()] = false; |
2925 | |
2926 | // Iterative dominator algorithm |
2927 | bool changed = true; |
2928 | while (changed) { |
2929 | changed = false; |
2930 | // Use reverse postorder iteration |
2931 | for (Block* blk = _rpo_list; blk != NULL__null; blk = blk->rpo_next()) { |
2932 | if (blk->is_start()) { |
2933 | // Ignore start block |
2934 | continue; |
2935 | } |
2936 | // The block is dominated if it is the dominating block |
2937 | // itself or if all predecessors are dominated. |
2938 | int index = blk->rpo(); |
2939 | bool dom = (index == dom_block->rpo()); |
2940 | if (!dom) { |
2941 | // Check if all predecessors are dominated |
2942 | dom = true; |
2943 | for (int i = 0; i < blk->predecessors()->length(); ++i) { |
2944 | Block* pred = blk->predecessors()->at(i); |
2945 | if (!dominated[pred->rpo()]) { |
2946 | dom = false; |
2947 | break; |
2948 | } |
2949 | } |
2950 | } |
2951 | // Update dominator information |
2952 | if (dominated[index] != dom) { |
2953 | changed = true; |
2954 | dominated[index] = dom; |
2955 | } |
2956 | } |
2957 | } |
2958 | // block dominated by dom_block? |
2959 | return dominated[block->rpo()]; |
2960 | } |
2961 | |
2962 | // ------------------------------------------------------------------ |
2963 | // ciTypeFlow::record_failure() |
2964 | // The ciTypeFlow object keeps track of failure reasons separately from the ciEnv. |
2965 | // This is required because there is not a 1-1 relation between the ciEnv and |
2966 | // the TypeFlow passes within a compilation task. For example, if the compiler |
2967 | // is considering inlining a method, it will request a TypeFlow. If that fails, |
2968 | // the compilation as a whole may continue without the inlining. Some TypeFlow |
2969 | // requests are not optional; if they fail the requestor is responsible for |
2970 | // copying the failure reason up to the ciEnv. (See Parse::Parse.) |
2971 | void ciTypeFlow::record_failure(const char* reason) { |
2972 | if (env()->log() != NULL__null) { |
2973 | env()->log()->elem("failure reason='%s' phase='typeflow'", reason); |
2974 | } |
2975 | if (_failure_reason == NULL__null) { |
2976 | // Record the first failure reason. |
2977 | _failure_reason = reason; |
2978 | } |
2979 | } |
2980 | |
2981 | #ifndef PRODUCT |
2982 | // ------------------------------------------------------------------ |
2983 | // ciTypeFlow::print_on |
2984 | void ciTypeFlow::print_on(outputStream* st) const { |
2985 | // Walk through CI blocks |
2986 | st->print_cr("********************************************************"); |
2987 | st->print ("TypeFlow for "); |
2988 | method()->name()->print_symbol_on(st); |
2989 | int limit_bci = code_size(); |
2990 | st->print_cr(" %d bytes", limit_bci); |
2991 | ciMethodBlocks* mblks = _method->get_method_blocks(); |
2992 | ciBlock* current = NULL__null; |
2993 | for (int bci = 0; bci < limit_bci; bci++) { |
2994 | ciBlock* blk = mblks->block_containing(bci); |
2995 | if (blk != NULL__null && blk != current) { |
2996 | current = blk; |
2997 | current->print_on(st); |
2998 | |
2999 | GrowableArray<Block*>* blocks = _idx_to_blocklist[blk->index()]; |
3000 | int num_blocks = (blocks == NULL__null) ? 0 : blocks->length(); |
3001 | |
3002 | if (num_blocks == 0) { |
3003 | st->print_cr(" No Blocks"); |
3004 | } else { |
3005 | for (int i = 0; i < num_blocks; i++) { |
3006 | Block* block = blocks->at(i); |
3007 | block->print_on(st); |
3008 | } |
3009 | } |
3010 | st->print_cr("--------------------------------------------------------"); |
3011 | st->cr(); |
3012 | } |
3013 | } |
3014 | st->print_cr("********************************************************"); |
3015 | st->cr(); |
3016 | } |
3017 | |
3018 | void ciTypeFlow::rpo_print_on(outputStream* st) const { |
3019 | st->print_cr("********************************************************"); |
3020 | st->print ("TypeFlow for "); |
3021 | method()->name()->print_symbol_on(st); |
3022 | int limit_bci = code_size(); |
3023 | st->print_cr(" %d bytes", limit_bci); |
3024 | for (Block* blk = _rpo_list; blk != NULL__null; blk = blk->rpo_next()) { |
3025 | blk->print_on(st); |
3026 | st->print_cr("--------------------------------------------------------"); |
3027 | st->cr(); |
3028 | } |
3029 | st->print_cr("********************************************************"); |
3030 | st->cr(); |
3031 | } |
3032 | #endif |