File: | jdk/src/hotspot/share/ci/ciTypeFlow.cpp |
Warning: | line 1781, column 25 Called C++ object pointer is null |
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() && | ||||||
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 |
1 | /* |
2 | * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #ifndef SHARE_CI_CISTREAMS_HPP |
26 | #define SHARE_CI_CISTREAMS_HPP |
27 | |
28 | #include "ci/ciClassList.hpp" |
29 | #include "ci/ciExceptionHandler.hpp" |
30 | #include "ci/ciInstanceKlass.hpp" |
31 | #include "ci/ciMethod.hpp" |
32 | #include "interpreter/bytecode.hpp" |
33 | |
34 | // ciBytecodeStream |
35 | // |
36 | // The class is used to iterate over the bytecodes of a method. |
37 | // It hides the details of constant pool structure/access by |
38 | // providing accessors for constant pool items. It returns only pure |
39 | // Java bytecodes; VM-internal _fast bytecodes are translated back to |
40 | // their original form during iteration. |
41 | class ciBytecodeStream : StackObj { |
42 | private: |
43 | // Handling for the weird bytecodes |
44 | Bytecodes::Code next_wide_or_table(Bytecodes::Code); // Handle _wide & complicated inline table |
45 | |
46 | static Bytecodes::Code check_java(Bytecodes::Code c) { |
47 | assert(Bytecodes::is_java_code(c), "should not return _fast bytecodes")do { if (!(Bytecodes::is_java_code(c))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciStreams.hpp" , 47, "assert(" "Bytecodes::is_java_code(c)" ") failed", "should not return _fast bytecodes" ); ::breakpoint(); } } while (0); |
48 | return c; |
49 | } |
50 | |
51 | static Bytecodes::Code check_defined(Bytecodes::Code c) { |
52 | assert(Bytecodes::is_defined(c), "")do { if (!(Bytecodes::is_defined(c))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciStreams.hpp" , 52, "assert(" "Bytecodes::is_defined(c)" ") failed", ""); :: breakpoint(); } } while (0); |
53 | return c; |
54 | } |
55 | |
56 | ciMethod* _method; // the method |
57 | ciInstanceKlass* _holder; |
58 | address _bc_start; // Start of current bytecode for table |
59 | address _was_wide; // Address past last wide bytecode |
60 | jint* _table_base; // Aligned start of last table or switch |
61 | |
62 | address _start; // Start of bytecodes |
63 | address _end; // Past end of bytecodes |
64 | address _pc; // Current PC |
65 | Bytecodes::Code _bc; // Current bytecode |
66 | Bytecodes::Code _raw_bc; // Current bytecode, raw form |
67 | |
68 | void reset( address base, unsigned int size ) { |
69 | _bc_start =_was_wide = 0; |
70 | _start = _pc = base; _end = base + size; |
71 | } |
72 | |
73 | Bytecode bytecode() const { return Bytecode(this, _bc_start); } |
74 | Bytecode next_bytecode() const { return Bytecode(this, _pc); } |
75 | |
76 | public: |
77 | // End-Of-Bytecodes |
78 | static Bytecodes::Code EOBC() { |
79 | return Bytecodes::_illegal; |
80 | } |
81 | |
82 | ciBytecodeStream(ciMethod* m) { |
83 | reset_to_method(m); |
84 | } |
85 | |
86 | ciBytecodeStream() { |
87 | reset_to_method(NULL__null); |
88 | } |
89 | |
90 | ciMethod* method() const { return _method; } |
91 | |
92 | void reset_to_method(ciMethod* m) { |
93 | _method = m; |
94 | if (m == NULL__null) { |
95 | _holder = NULL__null; |
96 | reset(NULL__null, 0); |
97 | } else { |
98 | _holder = m->holder(); |
99 | reset(m->code(), m->code_size()); |
100 | } |
101 | } |
102 | |
103 | void reset_to_bci( int bci ); |
104 | |
105 | // Force the iterator to report a certain bci. |
106 | void force_bci(int bci); |
107 | |
108 | void set_max_bci( int max ) { |
109 | _end = _start + max; |
110 | } |
111 | |
112 | address cur_bcp() const { return _bc_start; } // Returns bcp to current instruction |
113 | int next_bci() const { return _pc - _start; } |
114 | int cur_bci() const { return _bc_start - _start; } |
115 | int instruction_size() const { return _pc - _bc_start; } |
116 | |
117 | Bytecodes::Code cur_bc() const{ return check_java(_bc); } |
118 | Bytecodes::Code cur_bc_raw() const { return check_defined(_raw_bc); } |
119 | Bytecodes::Code next_bc() { return Bytecodes::java_code((Bytecodes::Code)* _pc); } |
120 | |
121 | // Return current ByteCode and increment PC to next bytecode, skipping all |
122 | // intermediate constants. Returns EOBC at end. |
123 | // Expected usage: |
124 | // ciBytecodeStream iter(m); |
125 | // while (iter.next() != ciBytecodeStream::EOBC()) { ... } |
126 | Bytecodes::Code next() { |
127 | _bc_start = _pc; // Capture start of bc |
128 | if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes |
129 | |
130 | // Fetch Java bytecode |
131 | // All rewritten bytecodes maintain the size of original bytecode. |
132 | _bc = Bytecodes::java_code(_raw_bc = (Bytecodes::Code)*_pc); |
133 | int csize = Bytecodes::length_for(_bc); // Expected size |
134 | _pc += csize; // Bump PC past bytecode |
135 | if (csize == 0) { |
136 | _bc = next_wide_or_table(_bc); |
137 | } |
138 | return check_java(_bc); |
139 | } |
140 | |
141 | bool is_wide() const { return ( _pc == _was_wide ); } |
142 | |
143 | // Does this instruction contain an index which refes into the CP cache? |
144 | bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); } |
145 | |
146 | int get_index_u1() const { |
147 | return bytecode().get_index_u1(cur_bc_raw()); |
148 | } |
149 | |
150 | // Get a byte index following this bytecode. |
151 | // If prefixed with a wide bytecode, get a wide index. |
152 | int get_index() const { |
153 | assert(!has_cache_index(), "else use cpcache variant")do { if (!(!has_cache_index())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciStreams.hpp" , 153, "assert(" "!has_cache_index()" ") failed", "else use cpcache variant" ); ::breakpoint(); } } while (0); |
154 | return (_pc == _was_wide) // was widened? |
155 | ? get_index_u2(true) // yes, return wide index |
156 | : get_index_u1(); // no, return narrow index |
157 | } |
158 | |
159 | // Get 2-byte index (byte swapping depending on which bytecode) |
160 | int get_index_u2(bool is_wide = false) const { |
161 | return bytecode().get_index_u2(cur_bc_raw(), is_wide); |
162 | } |
163 | |
164 | // Get 2-byte index in native byte order. (Rewriter::rewrite makes these.) |
165 | int get_index_u2_cpcache() const { |
166 | return bytecode().get_index_u2_cpcache(cur_bc_raw()); |
167 | } |
168 | |
169 | // Get 4-byte index, for invokedynamic. |
170 | int get_index_u4() const { |
171 | return bytecode().get_index_u4(cur_bc_raw()); |
172 | } |
173 | |
174 | bool has_index_u4() const { |
175 | return bytecode().has_index_u4(cur_bc_raw()); |
176 | } |
177 | |
178 | // Get dimensions byte (multinewarray) |
179 | int get_dimensions() const { return *(unsigned char*)(_pc-1); } |
180 | |
181 | // Sign-extended index byte/short, no widening |
182 | int get_constant_u1() const { return bytecode().get_constant_u1(instruction_size()-1, cur_bc_raw()); } |
183 | int get_constant_u2(bool is_wide = false) const { return bytecode().get_constant_u2(instruction_size()-2, cur_bc_raw(), is_wide); } |
184 | |
185 | // Get a byte signed constant for "iinc". Invalid for other bytecodes. |
186 | // If prefixed with a wide bytecode, get a wide constant |
187 | int get_iinc_con() const {return (_pc==_was_wide) ? (jshort) get_constant_u2(true) : (jbyte) get_constant_u1();} |
188 | |
189 | // 2-byte branch offset from current pc |
190 | int get_dest() const { |
191 | return cur_bci() + bytecode().get_offset_s2(cur_bc_raw()); |
192 | } |
193 | |
194 | // 2-byte branch offset from next pc |
195 | int next_get_dest() const { |
196 | assert(_pc < _end, "")do { if (!(_pc < _end)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciStreams.hpp" , 196, "assert(" "_pc < _end" ") failed", ""); ::breakpoint (); } } while (0); |
197 | return next_bci() + next_bytecode().get_offset_s2(Bytecodes::_ifeq); |
198 | } |
199 | |
200 | // 4-byte branch offset from current pc |
201 | int get_far_dest() const { |
202 | return cur_bci() + bytecode().get_offset_s4(cur_bc_raw()); |
203 | } |
204 | |
205 | // For a lookup or switch table, return target destination |
206 | jint get_int_table( int index ) const { |
207 | return (jint)Bytes::get_Java_u4((address)&_table_base[index]); |
208 | } |
209 | |
210 | int get_dest_table( int index ) const { |
211 | return cur_bci() + get_int_table(index); |
212 | } |
213 | |
214 | // --- Constant pool access --- |
215 | int get_constant_raw_index() const; |
216 | int get_constant_pool_index() const; |
217 | int get_field_index(); |
218 | int get_method_index(); |
219 | |
220 | // If this bytecode is a new, newarray, multianewarray, instanceof, |
221 | // or checkcast, get the referenced klass. |
222 | ciKlass* get_klass(bool& will_link); |
223 | int get_klass_index() const; |
224 | |
225 | // If this bytecode is one of the ldc variants, get the referenced |
226 | // constant. Do not attempt to resolve it, since that would require |
227 | // execution of Java code. If it is not resolved, return an unloaded |
228 | // object (ciConstant.as_object()->is_loaded() == false). |
229 | ciConstant get_constant(); |
230 | constantTag get_constant_pool_tag(int index) const; |
231 | |
232 | // True if the klass-using bytecode points to an unresolved klass |
233 | bool is_unresolved_klass() const { |
234 | constantTag tag = get_constant_pool_tag(get_klass_index()); |
235 | return tag.is_unresolved_klass(); |
236 | } |
237 | |
238 | bool is_unresolved_klass_in_error() const { |
239 | constantTag tag = get_constant_pool_tag(get_klass_index()); |
240 | return tag.is_unresolved_klass_in_error(); |
241 | } |
242 | |
243 | // If this bytecode is one of get_field, get_static, put_field, |
244 | // or put_static, get the referenced field. |
245 | ciField* get_field(bool& will_link); |
246 | |
247 | ciInstanceKlass* get_declared_field_holder(); |
248 | int get_field_holder_index(); |
249 | |
250 | ciMethod* get_method(bool& will_link, ciSignature* *declared_signature_result); |
251 | bool has_appendix(); |
252 | ciObject* get_appendix(); |
253 | bool has_local_signature(); |
254 | ciKlass* get_declared_method_holder(); |
255 | int get_method_holder_index(); |
256 | int get_method_signature_index(const constantPoolHandle& cpool); |
257 | |
258 | }; |
259 | |
260 | |
261 | // ciSignatureStream |
262 | // |
263 | // The class is used to iterate over the elements of a method signature. |
264 | class ciSignatureStream : public StackObj { |
265 | private: |
266 | ciSignature* _sig; |
267 | int _pos; |
268 | // holder is a method's holder |
269 | ciKlass* _holder; |
270 | public: |
271 | ciSignatureStream(ciSignature* signature, ciKlass* holder = NULL__null) { |
272 | _sig = signature; |
273 | _pos = 0; |
274 | _holder = holder; |
275 | } |
276 | |
277 | bool at_return_type() { return _pos == _sig->count(); } |
278 | |
279 | bool is_done() { return _pos > _sig->count(); } |
280 | |
281 | void next() { |
282 | if (_pos <= _sig->count()) { |
283 | _pos++; |
284 | } |
285 | } |
286 | |
287 | ciType* type() { |
288 | if (at_return_type()) { |
289 | return _sig->return_type(); |
290 | } else { |
291 | return _sig->type_at(_pos); |
292 | } |
293 | } |
294 | |
295 | // next klass in the signature |
296 | ciKlass* next_klass() { |
297 | ciKlass* sig_k; |
298 | if (_holder != NULL__null) { |
299 | sig_k = _holder; |
300 | _holder = NULL__null; |
301 | } else { |
302 | while (!type()->is_klass()) { |
303 | next(); |
304 | } |
305 | assert(!at_return_type(), "passed end of signature")do { if (!(!at_return_type())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciStreams.hpp" , 305, "assert(" "!at_return_type()" ") failed", "passed end of signature" ); ::breakpoint(); } } while (0); |
306 | sig_k = type()->as_klass(); |
307 | next(); |
308 | } |
309 | return sig_k; |
310 | } |
311 | }; |
312 | |
313 | |
314 | // ciExceptionHandlerStream |
315 | // |
316 | // The class is used to iterate over the exception handlers of |
317 | // a method. |
318 | class ciExceptionHandlerStream : public StackObj { |
319 | private: |
320 | // The method whose handlers we are traversing |
321 | ciMethod* _method; |
322 | |
323 | // Our current position in the list of handlers |
324 | int _pos; |
325 | int _end; |
326 | |
327 | ciInstanceKlass* _exception_klass; |
328 | int _bci; |
329 | bool _is_exact; |
330 | |
331 | public: |
332 | ciExceptionHandlerStream(ciMethod* method) { |
333 | _method = method; |
334 | |
335 | // Force loading of method code and handlers. |
336 | _method->code(); |
337 | |
338 | _pos = 0; |
339 | _end = _method->_handler_count; |
340 | _exception_klass = NULL__null; |
341 | _bci = -1; |
342 | _is_exact = false; |
343 | } |
344 | |
345 | ciExceptionHandlerStream(ciMethod* method, int bci, |
346 | ciInstanceKlass* exception_klass = NULL__null, |
347 | bool is_exact = false) { |
348 | _method = method; |
349 | |
350 | // Force loading of method code and handlers. |
351 | _method->code(); |
352 | |
353 | _pos = -1; |
354 | _end = _method->_handler_count + 1; // include the rethrow handler |
355 | _exception_klass = (exception_klass != NULL__null && exception_klass->is_loaded() |
356 | ? exception_klass |
357 | : NULL__null); |
358 | _bci = bci; |
359 | assert(_bci >= 0, "bci out of range")do { if (!(_bci >= 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/ci/ciStreams.hpp" , 359, "assert(" "_bci >= 0" ") failed", "bci out of range" ); ::breakpoint(); } } while (0); |
360 | _is_exact = is_exact; |
361 | next(); |
362 | } |
363 | |
364 | // These methods are currently implemented in an odd way. |
365 | // Count the number of handlers the iterator has ever produced |
366 | // or will ever produce. Do not include the final rethrow handler. |
367 | // That is, a trivial exception handler stream will have a count |
368 | // of zero and produce just the rethrow handler. |
369 | int count(); |
370 | |
371 | // Count the number of handlers this stream will produce from now on. |
372 | // Include the current handler, and the final rethrow handler. |
373 | // The remaining count will be zero iff is_done() is true, |
374 | int count_remaining(); |
375 | |
376 | bool is_done() { |
377 | return (_pos >= _end); |
378 | } |
379 | |
380 | void next() { |
381 | _pos++; |
382 | if (_bci != -1) { |
383 | // We are not iterating over all handlers... |
384 | while (!is_done()) { |
385 | ciExceptionHandler* handler = _method->_exception_handlers[_pos]; |
386 | if (handler->is_in_range(_bci)) { |
387 | if (handler->is_catch_all()) { |
388 | // Found final active catch block. |
389 | _end = _pos+1; |
390 | return; |
391 | } else if (_exception_klass == NULL__null || !handler->catch_klass()->is_loaded()) { |
392 | // We cannot do any type analysis here. Must conservatively assume |
393 | // catch block is reachable. |
394 | return; |
395 | } else if (_exception_klass->is_subtype_of(handler->catch_klass())) { |
396 | // This catch clause will definitely catch the exception. |
397 | // Final candidate. |
398 | _end = _pos+1; |
399 | return; |
400 | } else if (!_is_exact && |
401 | handler->catch_klass()->is_subtype_of(_exception_klass)) { |
402 | // This catch block may be reachable. |
403 | return; |
404 | } |
405 | } |
406 | |
407 | // The catch block was not pertinent. Go on. |
408 | _pos++; |
409 | } |
410 | } else { |
411 | // This is an iteration over all handlers. |
412 | return; |
413 | } |
414 | } |
415 | |
416 | ciExceptionHandler* handler() { |
417 | return _method->_exception_handlers[_pos]; |
418 | } |
419 | }; |
420 | |
421 | |
422 | |
423 | // Implementation for declarations in bytecode.hpp |
424 | Bytecode::Bytecode(const ciBytecodeStream* stream, address bcp): _bcp(bcp != NULL__null ? bcp : stream->cur_bcp()), _code(Bytecodes::code_at(NULL__null, addr_at(0))) {} |
425 | Bytecode_lookupswitch::Bytecode_lookupswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); } |
426 | Bytecode_tableswitch::Bytecode_tableswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); } |
427 | |
428 | #endif // SHARE_CI_CISTREAMS_HPP |
1 | /* |
2 | * Copyright (c) 1997, 2019, 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 | #ifndef SHARE_INTERPRETER_BYTECODES_HPP |
26 | #define SHARE_INTERPRETER_BYTECODES_HPP |
27 | |
28 | #include "memory/allocation.hpp" |
29 | |
30 | // Bytecodes specifies all bytecodes used in the VM and |
31 | // provides utility functions to get bytecode attributes. |
32 | |
33 | class Method; |
34 | |
35 | // NOTE: replicated in SA in vm/agent/sun/jvm/hotspot/interpreter/Bytecodes.java |
36 | class Bytecodes: AllStatic { |
37 | public: |
38 | enum Code { |
39 | _illegal = -1, |
40 | |
41 | // Java bytecodes |
42 | _nop = 0, // 0x00 |
43 | _aconst_null = 1, // 0x01 |
44 | _iconst_m1 = 2, // 0x02 |
45 | _iconst_0 = 3, // 0x03 |
46 | _iconst_1 = 4, // 0x04 |
47 | _iconst_2 = 5, // 0x05 |
48 | _iconst_3 = 6, // 0x06 |
49 | _iconst_4 = 7, // 0x07 |
50 | _iconst_5 = 8, // 0x08 |
51 | _lconst_0 = 9, // 0x09 |
52 | _lconst_1 = 10, // 0x0a |
53 | _fconst_0 = 11, // 0x0b |
54 | _fconst_1 = 12, // 0x0c |
55 | _fconst_2 = 13, // 0x0d |
56 | _dconst_0 = 14, // 0x0e |
57 | _dconst_1 = 15, // 0x0f |
58 | _bipush = 16, // 0x10 |
59 | _sipush = 17, // 0x11 |
60 | _ldc = 18, // 0x12 |
61 | _ldc_w = 19, // 0x13 |
62 | _ldc2_w = 20, // 0x14 |
63 | _iload = 21, // 0x15 |
64 | _lload = 22, // 0x16 |
65 | _fload = 23, // 0x17 |
66 | _dload = 24, // 0x18 |
67 | _aload = 25, // 0x19 |
68 | _iload_0 = 26, // 0x1a |
69 | _iload_1 = 27, // 0x1b |
70 | _iload_2 = 28, // 0x1c |
71 | _iload_3 = 29, // 0x1d |
72 | _lload_0 = 30, // 0x1e |
73 | _lload_1 = 31, // 0x1f |
74 | _lload_2 = 32, // 0x20 |
75 | _lload_3 = 33, // 0x21 |
76 | _fload_0 = 34, // 0x22 |
77 | _fload_1 = 35, // 0x23 |
78 | _fload_2 = 36, // 0x24 |
79 | _fload_3 = 37, // 0x25 |
80 | _dload_0 = 38, // 0x26 |
81 | _dload_1 = 39, // 0x27 |
82 | _dload_2 = 40, // 0x28 |
83 | _dload_3 = 41, // 0x29 |
84 | _aload_0 = 42, // 0x2a |
85 | _aload_1 = 43, // 0x2b |
86 | _aload_2 = 44, // 0x2c |
87 | _aload_3 = 45, // 0x2d |
88 | _iaload = 46, // 0x2e |
89 | _laload = 47, // 0x2f |
90 | _faload = 48, // 0x30 |
91 | _daload = 49, // 0x31 |
92 | _aaload = 50, // 0x32 |
93 | _baload = 51, // 0x33 |
94 | _caload = 52, // 0x34 |
95 | _saload = 53, // 0x35 |
96 | _istore = 54, // 0x36 |
97 | _lstore = 55, // 0x37 |
98 | _fstore = 56, // 0x38 |
99 | _dstore = 57, // 0x39 |
100 | _astore = 58, // 0x3a |
101 | _istore_0 = 59, // 0x3b |
102 | _istore_1 = 60, // 0x3c |
103 | _istore_2 = 61, // 0x3d |
104 | _istore_3 = 62, // 0x3e |
105 | _lstore_0 = 63, // 0x3f |
106 | _lstore_1 = 64, // 0x40 |
107 | _lstore_2 = 65, // 0x41 |
108 | _lstore_3 = 66, // 0x42 |
109 | _fstore_0 = 67, // 0x43 |
110 | _fstore_1 = 68, // 0x44 |
111 | _fstore_2 = 69, // 0x45 |
112 | _fstore_3 = 70, // 0x46 |
113 | _dstore_0 = 71, // 0x47 |
114 | _dstore_1 = 72, // 0x48 |
115 | _dstore_2 = 73, // 0x49 |
116 | _dstore_3 = 74, // 0x4a |
117 | _astore_0 = 75, // 0x4b |
118 | _astore_1 = 76, // 0x4c |
119 | _astore_2 = 77, // 0x4d |
120 | _astore_3 = 78, // 0x4e |
121 | _iastore = 79, // 0x4f |
122 | _lastore = 80, // 0x50 |
123 | _fastore = 81, // 0x51 |
124 | _dastore = 82, // 0x52 |
125 | _aastore = 83, // 0x53 |
126 | _bastore = 84, // 0x54 |
127 | _castore = 85, // 0x55 |
128 | _sastore = 86, // 0x56 |
129 | _pop = 87, // 0x57 |
130 | _pop2 = 88, // 0x58 |
131 | _dup = 89, // 0x59 |
132 | _dup_x1 = 90, // 0x5a |
133 | _dup_x2 = 91, // 0x5b |
134 | _dup2 = 92, // 0x5c |
135 | _dup2_x1 = 93, // 0x5d |
136 | _dup2_x2 = 94, // 0x5e |
137 | _swap = 95, // 0x5f |
138 | _iadd = 96, // 0x60 |
139 | _ladd = 97, // 0x61 |
140 | _fadd = 98, // 0x62 |
141 | _dadd = 99, // 0x63 |
142 | _isub = 100, // 0x64 |
143 | _lsub = 101, // 0x65 |
144 | _fsub = 102, // 0x66 |
145 | _dsub = 103, // 0x67 |
146 | _imul = 104, // 0x68 |
147 | _lmul = 105, // 0x69 |
148 | _fmul = 106, // 0x6a |
149 | _dmul = 107, // 0x6b |
150 | _idiv = 108, // 0x6c |
151 | _ldiv = 109, // 0x6d |
152 | _fdiv = 110, // 0x6e |
153 | _ddiv = 111, // 0x6f |
154 | _irem = 112, // 0x70 |
155 | _lrem = 113, // 0x71 |
156 | _frem = 114, // 0x72 |
157 | _drem = 115, // 0x73 |
158 | _ineg = 116, // 0x74 |
159 | _lneg = 117, // 0x75 |
160 | _fneg = 118, // 0x76 |
161 | _dneg = 119, // 0x77 |
162 | _ishl = 120, // 0x78 |
163 | _lshl = 121, // 0x79 |
164 | _ishr = 122, // 0x7a |
165 | _lshr = 123, // 0x7b |
166 | _iushr = 124, // 0x7c |
167 | _lushr = 125, // 0x7d |
168 | _iand = 126, // 0x7e |
169 | _land = 127, // 0x7f |
170 | _ior = 128, // 0x80 |
171 | _lor = 129, // 0x81 |
172 | _ixor = 130, // 0x82 |
173 | _lxor = 131, // 0x83 |
174 | _iinc = 132, // 0x84 |
175 | _i2l = 133, // 0x85 |
176 | _i2f = 134, // 0x86 |
177 | _i2d = 135, // 0x87 |
178 | _l2i = 136, // 0x88 |
179 | _l2f = 137, // 0x89 |
180 | _l2d = 138, // 0x8a |
181 | _f2i = 139, // 0x8b |
182 | _f2l = 140, // 0x8c |
183 | _f2d = 141, // 0x8d |
184 | _d2i = 142, // 0x8e |
185 | _d2l = 143, // 0x8f |
186 | _d2f = 144, // 0x90 |
187 | _i2b = 145, // 0x91 |
188 | _i2c = 146, // 0x92 |
189 | _i2s = 147, // 0x93 |
190 | _lcmp = 148, // 0x94 |
191 | _fcmpl = 149, // 0x95 |
192 | _fcmpg = 150, // 0x96 |
193 | _dcmpl = 151, // 0x97 |
194 | _dcmpg = 152, // 0x98 |
195 | _ifeq = 153, // 0x99 |
196 | _ifne = 154, // 0x9a |
197 | _iflt = 155, // 0x9b |
198 | _ifge = 156, // 0x9c |
199 | _ifgt = 157, // 0x9d |
200 | _ifle = 158, // 0x9e |
201 | _if_icmpeq = 159, // 0x9f |
202 | _if_icmpne = 160, // 0xa0 |
203 | _if_icmplt = 161, // 0xa1 |
204 | _if_icmpge = 162, // 0xa2 |
205 | _if_icmpgt = 163, // 0xa3 |
206 | _if_icmple = 164, // 0xa4 |
207 | _if_acmpeq = 165, // 0xa5 |
208 | _if_acmpne = 166, // 0xa6 |
209 | _goto = 167, // 0xa7 |
210 | _jsr = 168, // 0xa8 |
211 | _ret = 169, // 0xa9 |
212 | _tableswitch = 170, // 0xaa |
213 | _lookupswitch = 171, // 0xab |
214 | _ireturn = 172, // 0xac |
215 | _lreturn = 173, // 0xad |
216 | _freturn = 174, // 0xae |
217 | _dreturn = 175, // 0xaf |
218 | _areturn = 176, // 0xb0 |
219 | _return = 177, // 0xb1 |
220 | _getstatic = 178, // 0xb2 |
221 | _putstatic = 179, // 0xb3 |
222 | _getfield = 180, // 0xb4 |
223 | _putfield = 181, // 0xb5 |
224 | _invokevirtual = 182, // 0xb6 |
225 | _invokespecial = 183, // 0xb7 |
226 | _invokestatic = 184, // 0xb8 |
227 | _invokeinterface = 185, // 0xb9 |
228 | _invokedynamic = 186, // 0xba |
229 | _new = 187, // 0xbb |
230 | _newarray = 188, // 0xbc |
231 | _anewarray = 189, // 0xbd |
232 | _arraylength = 190, // 0xbe |
233 | _athrow = 191, // 0xbf |
234 | _checkcast = 192, // 0xc0 |
235 | _instanceof = 193, // 0xc1 |
236 | _monitorenter = 194, // 0xc2 |
237 | _monitorexit = 195, // 0xc3 |
238 | _wide = 196, // 0xc4 |
239 | _multianewarray = 197, // 0xc5 |
240 | _ifnull = 198, // 0xc6 |
241 | _ifnonnull = 199, // 0xc7 |
242 | _goto_w = 200, // 0xc8 |
243 | _jsr_w = 201, // 0xc9 |
244 | _breakpoint = 202, // 0xca |
245 | |
246 | number_of_java_codes, |
247 | |
248 | // JVM bytecodes |
249 | _fast_agetfield = number_of_java_codes, |
250 | _fast_bgetfield , |
251 | _fast_cgetfield , |
252 | _fast_dgetfield , |
253 | _fast_fgetfield , |
254 | _fast_igetfield , |
255 | _fast_lgetfield , |
256 | _fast_sgetfield , |
257 | |
258 | _fast_aputfield , |
259 | _fast_bputfield , |
260 | _fast_zputfield , |
261 | _fast_cputfield , |
262 | _fast_dputfield , |
263 | _fast_fputfield , |
264 | _fast_iputfield , |
265 | _fast_lputfield , |
266 | _fast_sputfield , |
267 | |
268 | _fast_aload_0 , |
269 | _fast_iaccess_0 , |
270 | _fast_aaccess_0 , |
271 | _fast_faccess_0 , |
272 | |
273 | _fast_iload , |
274 | _fast_iload2 , |
275 | _fast_icaload , |
276 | |
277 | _fast_invokevfinal , |
278 | _fast_linearswitch , |
279 | _fast_binaryswitch , |
280 | |
281 | // special handling of oop constants: |
282 | _fast_aldc , |
283 | _fast_aldc_w , |
284 | |
285 | _return_register_finalizer , |
286 | |
287 | // special handling of signature-polymorphic methods: |
288 | _invokehandle , |
289 | |
290 | // These bytecodes are rewritten at CDS dump time, so that we can prevent them from being |
291 | // rewritten at run time. This way, the ConstMethods can be placed in the CDS ReadOnly |
292 | // section, and RewriteByteCodes/RewriteFrequentPairs can rewrite non-CDS bytecodes |
293 | // at run time. |
294 | // |
295 | // Rewritten at CDS dump time to | Original bytecode |
296 | // _invoke_virtual rewritten on sparc, will be disabled if UseSharedSpaces turned on. |
297 | // ------------------------------+------------------ |
298 | _nofast_getfield , // <- _getfield |
299 | _nofast_putfield , // <- _putfield |
300 | _nofast_aload_0 , // <- _aload_0 |
301 | _nofast_iload , // <- _iload |
302 | |
303 | _shouldnotreachhere , // For debugging |
304 | |
305 | |
306 | number_of_codes |
307 | }; |
308 | |
309 | // Flag bits derived from format strings, can_trap, can_rewrite, etc.: |
310 | enum Flags { |
311 | // semantic flags: |
312 | _bc_can_trap = 1<<0, // bytecode execution can trap or block |
313 | _bc_can_rewrite = 1<<1, // bytecode execution has an alternate form |
314 | |
315 | // format bits (determined only by the format string): |
316 | _fmt_has_c = 1<<2, // constant, such as sipush "bcc" |
317 | _fmt_has_j = 1<<3, // constant pool cache index, such as getfield "bjj" |
318 | _fmt_has_k = 1<<4, // constant pool index, such as ldc "bk" |
319 | _fmt_has_i = 1<<5, // local index, such as iload |
320 | _fmt_has_o = 1<<6, // offset, such as ifeq |
321 | _fmt_has_nbo = 1<<7, // contains native-order field(s) |
322 | _fmt_has_u2 = 1<<8, // contains double-byte field(s) |
323 | _fmt_has_u4 = 1<<9, // contains quad-byte field |
324 | _fmt_not_variable = 1<<10, // not of variable length (simple or wide) |
325 | _fmt_not_simple = 1<<11, // either wide or variable length |
326 | _all_fmt_bits = (_fmt_not_simple*2 - _fmt_has_c), |
327 | |
328 | // Example derived format syndromes: |
329 | _fmt_b = _fmt_not_variable, |
330 | _fmt_bc = _fmt_b | _fmt_has_c, |
331 | _fmt_bi = _fmt_b | _fmt_has_i, |
332 | _fmt_bkk = _fmt_b | _fmt_has_k | _fmt_has_u2, |
333 | _fmt_bJJ = _fmt_b | _fmt_has_j | _fmt_has_u2 | _fmt_has_nbo, |
334 | _fmt_bo2 = _fmt_b | _fmt_has_o | _fmt_has_u2, |
335 | _fmt_bo4 = _fmt_b | _fmt_has_o | _fmt_has_u4 |
336 | }; |
337 | |
338 | private: |
339 | static bool _is_initialized; |
340 | static const char* _name [number_of_codes]; |
341 | static BasicType _result_type [number_of_codes]; |
342 | static s_char _depth [number_of_codes]; |
343 | static u_char _lengths [number_of_codes]; |
344 | static Code _java_code [number_of_codes]; |
345 | static jchar _flags [(1<<BitsPerByte)*2]; // all second page for wide formats |
346 | |
347 | static void def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap); |
348 | static void def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap, Code java_code); |
349 | |
350 | // Verify that bcp points into method |
351 | #ifdef ASSERT1 |
352 | static bool check_method(const Method* method, address bcp); |
353 | #endif |
354 | static bool check_must_rewrite(Bytecodes::Code bc); |
355 | |
356 | public: |
357 | // Conversion |
358 | static void check (Code code) { assert(is_defined(code), "illegal code: %d", (int)code)do { if (!(is_defined(code))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/interpreter/bytecodes.hpp" , 358, "assert(" "is_defined(code)" ") failed", "illegal code: %d" , (int)code); ::breakpoint(); } } while (0); } |
359 | static void wide_check (Code code) { assert(wide_is_defined(code), "illegal code: %d", (int)code)do { if (!(wide_is_defined(code))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/interpreter/bytecodes.hpp" , 359, "assert(" "wide_is_defined(code)" ") failed", "illegal code: %d" , (int)code); ::breakpoint(); } } while (0); } |
360 | static Code cast (int code) { return (Code)code; } |
361 | |
362 | |
363 | // Fetch a bytecode, hiding breakpoints as necessary. The method |
364 | // argument is used for conversion of breakpoints into the original |
365 | // bytecode. The CI uses these methods but guarantees that |
366 | // breakpoints are hidden so the method argument should be passed as |
367 | // NULL since in that case the bcp and Method* are unrelated |
368 | // memory. |
369 | static Code code_at(const Method* method, address bcp) { |
370 | assert(method == NULL || check_method(method, bcp), "bcp must point into method")do { if (!(method == __null || check_method(method, bcp))) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/interpreter/bytecodes.hpp" , 370, "assert(" "method == __null || check_method(method, bcp)" ") failed", "bcp must point into method"); ::breakpoint(); } } while (0); |
371 | Code code = cast(*bcp); |
372 | assert(code != _breakpoint || method != NULL, "need Method* to decode breakpoint")do { if (!(code != _breakpoint || method != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/interpreter/bytecodes.hpp" , 372, "assert(" "code != _breakpoint || method != __null" ") failed" , "need Method* to decode breakpoint"); ::breakpoint(); } } while (0); |
373 | return (code != _breakpoint) ? code : non_breakpoint_code_at(method, bcp); |
374 | } |
375 | static Code java_code_at(const Method* method, address bcp) { |
376 | return java_code(code_at(method, bcp)); |
377 | } |
378 | |
379 | // Fetch a bytecode or a breakpoint: |
380 | static Code code_or_bp_at(address bcp) { return (Code)cast(*bcp); } |
381 | |
382 | static Code code_at(Method* method, int bci); |
383 | |
384 | // find a bytecode, behind a breakpoint if necessary: |
385 | static Code non_breakpoint_code_at(const Method* method, address bcp); |
386 | |
387 | // Bytecode attributes |
388 | static bool is_valid (int code) { return 0 <= code && code < number_of_codes; } |
389 | static bool is_defined (int code) { return is_valid(code) && flags(code, false) != 0; } |
390 | static bool wide_is_defined(int code) { return is_defined(code) && flags(code, true) != 0; } |
391 | static const char* name (Code code) { check(code); return _name [code]; } |
392 | static BasicType result_type (Code code) { check(code); return _result_type [code]; } |
393 | static int depth (Code code) { check(code); return _depth [code]; } |
394 | // Note: Length functions must return <=0 for invalid bytecodes. |
395 | // Calling check(code) in length functions would throw an unwanted assert. |
396 | static int length_for (Code code) { return is_valid(code) ? _lengths[code] & 0xF : -1; } |
397 | static int wide_length_for(Code code) { return is_valid(code) ? _lengths[code] >> 4 : -1; } |
398 | static bool can_trap (Code code) { check(code); return has_all_flags(code, _bc_can_trap, false); } |
399 | static Code java_code (Code code) { check(code); return _java_code [code]; } |
400 | static bool can_rewrite (Code code) { check(code); return has_all_flags(code, _bc_can_rewrite, false); } |
401 | static bool must_rewrite(Bytecodes::Code code) { return can_rewrite(code) && check_must_rewrite(code); } |
402 | static bool native_byte_order(Code code) { check(code); return has_all_flags(code, _fmt_has_nbo, false); } |
403 | static bool uses_cp_cache (Code code) { check(code); return has_all_flags(code, _fmt_has_j, false); } |
404 | // if 'end' is provided, it indicates the end of the code buffer which |
405 | // should not be read past when parsing. |
406 | static int special_length_at(Bytecodes::Code code, address bcp, address end = NULL__null); |
407 | static int raw_special_length_at(address bcp, address end = NULL__null); |
408 | static int length_for_code_at(Bytecodes::Code code, address bcp) { int l = length_for(code); return l > 0 ? l : special_length_at(code, bcp); } |
409 | static int length_at (Method* method, address bcp) { return length_for_code_at(code_at(method, bcp), bcp); } |
410 | static int java_length_at (Method* method, address bcp) { return length_for_code_at(java_code_at(method, bcp), bcp); } |
411 | static bool is_java_code (Code code) { return 0 <= code && code < number_of_java_codes; } |
412 | |
413 | static bool is_store_into_local(Code code){ return (_istore <= code && code <= _astore_3); } |
414 | static bool is_const (Code code) { return (_aconst_null <= code && code <= _ldc2_w); } |
415 | static bool is_zero_const (Code code) { return (code == _aconst_null || code == _iconst_0 |
416 | || code == _fconst_0 || code == _dconst_0); } |
417 | static bool is_return (Code code) { return (_ireturn <= code && code <= _return); } |
418 | static bool is_invoke (Code code) { return (_invokevirtual <= code && code <= _invokedynamic); } |
419 | static bool has_receiver (Code code) { assert(is_invoke(code), "")do { if (!(is_invoke(code))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/interpreter/bytecodes.hpp" , 419, "assert(" "is_invoke(code)" ") failed", ""); ::breakpoint (); } } while (0); return code == _invokevirtual || |
420 | code == _invokespecial || |
421 | code == _invokeinterface; } |
422 | static bool has_optional_appendix(Code code) { return code == _invokedynamic || code == _invokehandle; } |
423 | |
424 | static int compute_flags (const char* format, int more_flags = 0); // compute the flags |
425 | static int flags (int code, bool is_wide) { |
426 | assert(code == (u_char)code, "must be a byte")do { if (!(code == (u_char)code)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/interpreter/bytecodes.hpp" , 426, "assert(" "code == (u_char)code" ") failed", "must be a byte" ); ::breakpoint(); } } while (0); |
427 | return _flags[code + (is_wide ? (1<<BitsPerByte) : 0)]; |
428 | } |
429 | static bool has_all_flags (Code code, int test_flags, bool is_wide) { |
430 | return (flags(code, is_wide) & test_flags) == test_flags; |
431 | } |
432 | |
433 | // Initialization |
434 | static void initialize (); |
435 | }; |
436 | |
437 | #endif // SHARE_INTERPRETER_BYTECODES_HPP |