Bug Summary

File:jdk/src/hotspot/share/oops/generateOopMap.cpp
Warning:line 953, column 11
Although the value stored to 'bytecode' is used in the enclosing expression, the value is never actually read from 'bytecode'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name generateOopMap.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp
1/*
2 * Copyright (c) 1997, 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 "classfile/vmSymbols.hpp"
27#include "interpreter/bytecodeStream.hpp"
28#include "logging/log.hpp"
29#include "logging/logStream.hpp"
30#include "memory/allocation.inline.hpp"
31#include "memory/resourceArea.hpp"
32#include "oops/constantPool.hpp"
33#include "oops/generateOopMap.hpp"
34#include "oops/oop.inline.hpp"
35#include "oops/symbol.hpp"
36#include "runtime/handles.inline.hpp"
37#include "runtime/java.hpp"
38#include "runtime/os.hpp"
39#include "runtime/relocator.hpp"
40#include "runtime/timerTrace.hpp"
41#include "utilities/bitMap.inline.hpp"
42#include "utilities/ostream.hpp"
43
44//
45//
46// Compute stack layouts for each instruction in method.
47//
48// Problems:
49// - What to do about jsr with different types of local vars?
50// Need maps that are conditional on jsr path?
51// - Jsr and exceptions should be done more efficiently (the retAddr stuff)
52//
53// Alternative:
54// - Could extend verifier to provide this information.
55// For: one fewer abstract interpreter to maintain. Against: the verifier
56// solves a bigger problem so slower (undesirable to force verification of
57// everything?).
58//
59// Algorithm:
60// Partition bytecodes into basic blocks
61// For each basic block: store entry state (vars, stack). For instructions
62// inside basic blocks we do not store any state (instead we recompute it
63// from state produced by previous instruction).
64//
65// Perform abstract interpretation of bytecodes over this lattice:
66//
67// _--'#'--_
68// / / \ \
69// / / \ \
70// / | | \
71// 'r' 'v' 'p' ' '
72// \ | | /
73// \ \ / /
74// \ \ / /
75// -- '@' --
76//
77// '#' top, result of conflict merge
78// 'r' reference type
79// 'v' value type
80// 'p' pc type for jsr/ret
81// ' ' uninitialized; never occurs on operand stack in Java
82// '@' bottom/unexecuted; initial state each bytecode.
83//
84// Basic block headers are the only merge points. We use this iteration to
85// compute the information:
86//
87// find basic blocks;
88// initialize them with uninitialized state;
89// initialize first BB according to method signature;
90// mark first BB changed
91// while (some BB is changed) do {
92// perform abstract interpration of all bytecodes in BB;
93// merge exit state of BB into entry state of all successor BBs,
94// noting if any of these change;
95// }
96//
97// One additional complication is necessary. The jsr instruction pushes
98// a return PC on the stack (a 'p' type in the abstract interpretation).
99// To be able to process "ret" bytecodes, we keep track of these return
100// PC's in a 'retAddrs' structure in abstract interpreter context (when
101// processing a "ret" bytecodes, it is not sufficient to know that it gets
102// an argument of the right type 'p'; we need to know which address it
103// returns to).
104//
105// (Note this comment is borrowed form the original author of the algorithm)
106
107// ComputeCallStack
108//
109// Specialization of SignatureIterator - compute the effects of a call
110//
111class ComputeCallStack : public SignatureIterator {
112 CellTypeState *_effect;
113 int _idx;
114
115 void setup();
116 void set(CellTypeState state) { _effect[_idx++] = state; }
117 int length() { return _idx; };
118
119 friend class SignatureIterator; // so do_parameters_on can call do_type
120 void do_type(BasicType type, bool for_return = false) {
121 if (for_return && type == T_VOID) {
122 set(CellTypeState::bottom);
123 } else if (is_reference_type(type)) {
124 set(CellTypeState::ref);
125 } else {
126 assert(is_java_primitive(type), "")do { if (!(is_java_primitive(type))) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 126, "assert(" "is_java_primitive(type)" ") failed", ""); ::
breakpoint(); } } while (0)
;
127 set(CellTypeState::value);
128 if (is_double_word_type(type)) {
129 set(CellTypeState::value);
130 }
131 }
132 }
133
134 public:
135 ComputeCallStack(Symbol* signature) : SignatureIterator(signature) {};
136
137 // Compute methods
138 int compute_for_parameters(bool is_static, CellTypeState *effect) {
139 _idx = 0;
140 _effect = effect;
141
142 if (!is_static)
143 effect[_idx++] = CellTypeState::ref;
144
145 do_parameters_on(this);
146
147 return length();
148 };
149
150 int compute_for_returntype(CellTypeState *effect) {
151 _idx = 0;
152 _effect = effect;
153 do_type(return_type(), true);
154 set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works
155
156 return length();
157 }
158};
159
160//=========================================================================================
161// ComputeEntryStack
162//
163// Specialization of SignatureIterator - in order to set up first stack frame
164//
165class ComputeEntryStack : public SignatureIterator {
166 CellTypeState *_effect;
167 int _idx;
168
169 void setup();
170 void set(CellTypeState state) { _effect[_idx++] = state; }
171 int length() { return _idx; };
172
173 friend class SignatureIterator; // so do_parameters_on can call do_type
174 void do_type(BasicType type, bool for_return = false) {
175 if (for_return && type == T_VOID) {
176 set(CellTypeState::bottom);
177 } else if (is_reference_type(type)) {
178 set(CellTypeState::make_slot_ref(_idx));
179 } else {
180 assert(is_java_primitive(type), "")do { if (!(is_java_primitive(type))) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 180, "assert(" "is_java_primitive(type)" ") failed", ""); ::
breakpoint(); } } while (0)
;
181 set(CellTypeState::value);
182 if (is_double_word_type(type)) {
183 set(CellTypeState::value);
184 }
185 }
186 }
187
188 public:
189 ComputeEntryStack(Symbol* signature) : SignatureIterator(signature) {};
190
191 // Compute methods
192 int compute_for_parameters(bool is_static, CellTypeState *effect) {
193 _idx = 0;
194 _effect = effect;
195
196 if (!is_static)
197 effect[_idx++] = CellTypeState::make_slot_ref(0);
198
199 do_parameters_on(this);
200
201 return length();
202 };
203
204 int compute_for_returntype(CellTypeState *effect) {
205 _idx = 0;
206 _effect = effect;
207 do_type(return_type(), true);
208 set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works
209
210 return length();
211 }
212};
213
214//=====================================================================================
215//
216// Implementation of RetTable/RetTableEntry
217//
218// Contains function to itereate through all bytecodes
219// and find all return entry points
220//
221int RetTable::_init_nof_entries = 10;
222int RetTableEntry::_init_nof_jsrs = 5;
223
224RetTableEntry::RetTableEntry(int target, RetTableEntry *next) {
225 _target_bci = target;
226 _jsrs = new GrowableArray<intptr_t>(_init_nof_jsrs);
227 _next = next;
228}
229
230void RetTableEntry::add_delta(int bci, int delta) {
231 if (_target_bci > bci) _target_bci += delta;
232
233 for (int k = 0; k < _jsrs->length(); k++) {
234 int jsr = _jsrs->at(k);
235 if (jsr > bci) _jsrs->at_put(k, jsr+delta);
236 }
237}
238
239void RetTable::compute_ret_table(const methodHandle& method) {
240 BytecodeStream i(method);
241 Bytecodes::Code bytecode;
242
243 while( (bytecode = i.next()) >= 0) {
244 switch (bytecode) {
245 case Bytecodes::_jsr:
246 add_jsr(i.next_bci(), i.dest());
247 break;
248 case Bytecodes::_jsr_w:
249 add_jsr(i.next_bci(), i.dest_w());
250 break;
251 default:
252 break;
253 }
254 }
255}
256
257void RetTable::add_jsr(int return_bci, int target_bci) {
258 RetTableEntry* entry = _first;
259
260 // Scan table for entry
261 for (;entry && entry->target_bci() != target_bci; entry = entry->next());
262
263 if (!entry) {
264 // Allocate new entry and put in list
265 entry = new RetTableEntry(target_bci, _first);
266 _first = entry;
267 }
268
269 // Now "entry" is set. Make sure that the entry is initialized
270 // and has room for the new jsr.
271 entry->add_jsr(return_bci);
272}
273
274RetTableEntry* RetTable::find_jsrs_for_target(int targBci) {
275 RetTableEntry *cur = _first;
276
277 while(cur) {
278 assert(cur->target_bci() != -1, "sanity check")do { if (!(cur->target_bci() != -1)) { (*g_assert_poison) =
'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 278, "assert(" "cur->target_bci() != -1" ") failed", "sanity check"
); ::breakpoint(); } } while (0)
;
279 if (cur->target_bci() == targBci) return cur;
280 cur = cur->next();
281 }
282 ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here(
"/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 282); ::breakpoint(); } while (0)
;
283 return NULL__null;
284}
285
286// The instruction at bci is changing size by "delta". Update the return map.
287void RetTable::update_ret_table(int bci, int delta) {
288 RetTableEntry *cur = _first;
289 while(cur) {
290 cur->add_delta(bci, delta);
291 cur = cur->next();
292 }
293}
294
295//
296// Celltype state
297//
298
299CellTypeState CellTypeState::bottom = CellTypeState::make_bottom();
300CellTypeState CellTypeState::uninit = CellTypeState::make_any(uninit_value);
301CellTypeState CellTypeState::ref = CellTypeState::make_any(ref_conflict);
302CellTypeState CellTypeState::value = CellTypeState::make_any(val_value);
303CellTypeState CellTypeState::refUninit = CellTypeState::make_any(ref_conflict | uninit_value);
304CellTypeState CellTypeState::top = CellTypeState::make_top();
305CellTypeState CellTypeState::addr = CellTypeState::make_any(addr_conflict);
306
307// Commonly used constants
308static CellTypeState epsilonCTS[1] = { CellTypeState::bottom };
309static CellTypeState refCTS = CellTypeState::ref;
310static CellTypeState valCTS = CellTypeState::value;
311static CellTypeState vCTS[2] = { CellTypeState::value, CellTypeState::bottom };
312static CellTypeState rCTS[2] = { CellTypeState::ref, CellTypeState::bottom };
313static CellTypeState rrCTS[3] = { CellTypeState::ref, CellTypeState::ref, CellTypeState::bottom };
314static CellTypeState vrCTS[3] = { CellTypeState::value, CellTypeState::ref, CellTypeState::bottom };
315static CellTypeState vvCTS[3] = { CellTypeState::value, CellTypeState::value, CellTypeState::bottom };
316static CellTypeState rvrCTS[4] = { CellTypeState::ref, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom };
317static CellTypeState vvrCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom };
318static CellTypeState vvvCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom };
319static CellTypeState vvvrCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom };
320static CellTypeState vvvvCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom };
321
322char CellTypeState::to_char() const {
323 if (can_be_reference()) {
324 if (can_be_value() || can_be_address())
325 return '#'; // Conflict that needs to be rewritten
326 else
327 return 'r';
328 } else if (can_be_value())
329 return 'v';
330 else if (can_be_address())
331 return 'p';
332 else if (can_be_uninit())
333 return ' ';
334 else
335 return '@';
336}
337
338
339// Print a detailed CellTypeState. Indicate all bits that are set. If
340// the CellTypeState represents an address or a reference, print the
341// value of the additional information.
342void CellTypeState::print(outputStream *os) {
343 if (can_be_address()) {
344 os->print("(p");
345 } else {
346 os->print("( ");
347 }
348 if (can_be_reference()) {
349 os->print("r");
350 } else {
351 os->print(" ");
352 }
353 if (can_be_value()) {
354 os->print("v");
355 } else {
356 os->print(" ");
357 }
358 if (can_be_uninit()) {
359 os->print("u|");
360 } else {
361 os->print(" |");
362 }
363 if (is_info_top()) {
364 os->print("Top)");
365 } else if (is_info_bottom()) {
366 os->print("Bot)");
367 } else {
368 if (is_reference()) {
369 int info = get_info();
370 int data = info & ~(ref_not_lock_bit | ref_slot_bit);
371 if (info & ref_not_lock_bit) {
372 // Not a monitor lock reference.
373 if (info & ref_slot_bit) {
374 // slot
375 os->print("slot%d)", data);
376 } else {
377 // line
378 os->print("line%d)", data);
379 }
380 } else {
381 // lock
382 os->print("lock%d)", data);
383 }
384 } else {
385 os->print("%d)", get_info());
386 }
387 }
388}
389
390//
391// Basicblock handling methods
392//
393
394void GenerateOopMap::initialize_bb() {
395 _gc_points = 0;
396 _bb_count = 0;
397 _bb_hdr_bits.reinitialize(method()->code_size());
398}
399
400void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) {
401 assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds")do { if (!(bci>= 0 && bci < c->method()->
code_size())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 401, "assert(" "bci>= 0 && bci < c->method()->code_size()"
") failed", "index out of bounds"); ::breakpoint(); } } while
(0)
;
402 if (c->is_bb_header(bci))
403 return;
404
405 if (TraceNewOopMapGeneration) {
406 tty->print_cr("Basicblock#%d begins at: %d", c->_bb_count, bci);
407 }
408 c->set_bbmark_bit(bci);
409 c->_bb_count++;
410}
411
412
413void GenerateOopMap::mark_bbheaders_and_count_gc_points() {
414 initialize_bb();
415
416 bool fellThrough = false; // False to get first BB marked.
417
418 // First mark all exception handlers as start of a basic-block
419 ExceptionTable excps(method());
420 for(int i = 0; i < excps.length(); i ++) {
421 bb_mark_fct(this, excps.handler_pc(i), NULL__null);
422 }
423
424 // Then iterate through the code
425 BytecodeStream bcs(_method);
426 Bytecodes::Code bytecode;
427
428 while( (bytecode = bcs.next()) >= 0) {
429 int bci = bcs.bci();
430
431 if (!fellThrough)
432 bb_mark_fct(this, bci, NULL__null);
433
434 fellThrough = jump_targets_do(&bcs, &GenerateOopMap::bb_mark_fct, NULL__null);
435
436 /* We will also mark successors of jsr's as basic block headers. */
437 switch (bytecode) {
438 case Bytecodes::_jsr:
439 assert(!fellThrough, "should not happen")do { if (!(!fellThrough)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 439, "assert(" "!fellThrough" ") failed", "should not happen"
); ::breakpoint(); } } while (0)
;
440 bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL__null);
441 break;
442 case Bytecodes::_jsr_w:
443 assert(!fellThrough, "should not happen")do { if (!(!fellThrough)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 443, "assert(" "!fellThrough" ") failed", "should not happen"
); ::breakpoint(); } } while (0)
;
444 bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL__null);
445 break;
446 default:
447 break;
448 }
449
450 if (possible_gc_point(&bcs))
451 _gc_points++;
452 }
453}
454
455void GenerateOopMap::set_bbmark_bit(int bci) {
456 _bb_hdr_bits.at_put(bci, true);
457}
458
459void GenerateOopMap::reachable_basicblock(GenerateOopMap *c, int bci, int *data) {
460 assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds")do { if (!(bci>= 0 && bci < c->method()->
code_size())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 460, "assert(" "bci>= 0 && bci < c->method()->code_size()"
") failed", "index out of bounds"); ::breakpoint(); } } while
(0)
;
461 BasicBlock* bb = c->get_basic_block_at(bci);
462 if (bb->is_dead()) {
463 bb->mark_as_alive();
464 *data = 1; // Mark basicblock as changed
465 }
466}
467
468
469void GenerateOopMap::mark_reachable_code() {
470 int change = 1; // int to get function pointers to work
471
472 // Mark entry basic block as alive and all exception handlers
473 _basic_blocks[0].mark_as_alive();
474 ExceptionTable excps(method());
475 for(int i = 0; i < excps.length(); i++) {
476 BasicBlock *bb = get_basic_block_at(excps.handler_pc(i));
477 // If block is not already alive (due to multiple exception handlers to same bb), then
478 // make it alive
479 if (bb->is_dead()) bb->mark_as_alive();
480 }
481
482 BytecodeStream bcs(_method);
483
484 // Iterate through all basic blocks until we reach a fixpoint
485 while (change) {
486 change = 0;
487
488 for (int i = 0; i < _bb_count; i++) {
489 BasicBlock *bb = &_basic_blocks[i];
490 if (bb->is_alive()) {
491 // Position bytecodestream at last bytecode in basicblock
492 bcs.set_start(bb->_end_bci);
493 bcs.next();
494 Bytecodes::Code bytecode = bcs.code();
495 int bci = bcs.bci();
496 assert(bci == bb->_end_bci, "wrong bci")do { if (!(bci == bb->_end_bci)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 496, "assert(" "bci == bb->_end_bci" ") failed", "wrong bci"
); ::breakpoint(); } } while (0)
;
497
498 bool fell_through = jump_targets_do(&bcs, &GenerateOopMap::reachable_basicblock, &change);
499
500 // We will also mark successors of jsr's as alive.
501 switch (bytecode) {
502 case Bytecodes::_jsr:
503 case Bytecodes::_jsr_w:
504 assert(!fell_through, "should not happen")do { if (!(!fell_through)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 504, "assert(" "!fell_through" ") failed", "should not happen"
); ::breakpoint(); } } while (0)
;
505 reachable_basicblock(this, bci + Bytecodes::length_for(bytecode), &change);
506 break;
507 default:
508 break;
509 }
510 if (fell_through) {
511 // Mark successor as alive
512 if (bb[1].is_dead()) {
513 bb[1].mark_as_alive();
514 change = 1;
515 }
516 }
517 }
518 }
519 }
520}
521
522/* If the current instruction in "c" has no effect on control flow,
523 returns "true". Otherwise, calls "jmpFct" one or more times, with
524 "c", an appropriate "pcDelta", and "data" as arguments, then
525 returns "false". There is one exception: if the current
526 instruction is a "ret", returns "false" without calling "jmpFct".
527 Arrangements for tracking the control flow of a "ret" must be made
528 externally. */
529bool GenerateOopMap::jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int *data) {
530 int bci = bcs->bci();
531
532 switch (bcs->code()) {
533 case Bytecodes::_ifeq:
534 case Bytecodes::_ifne:
535 case Bytecodes::_iflt:
536 case Bytecodes::_ifge:
537 case Bytecodes::_ifgt:
538 case Bytecodes::_ifle:
539 case Bytecodes::_if_icmpeq:
540 case Bytecodes::_if_icmpne:
541 case Bytecodes::_if_icmplt:
542 case Bytecodes::_if_icmpge:
543 case Bytecodes::_if_icmpgt:
544 case Bytecodes::_if_icmple:
545 case Bytecodes::_if_acmpeq:
546 case Bytecodes::_if_acmpne:
547 case Bytecodes::_ifnull:
548 case Bytecodes::_ifnonnull:
549 (*jmpFct)(this, bcs->dest(), data);
550 (*jmpFct)(this, bci + 3, data);
551 break;
552
553 case Bytecodes::_goto:
554 (*jmpFct)(this, bcs->dest(), data);
555 break;
556 case Bytecodes::_goto_w:
557 (*jmpFct)(this, bcs->dest_w(), data);
558 break;
559 case Bytecodes::_tableswitch:
560 { Bytecode_tableswitch tableswitch(method(), bcs->bcp());
561 int len = tableswitch.length();
562
563 (*jmpFct)(this, bci + tableswitch.default_offset(), data); /* Default. jump address */
564 while (--len >= 0) {
565 (*jmpFct)(this, bci + tableswitch.dest_offset_at(len), data);
566 }
567 break;
568 }
569
570 case Bytecodes::_lookupswitch:
571 { Bytecode_lookupswitch lookupswitch(method(), bcs->bcp());
572 int npairs = lookupswitch.number_of_pairs();
573 (*jmpFct)(this, bci + lookupswitch.default_offset(), data); /* Default. */
574 while(--npairs >= 0) {
575 LookupswitchPair pair = lookupswitch.pair_at(npairs);
576 (*jmpFct)(this, bci + pair.offset(), data);
577 }
578 break;
579 }
580 case Bytecodes::_jsr:
581 assert(bcs->is_wide()==false, "sanity check")do { if (!(bcs->is_wide()==false)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 581, "assert(" "bcs->is_wide()==false" ") failed", "sanity check"
); ::breakpoint(); } } while (0)
;
582 (*jmpFct)(this, bcs->dest(), data);
583
584
585
586 break;
587 case Bytecodes::_jsr_w:
588 (*jmpFct)(this, bcs->dest_w(), data);
589 break;
590 case Bytecodes::_wide:
591 ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here(
"/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 591); ::breakpoint(); } while (0)
;
592 return true;
593 break;
594 case Bytecodes::_athrow:
595 case Bytecodes::_ireturn:
596 case Bytecodes::_lreturn:
597 case Bytecodes::_freturn:
598 case Bytecodes::_dreturn:
599 case Bytecodes::_areturn:
600 case Bytecodes::_return:
601 case Bytecodes::_ret:
602 break;
603 default:
604 return true;
605 }
606 return false;
607}
608
609/* Requires "pc" to be the head of a basic block; returns that basic
610 block. */
611BasicBlock *GenerateOopMap::get_basic_block_at(int bci) const {
612 BasicBlock* bb = get_basic_block_containing(bci);
613 assert(bb->_bci == bci, "should have found BB")do { if (!(bb->_bci == bci)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 613, "assert(" "bb->_bci == bci" ") failed", "should have found BB"
); ::breakpoint(); } } while (0)
;
614 return bb;
615}
616
617// Requires "pc" to be the start of an instruction; returns the basic
618// block containing that instruction. */
619BasicBlock *GenerateOopMap::get_basic_block_containing(int bci) const {
620 BasicBlock *bbs = _basic_blocks;
621 int lo = 0, hi = _bb_count - 1;
622
623 while (lo <= hi) {
624 int m = (lo + hi) / 2;
625 int mbci = bbs[m]._bci;
626 int nbci;
627
628 if ( m == _bb_count-1) {
629 assert( bci >= mbci && bci < method()->code_size(), "sanity check failed")do { if (!(bci >= mbci && bci < method()->code_size
())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 629, "assert(" "bci >= mbci && bci < method()->code_size()"
") failed", "sanity check failed"); ::breakpoint(); } } while
(0)
;
630 return bbs+m;
631 } else {
632 nbci = bbs[m+1]._bci;
633 }
634
635 if ( mbci <= bci && bci < nbci) {
636 return bbs+m;
637 } else if (mbci < bci) {
638 lo = m + 1;
639 } else {
640 assert(mbci > bci, "sanity check")do { if (!(mbci > bci)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 640, "assert(" "mbci > bci" ") failed", "sanity check");
::breakpoint(); } } while (0)
;
641 hi = m - 1;
642 }
643 }
644
645 fatal("should have found BB")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 645, "should have found BB"); ::breakpoint(); } while (0)
;
646 return NULL__null;
647}
648
649void GenerateOopMap::restore_state(BasicBlock *bb)
650{
651 memcpy(_state, bb->_state, _state_len*sizeof(CellTypeState));
652 _stack_top = bb->_stack_top;
653 _monitor_top = bb->_monitor_top;
654}
655
656int GenerateOopMap::next_bb_start_pc(BasicBlock *bb) {
657 int bbNum = bb - _basic_blocks + 1;
658 if (bbNum == _bb_count)
659 return method()->code_size();
660
661 return _basic_blocks[bbNum]._bci;
662}
663
664//
665// CellType handling methods
666//
667
668// Allocate memory and throw LinkageError if failure.
669#define ALLOC_RESOURCE_ARRAY(var, type, count)var = (type*) resource_allocate_bytes((count) * sizeof(type),
AllocFailStrategy::RETURN_NULL); if (var == __null) { report_error
("Cannot reserve enough memory to analyze this method"); return
; }
\
670 var = NEW_RESOURCE_ARRAY_RETURN_NULL(type, count)(type*) resource_allocate_bytes((count) * sizeof(type), AllocFailStrategy
::RETURN_NULL)
; \
671 if (var == NULL__null) { \
672 report_error("Cannot reserve enough memory to analyze this method"); \
673 return; \
674 }
675
676
677void GenerateOopMap::init_state() {
678 _state_len = _max_locals + _max_stack + _max_monitors;
679 ALLOC_RESOURCE_ARRAY(_state, CellTypeState, _state_len)_state = (CellTypeState*) resource_allocate_bytes((_state_len
) * sizeof(CellTypeState), AllocFailStrategy::RETURN_NULL); if
(_state == __null) { report_error("Cannot reserve enough memory to analyze this method"
); return; }
;
680 memset(_state, 0, _state_len * sizeof(CellTypeState));
681 int count = MAX3(_max_locals, _max_stack, _max_monitors) + 1/*for null terminator char */;
682 ALLOC_RESOURCE_ARRAY(_state_vec_buf, char, count)_state_vec_buf = (char*) resource_allocate_bytes((count) * sizeof
(char), AllocFailStrategy::RETURN_NULL); if (_state_vec_buf ==
__null) { report_error("Cannot reserve enough memory to analyze this method"
); return; }
;
683}
684
685void GenerateOopMap::make_context_uninitialized() {
686 CellTypeState* vs = vars();
687
688 for (int i = 0; i < _max_locals; i++)
689 vs[i] = CellTypeState::uninit;
690
691 _stack_top = 0;
692 _monitor_top = 0;
693}
694
695int GenerateOopMap::methodsig_to_effect(Symbol* signature, bool is_static, CellTypeState* effect) {
696 ComputeEntryStack ces(signature);
697 return ces.compute_for_parameters(is_static, effect);
698}
699
700// Return result of merging cts1 and cts2.
701CellTypeState CellTypeState::merge(CellTypeState cts, int slot) const {
702 CellTypeState result;
703
704 assert(!is_bottom() && !cts.is_bottom(),do { if (!(!is_bottom() && !cts.is_bottom())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 705, "assert(" "!is_bottom() && !cts.is_bottom()" ") failed"
, "merge of bottom values is handled elsewhere"); ::breakpoint
(); } } while (0)
705 "merge of bottom values is handled elsewhere")do { if (!(!is_bottom() && !cts.is_bottom())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 705, "assert(" "!is_bottom() && !cts.is_bottom()" ") failed"
, "merge of bottom values is handled elsewhere"); ::breakpoint
(); } } while (0)
;
706
707 result._state = _state | cts._state;
708
709 // If the top bit is set, we don't need to do any more work.
710 if (!result.is_info_top()) {
711 assert((result.can_be_address() || result.can_be_reference()),do { if (!((result.can_be_address() || result.can_be_reference
()))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 712, "assert(" "(result.can_be_address() || result.can_be_reference())"
") failed", "only addresses and references have non-top info"
); ::breakpoint(); } } while (0)
712 "only addresses and references have non-top info")do { if (!((result.can_be_address() || result.can_be_reference
()))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 712, "assert(" "(result.can_be_address() || result.can_be_reference())"
") failed", "only addresses and references have non-top info"
); ::breakpoint(); } } while (0)
;
713
714 if (!equal(cts)) {
715 // The two values being merged are different. Raise to top.
716 if (result.is_reference()) {
717 result = CellTypeState::make_slot_ref(slot);
718 } else {
719 result._state |= info_conflict;
720 }
721 }
722 }
723 assert(result.is_valid_state(), "checking that CTS merge maintains legal state")do { if (!(result.is_valid_state())) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 723, "assert(" "result.is_valid_state()" ") failed", "checking that CTS merge maintains legal state"
); ::breakpoint(); } } while (0)
;
724
725 return result;
726}
727
728// Merge the variable state for locals and stack from cts into bbts.
729bool GenerateOopMap::merge_local_state_vectors(CellTypeState* cts,
730 CellTypeState* bbts) {
731 int i;
732 int len = _max_locals + _stack_top;
733 bool change = false;
734
735 for (i = len - 1; i >= 0; i--) {
736 CellTypeState v = cts[i].merge(bbts[i], i);
737 change = change || !v.equal(bbts[i]);
738 bbts[i] = v;
739 }
740
741 return change;
742}
743
744// Merge the monitor stack state from cts into bbts.
745bool GenerateOopMap::merge_monitor_state_vectors(CellTypeState* cts,
746 CellTypeState* bbts) {
747 bool change = false;
748 if (_max_monitors > 0 && _monitor_top != bad_monitors) {
749 // If there are no monitors in the program, or there has been
750 // a monitor matching error before this point in the program,
751 // then we do not merge in the monitor state.
752
753 int base = _max_locals + _max_stack;
754 int len = base + _monitor_top;
755 for (int i = len - 1; i >= base; i--) {
756 CellTypeState v = cts[i].merge(bbts[i], i);
757
758 // Can we prove that, when there has been a change, it will already
759 // have been detected at this point? That would make this equal
760 // check here unnecessary.
761 change = change || !v.equal(bbts[i]);
762 bbts[i] = v;
763 }
764 }
765
766 return change;
767}
768
769void GenerateOopMap::copy_state(CellTypeState *dst, CellTypeState *src) {
770 int len = _max_locals + _stack_top;
771 for (int i = 0; i < len; i++) {
772 if (src[i].is_nonlock_reference()) {
773 dst[i] = CellTypeState::make_slot_ref(i);
774 } else {
775 dst[i] = src[i];
776 }
777 }
778 if (_max_monitors > 0 && _monitor_top != bad_monitors) {
779 int base = _max_locals + _max_stack;
780 len = base + _monitor_top;
781 for (int i = base; i < len; i++) {
782 dst[i] = src[i];
783 }
784 }
785}
786
787
788// Merge the states for the current block and the next. As long as a
789// block is reachable the locals and stack must be merged. If the
790// stack heights don't match then this is a verification error and
791// it's impossible to interpret the code. Simultaneously monitor
792// states are being check to see if they nest statically. If monitor
793// depths match up then their states are merged. Otherwise the
794// mismatch is simply recorded and interpretation continues since
795// monitor matching is purely informational and doesn't say anything
796// about the correctness of the code.
797void GenerateOopMap::merge_state_into_bb(BasicBlock *bb) {
798 guarantee(bb != NULL, "null basicblock")do { if (!(bb != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 798, "guarantee(" "bb != NULL" ") failed", "null basicblock"
); ::breakpoint(); } } while (0)
;
799 assert(bb->is_alive(), "merging state into a dead basicblock")do { if (!(bb->is_alive())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 799, "assert(" "bb->is_alive()" ") failed", "merging state into a dead basicblock"
); ::breakpoint(); } } while (0)
;
800
801 if (_stack_top == bb->_stack_top) {
802 // always merge local state even if monitors don't match.
803 if (merge_local_state_vectors(_state, bb->_state)) {
804 bb->set_changed(true);
805 }
806 if (_monitor_top == bb->_monitor_top) {
807 // monitors still match so continue merging monitor states.
808 if (merge_monitor_state_vectors(_state, bb->_state)) {
809 bb->set_changed(true);
810 }
811 } else {
812 if (log_is_enabled(Info, monitormismatch)(LogImpl<(LogTag::_monitormismatch), (LogTag::__NO_TAG), (
LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag
::__NO_TAG)>::is_level(LogLevel::Info))
) {
813 report_monitor_mismatch("monitor stack height merge conflict");
814 }
815 // When the monitor stacks are not matched, we set _monitor_top to
816 // bad_monitors. This signals that, from here on, the monitor stack cannot
817 // be trusted. In particular, monitorexit bytecodes may throw
818 // exceptions. We mark this block as changed so that the change
819 // propagates properly.
820 bb->_monitor_top = bad_monitors;
821 bb->set_changed(true);
822 _monitor_safe = false;
823 }
824 } else if (!bb->is_reachable()) {
825 // First time we look at this BB
826 copy_state(bb->_state, _state);
827 bb->_stack_top = _stack_top;
828 bb->_monitor_top = _monitor_top;
829 bb->set_changed(true);
830 } else {
831 verify_error("stack height conflict: %d vs. %d", _stack_top, bb->_stack_top);
832 }
833}
834
835void GenerateOopMap::merge_state(GenerateOopMap *gom, int bci, int* data) {
836 gom->merge_state_into_bb(gom->get_basic_block_at(bci));
837}
838
839void GenerateOopMap::set_var(int localNo, CellTypeState cts) {
840 assert(cts.is_reference() || cts.is_value() || cts.is_address(),do { if (!(cts.is_reference() || cts.is_value() || cts.is_address
())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 841, "assert(" "cts.is_reference() || cts.is_value() || cts.is_address()"
") failed", "wrong celltypestate"); ::breakpoint(); } } while
(0)
841 "wrong celltypestate")do { if (!(cts.is_reference() || cts.is_value() || cts.is_address
())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 841, "assert(" "cts.is_reference() || cts.is_value() || cts.is_address()"
") failed", "wrong celltypestate"); ::breakpoint(); } } while
(0)
;
842 if (localNo < 0 || localNo > _max_locals) {
843 verify_error("variable write error: r%d", localNo);
844 return;
845 }
846 vars()[localNo] = cts;
847}
848
849CellTypeState GenerateOopMap::get_var(int localNo) {
850 assert(localNo < _max_locals + _nof_refval_conflicts, "variable read error")do { if (!(localNo < _max_locals + _nof_refval_conflicts))
{ (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 850, "assert(" "localNo < _max_locals + _nof_refval_conflicts"
") failed", "variable read error"); ::breakpoint(); } } while
(0)
;
851 if (localNo < 0 || localNo > _max_locals) {
852 verify_error("variable read error: r%d", localNo);
853 return valCTS; // just to pick something;
854 }
855 return vars()[localNo];
856}
857
858CellTypeState GenerateOopMap::pop() {
859 if ( _stack_top <= 0) {
860 verify_error("stack underflow");
861 return valCTS; // just to pick something
862 }
863 return stack()[--_stack_top];
864}
865
866void GenerateOopMap::push(CellTypeState cts) {
867 if ( _stack_top >= _max_stack) {
868 verify_error("stack overflow");
869 return;
870 }
871 stack()[_stack_top++] = cts;
872}
873
874CellTypeState GenerateOopMap::monitor_pop() {
875 assert(_monitor_top != bad_monitors, "monitor_pop called on error monitor stack")do { if (!(_monitor_top != bad_monitors)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 875, "assert(" "_monitor_top != bad_monitors" ") failed", "monitor_pop called on error monitor stack"
); ::breakpoint(); } } while (0)
;
876 if (_monitor_top == 0) {
877 // We have detected a pop of an empty monitor stack.
878 _monitor_safe = false;
879 _monitor_top = bad_monitors;
880
881 if (log_is_enabled(Info, monitormismatch)(LogImpl<(LogTag::_monitormismatch), (LogTag::__NO_TAG), (
LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag
::__NO_TAG)>::is_level(LogLevel::Info))
) {
882 report_monitor_mismatch("monitor stack underflow");
883 }
884 return CellTypeState::ref; // just to keep the analysis going.
885 }
886 return monitors()[--_monitor_top];
887}
888
889void GenerateOopMap::monitor_push(CellTypeState cts) {
890 assert(_monitor_top != bad_monitors, "monitor_push called on error monitor stack")do { if (!(_monitor_top != bad_monitors)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 890, "assert(" "_monitor_top != bad_monitors" ") failed", "monitor_push called on error monitor stack"
); ::breakpoint(); } } while (0)
;
891 if (_monitor_top >= _max_monitors) {
892 // Some monitorenter is being executed more than once.
893 // This means that the monitor stack cannot be simulated.
894 _monitor_safe = false;
895 _monitor_top = bad_monitors;
896
897 if (log_is_enabled(Info, monitormismatch)(LogImpl<(LogTag::_monitormismatch), (LogTag::__NO_TAG), (
LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag
::__NO_TAG)>::is_level(LogLevel::Info))
) {
898 report_monitor_mismatch("monitor stack overflow");
899 }
900 return;
901 }
902 monitors()[_monitor_top++] = cts;
903}
904
905//
906// Interpretation handling methods
907//
908
909void GenerateOopMap::do_interpretation()
910{
911 // "i" is just for debugging, so we can detect cases where this loop is
912 // iterated more than once.
913 int i = 0;
914 do {
915#ifndef PRODUCT
916 if (TraceNewOopMapGeneration) {
917 tty->print("\n\nIteration #%d of do_interpretation loop, method:\n", i);
918 method()->print_name(tty);
919 tty->print("\n\n");
920 }
921#endif
922 _conflict = false;
923 _monitor_safe = true;
924 // init_state is now called from init_basic_blocks. The length of a
925 // state vector cannot be determined until we have made a pass through
926 // the bytecodes counting the possible monitor entries.
927 if (!_got_error) init_basic_blocks();
928 if (!_got_error) setup_method_entry_state();
929 if (!_got_error) interp_all();
930 if (!_got_error) rewrite_refval_conflicts();
931 i++;
932 } while (_conflict && !_got_error);
933}
934
935void GenerateOopMap::init_basic_blocks() {
936 // Note: Could consider reserving only the needed space for each BB's state
937 // (entry stack may not be of maximal height for every basic block).
938 // But cumbersome since we don't know the stack heights yet. (Nor the
939 // monitor stack heights...)
940
941 ALLOC_RESOURCE_ARRAY(_basic_blocks, BasicBlock, _bb_count)_basic_blocks = (BasicBlock*) resource_allocate_bytes((_bb_count
) * sizeof(BasicBlock), AllocFailStrategy::RETURN_NULL); if (
_basic_blocks == __null) { report_error("Cannot reserve enough memory to analyze this method"
); return; }
;
942
943 // Make a pass through the bytecodes. Count the number of monitorenters.
944 // This can be used an upper bound on the monitor stack depth in programs
945 // which obey stack discipline with their monitor usage. Initialize the
946 // known information about basic blocks.
947 BytecodeStream j(_method);
948 Bytecodes::Code bytecode;
949
950 int bbNo = 0;
951 int monitor_count = 0;
952 int prev_bci = -1;
953 while( (bytecode = j.next()) >= 0) {
Although the value stored to 'bytecode' is used in the enclosing expression, the value is never actually read from 'bytecode'
954 if (j.code() == Bytecodes::_monitorenter) {
955 monitor_count++;
956 }
957
958 int bci = j.bci();
959 if (is_bb_header(bci)) {
960 // Initialize the basicblock structure
961 BasicBlock *bb = _basic_blocks + bbNo;
962 bb->_bci = bci;
963 bb->_max_locals = _max_locals;
964 bb->_max_stack = _max_stack;
965 bb->set_changed(false);
966 bb->_stack_top = BasicBlock::_dead_basic_block; // Initialize all basicblocks are dead.
967 bb->_monitor_top = bad_monitors;
968
969 if (bbNo > 0) {
970 _basic_blocks[bbNo - 1]._end_bci = prev_bci;
971 }
972
973 bbNo++;
974 }
975 // Remember prevous bci.
976 prev_bci = bci;
977 }
978 // Set
979 _basic_blocks[bbNo-1]._end_bci = prev_bci;
980
981
982 // Check that the correct number of basicblocks was found
983 if (bbNo !=_bb_count) {
984 if (bbNo < _bb_count) {
985 verify_error("jump into the middle of instruction?");
986 return;
987 } else {
988 verify_error("extra basic blocks - should not happen?");
989 return;
990 }
991 }
992
993 _max_monitors = monitor_count;
994
995 // Now that we have a bound on the depth of the monitor stack, we can
996 // initialize the CellTypeState-related information.
997 init_state();
998
999 // We allocate space for all state-vectors for all basicblocks in one huge
1000 // chunk. Then in the next part of the code, we set a pointer in each
1001 // _basic_block that points to each piece.
1002
1003 // The product of bbNo and _state_len can get large if there are lots of
1004 // basic blocks and stack/locals/monitors. Need to check to make sure
1005 // we don't overflow the capacity of a pointer.
1006 if ((unsigned)bbNo > UINTPTR_MAX(18446744073709551615UL) / sizeof(CellTypeState) / _state_len) {
1007 report_error("The amount of memory required to analyze this method "
1008 "exceeds addressable range");
1009 return;
1010 }
1011
1012 CellTypeState *basicBlockState;
1013 ALLOC_RESOURCE_ARRAY(basicBlockState, CellTypeState, bbNo * _state_len)basicBlockState = (CellTypeState*) resource_allocate_bytes((bbNo
* _state_len) * sizeof(CellTypeState), AllocFailStrategy::RETURN_NULL
); if (basicBlockState == __null) { report_error("Cannot reserve enough memory to analyze this method"
); return; }
;
1014 memset(basicBlockState, 0, bbNo * _state_len * sizeof(CellTypeState));
1015
1016 // Make a pass over the basicblocks and assign their state vectors.
1017 for (int blockNum=0; blockNum < bbNo; blockNum++) {
1018 BasicBlock *bb = _basic_blocks + blockNum;
1019 bb->_state = basicBlockState + blockNum * _state_len;
1020
1021#ifdef ASSERT1
1022 if (blockNum + 1 < bbNo) {
1023 address bcp = _method->bcp_from(bb->_end_bci);
1024 int bc_len = Bytecodes::java_length_at(_method(), bcp);
1025 assert(bb->_end_bci + bc_len == bb[1]._bci, "unmatched bci info in basicblock")do { if (!(bb->_end_bci + bc_len == bb[1]._bci)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1025, "assert(" "bb->_end_bci + bc_len == bb[1]._bci" ") failed"
, "unmatched bci info in basicblock"); ::breakpoint(); } } while
(0)
;
1026 }
1027#endif
1028 }
1029#ifdef ASSERT1
1030 { BasicBlock *bb = &_basic_blocks[bbNo-1];
1031 address bcp = _method->bcp_from(bb->_end_bci);
1032 int bc_len = Bytecodes::java_length_at(_method(), bcp);
1033 assert(bb->_end_bci + bc_len == _method->code_size(), "wrong end bci")do { if (!(bb->_end_bci + bc_len == _method->code_size(
))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1033, "assert(" "bb->_end_bci + bc_len == _method->code_size()"
") failed", "wrong end bci"); ::breakpoint(); } } while (0)
;
1034 }
1035#endif
1036
1037 // Mark all alive blocks
1038 mark_reachable_code();
1039}
1040
1041void GenerateOopMap::setup_method_entry_state() {
1042
1043 // Initialize all locals to 'uninit' and set stack-height to 0
1044 make_context_uninitialized();
1045
1046 // Initialize CellState type of arguments
1047 methodsig_to_effect(method()->signature(), method()->is_static(), vars());
1048
1049 // If some references must be pre-assigned to null, then set that up
1050 initialize_vars();
1051
1052 // This is the start state
1053 merge_state_into_bb(&_basic_blocks[0]);
1054
1055 assert(_basic_blocks[0].changed(), "we are not getting off the ground")do { if (!(_basic_blocks[0].changed())) { (*g_assert_poison) =
'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1055, "assert(" "_basic_blocks[0].changed()" ") failed", "we are not getting off the ground"
); ::breakpoint(); } } while (0)
;
1056}
1057
1058// The instruction at bci is changing size by "delta". Update the basic blocks.
1059void GenerateOopMap::update_basic_blocks(int bci, int delta,
1060 int new_method_size) {
1061 assert(new_method_size >= method()->code_size() + delta,do { if (!(new_method_size >= method()->code_size() + delta
)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1062, "assert(" "new_method_size >= method()->code_size() + delta"
") failed", "new method size is too small"); ::breakpoint();
} } while (0)
1062 "new method size is too small")do { if (!(new_method_size >= method()->code_size() + delta
)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1062, "assert(" "new_method_size >= method()->code_size() + delta"
") failed", "new method size is too small"); ::breakpoint();
} } while (0)
;
1063
1064 _bb_hdr_bits.reinitialize(new_method_size);
1065
1066 for(int k = 0; k < _bb_count; k++) {
1067 if (_basic_blocks[k]._bci > bci) {
1068 _basic_blocks[k]._bci += delta;
1069 _basic_blocks[k]._end_bci += delta;
1070 }
1071 _bb_hdr_bits.at_put(_basic_blocks[k]._bci, true);
1072 }
1073}
1074
1075//
1076// Initvars handling
1077//
1078
1079void GenerateOopMap::initialize_vars() {
1080 for (int k = 0; k < _init_vars->length(); k++)
1081 _state[_init_vars->at(k)] = CellTypeState::make_slot_ref(k);
1082}
1083
1084void GenerateOopMap::add_to_ref_init_set(int localNo) {
1085
1086 if (TraceNewOopMapGeneration)
1087 tty->print_cr("Added init vars: %d", localNo);
1088
1089 // Is it already in the set?
1090 if (_init_vars->contains(localNo) )
1091 return;
1092
1093 _init_vars->append(localNo);
1094}
1095
1096//
1097// Interpreration code
1098//
1099
1100void GenerateOopMap::interp_all() {
1101 bool change = true;
1102
1103 while (change && !_got_error) {
1104 change = false;
1105 for (int i = 0; i < _bb_count && !_got_error; i++) {
1106 BasicBlock *bb = &_basic_blocks[i];
1107 if (bb->changed()) {
1108 if (_got_error) return;
1109 change = true;
1110 bb->set_changed(false);
1111 interp_bb(bb);
1112 }
1113 }
1114 }
1115}
1116
1117void GenerateOopMap::interp_bb(BasicBlock *bb) {
1118
1119 // We do not want to do anything in case the basic-block has not been initialized. This
1120 // will happen in the case where there is dead-code hang around in a method.
1121 assert(bb->is_reachable(), "should be reachable or deadcode exist")do { if (!(bb->is_reachable())) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1121, "assert(" "bb->is_reachable()" ") failed", "should be reachable or deadcode exist"
); ::breakpoint(); } } while (0)
;
1122 restore_state(bb);
1123
1124 BytecodeStream itr(_method);
1125
1126 // Set iterator interval to be the current basicblock
1127 int lim_bci = next_bb_start_pc(bb);
1128 itr.set_interval(bb->_bci, lim_bci);
1129 assert(lim_bci != bb->_bci, "must be at least one instruction in a basicblock")do { if (!(lim_bci != bb->_bci)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1129, "assert(" "lim_bci != bb->_bci" ") failed", "must be at least one instruction in a basicblock"
); ::breakpoint(); } } while (0)
;
1130 itr.next(); // read first instruction
1131
1132 // Iterates through all bytecodes except the last in a basic block.
1133 // We handle the last one special, since there is controlflow change.
1134 while(itr.next_bci() < lim_bci && !_got_error) {
1135 if (_has_exceptions || _monitor_top != 0) {
1136 // We do not need to interpret the results of exceptional
1137 // continuation from this instruction when the method has no
1138 // exception handlers and the monitor stack is currently
1139 // empty.
1140 do_exception_edge(&itr);
1141 }
1142 interp1(&itr);
1143 itr.next();
1144 }
1145
1146 // Handle last instruction.
1147 if (!_got_error) {
1148 assert(itr.next_bci() == lim_bci, "must point to end")do { if (!(itr.next_bci() == lim_bci)) { (*g_assert_poison) =
'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1148, "assert(" "itr.next_bci() == lim_bci" ") failed", "must point to end"
); ::breakpoint(); } } while (0)
;
1149 if (_has_exceptions || _monitor_top != 0) {
1150 do_exception_edge(&itr);
1151 }
1152 interp1(&itr);
1153
1154 bool fall_through = jump_targets_do(&itr, GenerateOopMap::merge_state, NULL__null);
1155 if (_got_error) return;
1156
1157 if (itr.code() == Bytecodes::_ret) {
1158 assert(!fall_through, "cannot be set if ret instruction")do { if (!(!fall_through)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1158, "assert(" "!fall_through" ") failed", "cannot be set if ret instruction"
); ::breakpoint(); } } while (0)
;
1159 // Automatically handles 'wide' ret indicies
1160 ret_jump_targets_do(&itr, GenerateOopMap::merge_state, itr.get_index(), NULL__null);
1161 } else if (fall_through) {
1162 // Hit end of BB, but the instr. was a fall-through instruction,
1163 // so perform transition as if the BB ended in a "jump".
1164 if (lim_bci != bb[1]._bci) {
1165 verify_error("bytecodes fell through last instruction");
1166 return;
1167 }
1168 merge_state_into_bb(bb + 1);
1169 }
1170 }
1171}
1172
1173void GenerateOopMap::do_exception_edge(BytecodeStream* itr) {
1174 // Only check exception edge, if bytecode can trap
1175 if (!Bytecodes::can_trap(itr->code())) return;
1176 switch (itr->code()) {
1177 case Bytecodes::_aload_0:
1178 // These bytecodes can trap for rewriting. We need to assume that
1179 // they do not throw exceptions to make the monitor analysis work.
1180 return;
1181
1182 case Bytecodes::_ireturn:
1183 case Bytecodes::_lreturn:
1184 case Bytecodes::_freturn:
1185 case Bytecodes::_dreturn:
1186 case Bytecodes::_areturn:
1187 case Bytecodes::_return:
1188 // If the monitor stack height is not zero when we leave the method,
1189 // then we are either exiting with a non-empty stack or we have
1190 // found monitor trouble earlier in our analysis. In either case,
1191 // assume an exception could be taken here.
1192 if (_monitor_top == 0) {
1193 return;
1194 }
1195 break;
1196
1197 case Bytecodes::_monitorexit:
1198 // If the monitor stack height is bad_monitors, then we have detected a
1199 // monitor matching problem earlier in the analysis. If the
1200 // monitor stack height is 0, we are about to pop a monitor
1201 // off of an empty stack. In either case, the bytecode
1202 // could throw an exception.
1203 if (_monitor_top != bad_monitors && _monitor_top != 0) {
1204 return;
1205 }
1206 break;
1207
1208 default:
1209 break;
1210 }
1211
1212 if (_has_exceptions) {
1213 int bci = itr->bci();
1214 ExceptionTable exct(method());
1215 for(int i = 0; i< exct.length(); i++) {
1216 int start_pc = exct.start_pc(i);
1217 int end_pc = exct.end_pc(i);
1218 int handler_pc = exct.handler_pc(i);
1219 int catch_type = exct.catch_type_index(i);
1220
1221 if (start_pc <= bci && bci < end_pc) {
1222 BasicBlock *excBB = get_basic_block_at(handler_pc);
1223 guarantee(excBB != NULL, "no basic block for exception")do { if (!(excBB != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1223, "guarantee(" "excBB != NULL" ") failed", "no basic block for exception"
); ::breakpoint(); } } while (0)
;
1224 CellTypeState *excStk = excBB->stack();
1225 CellTypeState *cOpStck = stack();
1226 CellTypeState cOpStck_0 = cOpStck[0];
1227 int cOpStackTop = _stack_top;
1228
1229 // Exception stacks are always the same.
1230 assert(method()->max_stack() > 0, "sanity check")do { if (!(method()->max_stack() > 0)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1230, "assert(" "method()->max_stack() > 0" ") failed"
, "sanity check"); ::breakpoint(); } } while (0)
;
1231
1232 // We remembered the size and first element of "cOpStck"
1233 // above; now we temporarily set them to the appropriate
1234 // values for an exception handler. */
1235 cOpStck[0] = CellTypeState::make_slot_ref(_max_locals);
1236 _stack_top = 1;
1237
1238 merge_state_into_bb(excBB);
1239
1240 // Now undo the temporary change.
1241 cOpStck[0] = cOpStck_0;
1242 _stack_top = cOpStackTop;
1243
1244 // If this is a "catch all" handler, then we do not need to
1245 // consider any additional handlers.
1246 if (catch_type == 0) {
1247 return;
1248 }
1249 }
1250 }
1251 }
1252
1253 // It is possible that none of the exception handlers would have caught
1254 // the exception. In this case, we will exit the method. We must
1255 // ensure that the monitor stack is empty in this case.
1256 if (_monitor_top == 0) {
1257 return;
1258 }
1259
1260 // We pessimistically assume that this exception can escape the
1261 // method. (It is possible that it will always be caught, but
1262 // we don't care to analyse the types of the catch clauses.)
1263
1264 // We don't set _monitor_top to bad_monitors because there are no successors
1265 // to this exceptional exit.
1266
1267 if (log_is_enabled(Info, monitormismatch)(LogImpl<(LogTag::_monitormismatch), (LogTag::__NO_TAG), (
LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag
::__NO_TAG)>::is_level(LogLevel::Info))
&& _monitor_safe) {
1268 // We check _monitor_safe so that we only report the first mismatched
1269 // exceptional exit.
1270 report_monitor_mismatch("non-empty monitor stack at exceptional exit");
1271 }
1272 _monitor_safe = false;
1273
1274}
1275
1276void GenerateOopMap::report_monitor_mismatch(const char *msg) {
1277 ResourceMark rm;
1278 LogStream ls(Log(monitormismatch)LogImpl<(LogTag::_monitormismatch), (LogTag::__NO_TAG), (LogTag
::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::
__NO_TAG)>
::info());
1279 ls.print("Monitor mismatch in method ");
1280 method()->print_short_name(&ls);
1281 ls.print_cr(": %s", msg);
1282}
1283
1284void GenerateOopMap::print_states(outputStream *os,
1285 CellTypeState* vec, int num) {
1286 for (int i = 0; i < num; i++) {
1287 vec[i].print(tty);
1288 }
1289}
1290
1291// Print the state values at the current bytecode.
1292void GenerateOopMap::print_current_state(outputStream *os,
1293 BytecodeStream *currentBC,
1294 bool detailed) {
1295 if (detailed) {
1296 os->print(" %4d vars = ", currentBC->bci());
1297 print_states(os, vars(), _max_locals);
1298 os->print(" %s", Bytecodes::name(currentBC->code()));
1299 } else {
1300 os->print(" %4d vars = '%s' ", currentBC->bci(), state_vec_to_string(vars(), _max_locals));
1301 os->print(" stack = '%s' ", state_vec_to_string(stack(), _stack_top));
1302 if (_monitor_top != bad_monitors) {
1303 os->print(" monitors = '%s' \t%s", state_vec_to_string(monitors(), _monitor_top), Bytecodes::name(currentBC->code()));
1304 } else {
1305 os->print(" [bad monitor stack]");
1306 }
1307 }
1308
1309 switch(currentBC->code()) {
1310 case Bytecodes::_invokevirtual:
1311 case Bytecodes::_invokespecial:
1312 case Bytecodes::_invokestatic:
1313 case Bytecodes::_invokedynamic:
1314 case Bytecodes::_invokeinterface: {
1315 int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2_cpcache();
1316 ConstantPool* cp = method()->constants();
1317 int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx);
1318 int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);
1319 Symbol* signature = cp->symbol_at(signatureIdx);
1320 os->print("%s", signature->as_C_string());
1321 }
1322 default:
1323 break;
1324 }
1325
1326 if (detailed) {
1327 os->cr();
1328 os->print(" stack = ");
1329 print_states(os, stack(), _stack_top);
1330 os->cr();
1331 if (_monitor_top != bad_monitors) {
1332 os->print(" monitors = ");
1333 print_states(os, monitors(), _monitor_top);
1334 } else {
1335 os->print(" [bad monitor stack]");
1336 }
1337 }
1338
1339 os->cr();
1340}
1341
1342// Sets the current state to be the state after executing the
1343// current instruction, starting in the current state.
1344void GenerateOopMap::interp1(BytecodeStream *itr) {
1345 if (TraceNewOopMapGeneration) {
1346 print_current_state(tty, itr, TraceNewOopMapGenerationDetailed);
1347 }
1348
1349 // Should we report the results? Result is reported *before* the instruction at the current bci is executed.
1350 // However, not for calls. For calls we do not want to include the arguments, so we postpone the reporting until
1351 // they have been popped (in method ppl).
1352 if (_report_result == true) {
1353 switch(itr->code()) {
1354 case Bytecodes::_invokevirtual:
1355 case Bytecodes::_invokespecial:
1356 case Bytecodes::_invokestatic:
1357 case Bytecodes::_invokedynamic:
1358 case Bytecodes::_invokeinterface:
1359 _itr_send = itr;
1360 _report_result_for_send = true;
1361 break;
1362 default:
1363 fill_stackmap_for_opcodes(itr, vars(), stack(), _stack_top);
1364 break;
1365 }
1366 }
1367
1368 // abstract interpretation of current opcode
1369 switch(itr->code()) {
1370 case Bytecodes::_nop: break;
1371 case Bytecodes::_goto: break;
1372 case Bytecodes::_goto_w: break;
1373 case Bytecodes::_iinc: break;
1374 case Bytecodes::_return: do_return_monitor_check();
1375 break;
1376
1377 case Bytecodes::_aconst_null:
1378 case Bytecodes::_new: ppush1(CellTypeState::make_line_ref(itr->bci()));
1379 break;
1380
1381 case Bytecodes::_iconst_m1:
1382 case Bytecodes::_iconst_0:
1383 case Bytecodes::_iconst_1:
1384 case Bytecodes::_iconst_2:
1385 case Bytecodes::_iconst_3:
1386 case Bytecodes::_iconst_4:
1387 case Bytecodes::_iconst_5:
1388 case Bytecodes::_fconst_0:
1389 case Bytecodes::_fconst_1:
1390 case Bytecodes::_fconst_2:
1391 case Bytecodes::_bipush:
1392 case Bytecodes::_sipush: ppush1(valCTS); break;
1393
1394 case Bytecodes::_lconst_0:
1395 case Bytecodes::_lconst_1:
1396 case Bytecodes::_dconst_0:
1397 case Bytecodes::_dconst_1: ppush(vvCTS); break;
1398
1399 case Bytecodes::_ldc2_w: ppush(vvCTS); break;
1400
1401 case Bytecodes::_ldc: // fall through:
1402 case Bytecodes::_ldc_w: do_ldc(itr->bci()); break;
1403
1404 case Bytecodes::_iload:
1405 case Bytecodes::_fload: ppload(vCTS, itr->get_index()); break;
1406
1407 case Bytecodes::_lload:
1408 case Bytecodes::_dload: ppload(vvCTS,itr->get_index()); break;
1409
1410 case Bytecodes::_aload: ppload(rCTS, itr->get_index()); break;
1411
1412 case Bytecodes::_iload_0:
1413 case Bytecodes::_fload_0: ppload(vCTS, 0); break;
1414 case Bytecodes::_iload_1:
1415 case Bytecodes::_fload_1: ppload(vCTS, 1); break;
1416 case Bytecodes::_iload_2:
1417 case Bytecodes::_fload_2: ppload(vCTS, 2); break;
1418 case Bytecodes::_iload_3:
1419 case Bytecodes::_fload_3: ppload(vCTS, 3); break;
1420
1421 case Bytecodes::_lload_0:
1422 case Bytecodes::_dload_0: ppload(vvCTS, 0); break;
1423 case Bytecodes::_lload_1:
1424 case Bytecodes::_dload_1: ppload(vvCTS, 1); break;
1425 case Bytecodes::_lload_2:
1426 case Bytecodes::_dload_2: ppload(vvCTS, 2); break;
1427 case Bytecodes::_lload_3:
1428 case Bytecodes::_dload_3: ppload(vvCTS, 3); break;
1429
1430 case Bytecodes::_aload_0: ppload(rCTS, 0); break;
1431 case Bytecodes::_aload_1: ppload(rCTS, 1); break;
1432 case Bytecodes::_aload_2: ppload(rCTS, 2); break;
1433 case Bytecodes::_aload_3: ppload(rCTS, 3); break;
1434
1435 case Bytecodes::_iaload:
1436 case Bytecodes::_faload:
1437 case Bytecodes::_baload:
1438 case Bytecodes::_caload:
1439 case Bytecodes::_saload: pp(vrCTS, vCTS); break;
1440
1441 case Bytecodes::_laload: pp(vrCTS, vvCTS); break;
1442 case Bytecodes::_daload: pp(vrCTS, vvCTS); break;
1443
1444 case Bytecodes::_aaload: pp_new_ref(vrCTS, itr->bci()); break;
1445
1446 case Bytecodes::_istore:
1447 case Bytecodes::_fstore: ppstore(vCTS, itr->get_index()); break;
1448
1449 case Bytecodes::_lstore:
1450 case Bytecodes::_dstore: ppstore(vvCTS, itr->get_index()); break;
1451
1452 case Bytecodes::_astore: do_astore(itr->get_index()); break;
1453
1454 case Bytecodes::_istore_0:
1455 case Bytecodes::_fstore_0: ppstore(vCTS, 0); break;
1456 case Bytecodes::_istore_1:
1457 case Bytecodes::_fstore_1: ppstore(vCTS, 1); break;
1458 case Bytecodes::_istore_2:
1459 case Bytecodes::_fstore_2: ppstore(vCTS, 2); break;
1460 case Bytecodes::_istore_3:
1461 case Bytecodes::_fstore_3: ppstore(vCTS, 3); break;
1462
1463 case Bytecodes::_lstore_0:
1464 case Bytecodes::_dstore_0: ppstore(vvCTS, 0); break;
1465 case Bytecodes::_lstore_1:
1466 case Bytecodes::_dstore_1: ppstore(vvCTS, 1); break;
1467 case Bytecodes::_lstore_2:
1468 case Bytecodes::_dstore_2: ppstore(vvCTS, 2); break;
1469 case Bytecodes::_lstore_3:
1470 case Bytecodes::_dstore_3: ppstore(vvCTS, 3); break;
1471
1472 case Bytecodes::_astore_0: do_astore(0); break;
1473 case Bytecodes::_astore_1: do_astore(1); break;
1474 case Bytecodes::_astore_2: do_astore(2); break;
1475 case Bytecodes::_astore_3: do_astore(3); break;
1476
1477 case Bytecodes::_iastore:
1478 case Bytecodes::_fastore:
1479 case Bytecodes::_bastore:
1480 case Bytecodes::_castore:
1481 case Bytecodes::_sastore: ppop(vvrCTS); break;
1482 case Bytecodes::_lastore:
1483 case Bytecodes::_dastore: ppop(vvvrCTS); break;
1484 case Bytecodes::_aastore: ppop(rvrCTS); break;
1485
1486 case Bytecodes::_pop: ppop_any(1); break;
1487 case Bytecodes::_pop2: ppop_any(2); break;
1488
1489 case Bytecodes::_dup: ppdupswap(1, "11"); break;
1490 case Bytecodes::_dup_x1: ppdupswap(2, "121"); break;
1491 case Bytecodes::_dup_x2: ppdupswap(3, "1321"); break;
1492 case Bytecodes::_dup2: ppdupswap(2, "2121"); break;
1493 case Bytecodes::_dup2_x1: ppdupswap(3, "21321"); break;
1494 case Bytecodes::_dup2_x2: ppdupswap(4, "214321"); break;
1495 case Bytecodes::_swap: ppdupswap(2, "12"); break;
1496
1497 case Bytecodes::_iadd:
1498 case Bytecodes::_fadd:
1499 case Bytecodes::_isub:
1500 case Bytecodes::_fsub:
1501 case Bytecodes::_imul:
1502 case Bytecodes::_fmul:
1503 case Bytecodes::_idiv:
1504 case Bytecodes::_fdiv:
1505 case Bytecodes::_irem:
1506 case Bytecodes::_frem:
1507 case Bytecodes::_ishl:
1508 case Bytecodes::_ishr:
1509 case Bytecodes::_iushr:
1510 case Bytecodes::_iand:
1511 case Bytecodes::_ior:
1512 case Bytecodes::_ixor:
1513 case Bytecodes::_l2f:
1514 case Bytecodes::_l2i:
1515 case Bytecodes::_d2f:
1516 case Bytecodes::_d2i:
1517 case Bytecodes::_fcmpl:
1518 case Bytecodes::_fcmpg: pp(vvCTS, vCTS); break;
1519
1520 case Bytecodes::_ladd:
1521 case Bytecodes::_dadd:
1522 case Bytecodes::_lsub:
1523 case Bytecodes::_dsub:
1524 case Bytecodes::_lmul:
1525 case Bytecodes::_dmul:
1526 case Bytecodes::_ldiv:
1527 case Bytecodes::_ddiv:
1528 case Bytecodes::_lrem:
1529 case Bytecodes::_drem:
1530 case Bytecodes::_land:
1531 case Bytecodes::_lor:
1532 case Bytecodes::_lxor: pp(vvvvCTS, vvCTS); break;
1533
1534 case Bytecodes::_ineg:
1535 case Bytecodes::_fneg:
1536 case Bytecodes::_i2f:
1537 case Bytecodes::_f2i:
1538 case Bytecodes::_i2c:
1539 case Bytecodes::_i2s:
1540 case Bytecodes::_i2b: pp(vCTS, vCTS); break;
1541
1542 case Bytecodes::_lneg:
1543 case Bytecodes::_dneg:
1544 case Bytecodes::_l2d:
1545 case Bytecodes::_d2l: pp(vvCTS, vvCTS); break;
1546
1547 case Bytecodes::_lshl:
1548 case Bytecodes::_lshr:
1549 case Bytecodes::_lushr: pp(vvvCTS, vvCTS); break;
1550
1551 case Bytecodes::_i2l:
1552 case Bytecodes::_i2d:
1553 case Bytecodes::_f2l:
1554 case Bytecodes::_f2d: pp(vCTS, vvCTS); break;
1555
1556 case Bytecodes::_lcmp: pp(vvvvCTS, vCTS); break;
1557 case Bytecodes::_dcmpl:
1558 case Bytecodes::_dcmpg: pp(vvvvCTS, vCTS); break;
1559
1560 case Bytecodes::_ifeq:
1561 case Bytecodes::_ifne:
1562 case Bytecodes::_iflt:
1563 case Bytecodes::_ifge:
1564 case Bytecodes::_ifgt:
1565 case Bytecodes::_ifle:
1566 case Bytecodes::_tableswitch: ppop1(valCTS);
1567 break;
1568 case Bytecodes::_ireturn:
1569 case Bytecodes::_freturn: do_return_monitor_check();
1570 ppop1(valCTS);
1571 break;
1572 case Bytecodes::_if_icmpeq:
1573 case Bytecodes::_if_icmpne:
1574 case Bytecodes::_if_icmplt:
1575 case Bytecodes::_if_icmpge:
1576 case Bytecodes::_if_icmpgt:
1577 case Bytecodes::_if_icmple: ppop(vvCTS);
1578 break;
1579
1580 case Bytecodes::_lreturn: do_return_monitor_check();
1581 ppop(vvCTS);
1582 break;
1583
1584 case Bytecodes::_dreturn: do_return_monitor_check();
1585 ppop(vvCTS);
1586 break;
1587
1588 case Bytecodes::_if_acmpeq:
1589 case Bytecodes::_if_acmpne: ppop(rrCTS); break;
1590
1591 case Bytecodes::_jsr: do_jsr(itr->dest()); break;
1592 case Bytecodes::_jsr_w: do_jsr(itr->dest_w()); break;
1593
1594 case Bytecodes::_getstatic: do_field(true, true, itr->get_index_u2_cpcache(), itr->bci()); break;
1595 case Bytecodes::_putstatic: do_field(false, true, itr->get_index_u2_cpcache(), itr->bci()); break;
1596 case Bytecodes::_getfield: do_field(true, false, itr->get_index_u2_cpcache(), itr->bci()); break;
1597 case Bytecodes::_putfield: do_field(false, false, itr->get_index_u2_cpcache(), itr->bci()); break;
1598
1599 case Bytecodes::_invokevirtual:
1600 case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_u2_cpcache(), itr->bci()); break;
1601 case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_u2_cpcache(), itr->bci()); break;
1602 case Bytecodes::_invokedynamic: do_method(true, false, itr->get_index_u4(), itr->bci()); break;
1603 case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_u2_cpcache(), itr->bci()); break;
1604 case Bytecodes::_newarray:
1605 case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break;
1606 case Bytecodes::_checkcast: do_checkcast(); break;
1607 case Bytecodes::_arraylength:
1608 case Bytecodes::_instanceof: pp(rCTS, vCTS); break;
1609 case Bytecodes::_monitorenter: do_monitorenter(itr->bci()); break;
1610 case Bytecodes::_monitorexit: do_monitorexit(itr->bci()); break;
1611
1612 case Bytecodes::_athrow: // handled by do_exception_edge() BUT ...
1613 // vlh(apple): do_exception_edge() does not get
1614 // called if method has no exception handlers
1615 if ((!_has_exceptions) && (_monitor_top > 0)) {
1616 _monitor_safe = false;
1617 }
1618 break;
1619
1620 case Bytecodes::_areturn: do_return_monitor_check();
1621 ppop1(refCTS);
1622 break;
1623 case Bytecodes::_ifnull:
1624 case Bytecodes::_ifnonnull: ppop1(refCTS); break;
1625 case Bytecodes::_multianewarray: do_multianewarray(*(itr->bcp()+3), itr->bci()); break;
1626
1627 case Bytecodes::_wide: fatal("Iterator should skip this bytecode")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1627, "Iterator should skip this bytecode"); ::breakpoint()
; } while (0)
; break;
1628 case Bytecodes::_ret: break;
1629
1630 // Java opcodes
1631 case Bytecodes::_lookupswitch: ppop1(valCTS); break;
1632
1633 default:
1634 tty->print("unexpected opcode: %d\n", itr->code());
1635 ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here(
"/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1635); ::breakpoint(); } while (0)
;
1636 break;
1637 }
1638}
1639
1640void GenerateOopMap::check_type(CellTypeState expected, CellTypeState actual) {
1641 if (!expected.equal_kind(actual)) {
1642 verify_error("wrong type on stack (found: %c expected: %c)", actual.to_char(), expected.to_char());
1643 }
1644}
1645
1646void GenerateOopMap::ppstore(CellTypeState *in, int loc_no) {
1647 while(!(*in).is_bottom()) {
1648 CellTypeState expected =*in++;
1649 CellTypeState actual = pop();
1650 check_type(expected, actual);
1651 assert(loc_no >= 0, "sanity check")do { if (!(loc_no >= 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1651, "assert(" "loc_no >= 0" ") failed", "sanity check"
); ::breakpoint(); } } while (0)
;
1652 set_var(loc_no++, actual);
1653 }
1654}
1655
1656void GenerateOopMap::ppload(CellTypeState *out, int loc_no) {
1657 while(!(*out).is_bottom()) {
1658 CellTypeState out1 = *out++;
1659 CellTypeState vcts = get_var(loc_no);
1660 assert(out1.can_be_reference() || out1.can_be_value(),do { if (!(out1.can_be_reference() || out1.can_be_value())) {
(*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1661, "assert(" "out1.can_be_reference() || out1.can_be_value()"
") failed", "can only load refs. and values."); ::breakpoint
(); } } while (0)
1661 "can only load refs. and values.")do { if (!(out1.can_be_reference() || out1.can_be_value())) {
(*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1661, "assert(" "out1.can_be_reference() || out1.can_be_value()"
") failed", "can only load refs. and values."); ::breakpoint
(); } } while (0)
;
1662 if (out1.is_reference()) {
1663 assert(loc_no>=0, "sanity check")do { if (!(loc_no>=0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1663, "assert(" "loc_no>=0" ") failed", "sanity check");
::breakpoint(); } } while (0)
;
1664 if (!vcts.is_reference()) {
1665 // We were asked to push a reference, but the type of the
1666 // variable can be something else
1667 _conflict = true;
1668 if (vcts.can_be_uninit()) {
1669 // It is a ref-uninit conflict (at least). If there are other
1670 // problems, we'll get them in the next round
1671 add_to_ref_init_set(loc_no);
1672 vcts = out1;
1673 } else {
1674 // It wasn't a ref-uninit conflict. So must be a
1675 // ref-val or ref-pc conflict. Split the variable.
1676 record_refval_conflict(loc_no);
1677 vcts = out1;
1678 }
1679 push(out1); // recover...
1680 } else {
1681 push(vcts); // preserve reference.
1682 }
1683 // Otherwise it is a conflict, but one that verification would
1684 // have caught if illegal. In particular, it can't be a topCTS
1685 // resulting from mergeing two difference pcCTS's since the verifier
1686 // would have rejected any use of such a merge.
1687 } else {
1688 push(out1); // handle val/init conflict
1689 }
1690 loc_no++;
1691 }
1692}
1693
1694void GenerateOopMap::ppdupswap(int poplen, const char *out) {
1695 CellTypeState actual[5];
1696 assert(poplen < 5, "this must be less than length of actual vector")do { if (!(poplen < 5)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1696, "assert(" "poplen < 5" ") failed", "this must be less than length of actual vector"
); ::breakpoint(); } } while (0)
;
1697
1698 // Pop all arguments.
1699 for (int i = 0; i < poplen; i++) {
1700 actual[i] = pop();
1701 }
1702 // Field _state is uninitialized when calling push.
1703 for (int i = poplen; i < 5; i++) {
1704 actual[i] = CellTypeState::uninit;
1705 }
1706
1707 // put them back
1708 char push_ch = *out++;
1709 while (push_ch != '\0') {
1710 int idx = push_ch - '1';
1711 assert(idx >= 0 && idx < poplen, "wrong arguments")do { if (!(idx >= 0 && idx < poplen)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1711, "assert(" "idx >= 0 && idx < poplen" ") failed"
, "wrong arguments"); ::breakpoint(); } } while (0)
;
1712 push(actual[idx]);
1713 push_ch = *out++;
1714 }
1715}
1716
1717void GenerateOopMap::ppop1(CellTypeState out) {
1718 CellTypeState actual = pop();
1719 check_type(out, actual);
1720}
1721
1722void GenerateOopMap::ppop(CellTypeState *out) {
1723 while (!(*out).is_bottom()) {
1724 ppop1(*out++);
1725 }
1726}
1727
1728void GenerateOopMap::ppush1(CellTypeState in) {
1729 assert(in.is_reference() | in.is_value(), "sanity check")do { if (!(in.is_reference() | in.is_value())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1729, "assert(" "in.is_reference() | in.is_value()" ") failed"
, "sanity check"); ::breakpoint(); } } while (0)
;
1730 push(in);
1731}
1732
1733void GenerateOopMap::ppush(CellTypeState *in) {
1734 while (!(*in).is_bottom()) {
1735 ppush1(*in++);
1736 }
1737}
1738
1739void GenerateOopMap::pp(CellTypeState *in, CellTypeState *out) {
1740 ppop(in);
1741 ppush(out);
1742}
1743
1744void GenerateOopMap::pp_new_ref(CellTypeState *in, int bci) {
1745 ppop(in);
1746 ppush1(CellTypeState::make_line_ref(bci));
1747}
1748
1749void GenerateOopMap::ppop_any(int poplen) {
1750 if (_stack_top >= poplen) {
1751 _stack_top -= poplen;
1752 } else {
1753 verify_error("stack underflow");
1754 }
1755}
1756
1757// Replace all occurences of the state 'match' with the state 'replace'
1758// in our current state vector.
1759void GenerateOopMap::replace_all_CTS_matches(CellTypeState match,
1760 CellTypeState replace) {
1761 int i;
1762 int len = _max_locals + _stack_top;
1763 bool change = false;
1764
1765 for (i = len - 1; i >= 0; i--) {
1766 if (match.equal(_state[i])) {
1767 _state[i] = replace;
1768 }
1769 }
1770
1771 if (_monitor_top > 0) {
1772 int base = _max_locals + _max_stack;
1773 len = base + _monitor_top;
1774 for (i = len - 1; i >= base; i--) {
1775 if (match.equal(_state[i])) {
1776 _state[i] = replace;
1777 }
1778 }
1779 }
1780}
1781
1782void GenerateOopMap::do_checkcast() {
1783 CellTypeState actual = pop();
1784 check_type(refCTS, actual);
1785 push(actual);
1786}
1787
1788void GenerateOopMap::do_monitorenter(int bci) {
1789 CellTypeState actual = pop();
1790 if (_monitor_top == bad_monitors) {
1791 return;
1792 }
1793
1794 // Bail out when we get repeated locks on an identical monitor. This case
1795 // isn't too hard to handle and can be made to work if supporting nested
1796 // redundant synchronized statements becomes a priority.
1797 //
1798 // See also "Note" in do_monitorexit(), below.
1799 if (actual.is_lock_reference()) {
1800 _monitor_top = bad_monitors;
1801 _monitor_safe = false;
1802
1803 if (log_is_enabled(Info, monitormismatch)(LogImpl<(LogTag::_monitormismatch), (LogTag::__NO_TAG), (
LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag
::__NO_TAG)>::is_level(LogLevel::Info))
) {
1804 report_monitor_mismatch("nested redundant lock -- bailout...");
1805 }
1806 return;
1807 }
1808
1809 CellTypeState lock = CellTypeState::make_lock_ref(bci);
1810 check_type(refCTS, actual);
1811 if (!actual.is_info_top()) {
1812 replace_all_CTS_matches(actual, lock);
1813 monitor_push(lock);
1814 }
1815}
1816
1817void GenerateOopMap::do_monitorexit(int bci) {
1818 CellTypeState actual = pop();
1819 if (_monitor_top == bad_monitors) {
1820 return;
1821 }
1822 check_type(refCTS, actual);
1823 CellTypeState expected = monitor_pop();
1824 if (!actual.is_lock_reference() || !expected.equal(actual)) {
1825 // The monitor we are exiting is not verifiably the one
1826 // on the top of our monitor stack. This causes a monitor
1827 // mismatch.
1828 _monitor_top = bad_monitors;
1829 _monitor_safe = false;
1830
1831 // We need to mark this basic block as changed so that
1832 // this monitorexit will be visited again. We need to
1833 // do this to ensure that we have accounted for the
1834 // possibility that this bytecode will throw an
1835 // exception.
1836 BasicBlock* bb = get_basic_block_containing(bci);
1837 guarantee(bb != NULL, "no basic block for bci")do { if (!(bb != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1837, "guarantee(" "bb != NULL" ") failed", "no basic block for bci"
); ::breakpoint(); } } while (0)
;
1838 bb->set_changed(true);
1839 bb->_monitor_top = bad_monitors;
1840
1841 if (log_is_enabled(Info, monitormismatch)(LogImpl<(LogTag::_monitormismatch), (LogTag::__NO_TAG), (
LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag
::__NO_TAG)>::is_level(LogLevel::Info))
) {
1842 report_monitor_mismatch("improper monitor pair");
1843 }
1844 } else {
1845 // This code is a fix for the case where we have repeated
1846 // locking of the same object in straightline code. We clear
1847 // out the lock when it is popped from the monitor stack
1848 // and replace it with an unobtrusive reference value that can
1849 // be locked again.
1850 //
1851 // Note: when generateOopMap is fixed to properly handle repeated,
1852 // nested, redundant locks on the same object, then this
1853 // fix will need to be removed at that time.
1854 replace_all_CTS_matches(actual, CellTypeState::make_line_ref(bci));
1855 }
1856}
1857
1858void GenerateOopMap::do_return_monitor_check() {
1859 if (_monitor_top > 0) {
1860 // The monitor stack must be empty when we leave the method
1861 // for the monitors to be properly matched.
1862 _monitor_safe = false;
1863
1864 // Since there are no successors to the *return bytecode, it
1865 // isn't necessary to set _monitor_top to bad_monitors.
1866
1867 if (log_is_enabled(Info, monitormismatch)(LogImpl<(LogTag::_monitormismatch), (LogTag::__NO_TAG), (
LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag
::__NO_TAG)>::is_level(LogLevel::Info))
) {
1868 report_monitor_mismatch("non-empty monitor stack at return");
1869 }
1870 }
1871}
1872
1873void GenerateOopMap::do_jsr(int targ_bci) {
1874 push(CellTypeState::make_addr(targ_bci));
1875}
1876
1877
1878
1879void GenerateOopMap::do_ldc(int bci) {
1880 Bytecode_loadconstant ldc(methodHandle(Thread::current(), method()), bci);
1881 ConstantPool* cp = method()->constants();
1882 constantTag tag = cp->tag_at(ldc.pool_index()); // idx is index in resolved_references
1883 BasicType bt = ldc.result_type();
1884#ifdef ASSERT1
1885 BasicType tag_bt = (tag.is_dynamic_constant() || tag.is_dynamic_constant_in_error()) ? bt : tag.basic_type();
1886 assert(bt == tag_bt, "same result")do { if (!(bt == tag_bt)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1886, "assert(" "bt == tag_bt" ") failed", "same result"); ::
breakpoint(); } } while (0)
;
1887#endif
1888 CellTypeState cts;
1889 if (is_reference_type(bt)) { // could be T_ARRAY with condy
1890 assert(!tag.is_string_index() && !tag.is_klass_index(), "Unexpected index tag")do { if (!(!tag.is_string_index() && !tag.is_klass_index
())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1890, "assert(" "!tag.is_string_index() && !tag.is_klass_index()"
") failed", "Unexpected index tag"); ::breakpoint(); } } while
(0)
;
1891 cts = CellTypeState::make_line_ref(bci);
1892 } else {
1893 cts = valCTS;
1894 }
1895 ppush1(cts);
1896}
1897
1898void GenerateOopMap::do_multianewarray(int dims, int bci) {
1899 assert(dims >= 1, "sanity check")do { if (!(dims >= 1)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1899, "assert(" "dims >= 1" ") failed", "sanity check");
::breakpoint(); } } while (0)
;
1900 for(int i = dims -1; i >=0; i--) {
1901 ppop1(valCTS);
1902 }
1903 ppush1(CellTypeState::make_line_ref(bci));
1904}
1905
1906void GenerateOopMap::do_astore(int idx) {
1907 CellTypeState r_or_p = pop();
1908 if (!r_or_p.is_address() && !r_or_p.is_reference()) {
1909 // We actually expected ref or pc, but we only report that we expected a ref. It does not
1910 // really matter (at least for now)
1911 verify_error("wrong type on stack (found: %c, expected: {pr})", r_or_p.to_char());
1912 return;
1913 }
1914 set_var(idx, r_or_p);
1915}
1916
1917// Copies bottom/zero terminated CTS string from "src" into "dst".
1918// Does NOT terminate with a bottom. Returns the number of cells copied.
1919int GenerateOopMap::copy_cts(CellTypeState *dst, CellTypeState *src) {
1920 int idx = 0;
1921 while (!src[idx].is_bottom()) {
1922 dst[idx] = src[idx];
1923 idx++;
1924 }
1925 return idx;
1926}
1927
1928void GenerateOopMap::do_field(int is_get, int is_static, int idx, int bci) {
1929 // Dig up signature for field in constant pool
1930 ConstantPool* cp = method()->constants();
1931 int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx);
1932 int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);
1933 Symbol* signature = cp->symbol_at(signatureIdx);
1934
1935 CellTypeState temp[4];
1936 CellTypeState *eff = signature_to_effect(signature, bci, temp);
1937
1938 CellTypeState in[4];
1939 CellTypeState *out;
1940 int i = 0;
1941
1942 if (is_get) {
1943 out = eff;
1944 } else {
1945 out = epsilonCTS;
1946 i = copy_cts(in, eff);
1947 }
1948 if (!is_static) in[i++] = CellTypeState::ref;
1949 in[i] = CellTypeState::bottom;
1950 assert(i<=3, "sanity check")do { if (!(i<=3)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1950, "assert(" "i<=3" ") failed", "sanity check"); ::breakpoint
(); } } while (0)
;
1951 pp(in, out);
1952}
1953
1954void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci) {
1955 // Dig up signature for field in constant pool
1956 ConstantPool* cp = _method->constants();
1957 Symbol* signature = cp->signature_ref_at(idx);
1958
1959 // Parse method signature
1960 CellTypeState out[4];
1961 CellTypeState in[MAXARGSIZE256+1]; // Includes result
1962 ComputeCallStack cse(signature);
1963
1964 // Compute return type
1965 int res_length= cse.compute_for_returntype(out);
1966
1967 // Temporary hack.
1968 if (out[0].equal(CellTypeState::ref) && out[1].equal(CellTypeState::bottom)) {
1969 out[0] = CellTypeState::make_line_ref(bci);
1970 }
1971
1972 assert(res_length<=4, "max value should be vv")do { if (!(res_length<=4)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1972, "assert(" "res_length<=4" ") failed", "max value should be vv"
); ::breakpoint(); } } while (0)
;
1973
1974 // Compute arguments
1975 int arg_length = cse.compute_for_parameters(is_static != 0, in);
1976 assert(arg_length<=MAXARGSIZE, "too many locals")do { if (!(arg_length<=256)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 1976, "assert(" "arg_length<=256" ") failed", "too many locals"
); ::breakpoint(); } } while (0)
;
1977
1978 // Pop arguments
1979 for (int i = arg_length - 1; i >= 0; i--) ppop1(in[i]);// Do args in reverse order.
1980
1981 // Report results
1982 if (_report_result_for_send == true) {
1983 fill_stackmap_for_opcodes(_itr_send, vars(), stack(), _stack_top);
1984 _report_result_for_send = false;
1985 }
1986
1987 // Push return address
1988 ppush(out);
1989}
1990
1991// This is used to parse the signature for fields, since they are very simple...
1992CellTypeState *GenerateOopMap::signature_to_effect(const Symbol* sig, int bci, CellTypeState *out) {
1993 // Object and array
1994 BasicType bt = Signature::basic_type(sig);
1995 if (is_reference_type(bt)) {
1996 out[0] = CellTypeState::make_line_ref(bci);
1997 out[1] = CellTypeState::bottom;
1998 return out;
1999 }
2000 if (is_double_word_type(bt)) return vvCTS; // Long and Double
2001 if (bt == T_VOID) return epsilonCTS; // Void
2002 return vCTS; // Otherwise
2003}
2004
2005uint64_t GenerateOopMap::_total_byte_count = 0;
2006elapsedTimer GenerateOopMap::_total_oopmap_time;
2007
2008// This function assumes "bcs" is at a "ret" instruction and that the vars
2009// state is valid for that instruction. Furthermore, the ret instruction
2010// must be the last instruction in "bb" (we store information about the
2011// "ret" in "bb").
2012void GenerateOopMap::ret_jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int varNo, int *data) {
2013 CellTypeState ra = vars()[varNo];
2014 if (!ra.is_good_address()) {
2015 verify_error("ret returns from two jsr subroutines?");
2016 return;
2017 }
2018 int target = ra.get_info();
2019
2020 RetTableEntry* rtEnt = _rt.find_jsrs_for_target(target);
2021 int bci = bcs->bci();
2022 for (int i = 0; i < rtEnt->nof_jsrs(); i++) {
2023 int target_bci = rtEnt->jsrs(i);
2024 // Make sure a jrtRet does not set the changed bit for dead basicblock.
2025 BasicBlock* jsr_bb = get_basic_block_containing(target_bci - 1);
2026 debug_only(BasicBlock* target_bb = &jsr_bb[1];)BasicBlock* target_bb = &jsr_bb[1];
2027 assert(target_bb == get_basic_block_at(target_bci), "wrong calc. of successor basicblock")do { if (!(target_bb == get_basic_block_at(target_bci))) { (*
g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2027, "assert(" "target_bb == get_basic_block_at(target_bci)"
") failed", "wrong calc. of successor basicblock"); ::breakpoint
(); } } while (0)
;
2028 bool alive = jsr_bb->is_alive();
2029 if (TraceNewOopMapGeneration) {
2030 tty->print("pc = %d, ret -> %d alive: %s\n", bci, target_bci, alive ? "true" : "false");
2031 }
2032 if (alive) jmpFct(this, target_bci, data);
2033 }
2034}
2035
2036//
2037// Debug method
2038//
2039char* GenerateOopMap::state_vec_to_string(CellTypeState* vec, int len) {
2040#ifdef ASSERT1
2041 int checklen = MAX3(_max_locals, _max_stack, _max_monitors) + 1;
2042 assert(len < checklen, "state_vec_buf overflow")do { if (!(len < checklen)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2042, "assert(" "len < checklen" ") failed", "state_vec_buf overflow"
); ::breakpoint(); } } while (0)
;
2043#endif
2044 for (int i = 0; i < len; i++) _state_vec_buf[i] = vec[i].to_char();
2045 _state_vec_buf[len] = 0;
2046 return _state_vec_buf;
2047}
2048
2049void GenerateOopMap::print_time() {
2050 tty->print_cr ("Accumulated oopmap times:");
2051 tty->print_cr ("---------------------------");
2052 tty->print_cr (" Total : %3.3f sec.", GenerateOopMap::_total_oopmap_time.seconds());
2053 tty->print_cr (" (%3.0f bytecodes per sec) ",
2054 GenerateOopMap::_total_byte_count / GenerateOopMap::_total_oopmap_time.seconds());
2055}
2056
2057//
2058// ============ Main Entry Point ===========
2059//
2060GenerateOopMap::GenerateOopMap(const methodHandle& method) {
2061 // We have to initialize all variables here, that can be queried directly
2062 _method = method;
2063 _max_locals=0;
2064 _init_vars = NULL__null;
2065
2066#ifndef PRODUCT
2067 // If we are doing a detailed trace, include the regular trace information.
2068 if (TraceNewOopMapGenerationDetailed) {
2069 TraceNewOopMapGeneration = true;
2070 }
2071#endif
2072}
2073
2074bool GenerateOopMap::compute_map(Thread* current) {
2075#ifndef PRODUCT
2076 if (TimeOopMap2) {
2077 method()->print_short_name(tty);
2078 tty->print(" ");
2079 }
2080 if (TimeOopMap) {
2081 _total_byte_count += method()->code_size();
2082 }
2083#endif
2084 TraceTime t_single("oopmap time", TimeOopMap2);
2085 TraceTime t_all(NULL__null, &_total_oopmap_time, TimeOopMap);
2086
2087 // Initialize values
2088 _got_error = false;
2089 _conflict = false;
2090 _max_locals = method()->max_locals();
2091 _max_stack = method()->max_stack();
2092 _has_exceptions = (method()->has_exception_handler());
2093 _nof_refval_conflicts = 0;
2094 _init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars
2095 _report_result = false;
2096 _report_result_for_send = false;
2097 _new_var_map = NULL__null;
2098 _ret_adr_tos = new GrowableArray<intptr_t>(5); // 5 seems like a good number;
2099 _did_rewriting = false;
2100 _did_relocation = false;
2101
2102 if (TraceNewOopMapGeneration) {
2103 tty->print("Method name: %s\n", method()->name()->as_C_string());
2104 if (Verbose) {
2105 _method->print_codes();
2106 tty->print_cr("Exception table:");
2107 ExceptionTable excps(method());
2108 for(int i = 0; i < excps.length(); i ++) {
2109 tty->print_cr("[%d - %d] -> %d",
2110 excps.start_pc(i), excps.end_pc(i), excps.handler_pc(i));
2111 }
2112 }
2113 }
2114
2115 // if no code - do nothing
2116 // compiler needs info
2117 if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) {
2118 fill_stackmap_prolog(0);
2119 fill_stackmap_epilog();
2120 return true;
2121 }
2122 // Step 1: Compute all jump targets and their return value
2123 if (!_got_error)
2124 _rt.compute_ret_table(_method);
2125
2126 // Step 2: Find all basic blocks and count GC points
2127 if (!_got_error)
2128 mark_bbheaders_and_count_gc_points();
2129
2130 // Step 3: Calculate stack maps
2131 if (!_got_error)
2132 do_interpretation();
2133
2134 // Step 4:Return results
2135 if (!_got_error && report_results())
2136 report_result();
2137
2138 return !_got_error;
2139}
2140
2141// Error handling methods
2142//
2143// If we compute from a suitable JavaThread then we create an exception for the GenerateOopMap
2144// calling code to retrieve (via exception()) and throw if desired (in most cases errors are ignored).
2145// Otherwise it is considered a fatal error to hit malformed bytecode.
2146void GenerateOopMap::error_work(const char *format, va_list ap) {
2147 _got_error = true;
2148 char msg_buffer[512];
2149 os::vsnprintf(msg_buffer, sizeof(msg_buffer), format, ap);
2150 // Append method name
2151 char msg_buffer2[512];
2152 os::snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg_buffer, method()->name()->as_C_string());
2153 Thread* current = Thread::current();
2154 if (current->can_call_java()) {
2155 _exception = Exceptions::new_exception(JavaThread::cast(current),
2156 vmSymbols::java_lang_LinkageError(),
2157 msg_buffer2);
2158 } else {
2159 fatal("%s", msg_buffer2)do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2159, "%s", msg_buffer2); ::breakpoint(); } while (0)
;
2160 }
2161}
2162
2163void GenerateOopMap::report_error(const char *format, ...) {
2164 va_list ap;
2165 va_start(ap, format)__builtin_va_start(ap, format);
2166 error_work(format, ap);
2167}
2168
2169void GenerateOopMap::verify_error(const char *format, ...) {
2170 // We do not distinguish between different types of errors for verification
2171 // errors. Let the verifier give a better message.
2172 report_error("Illegal class file encountered. Try running with -Xverify:all");
2173}
2174
2175//
2176// Report result opcodes
2177//
2178void GenerateOopMap::report_result() {
2179
2180 if (TraceNewOopMapGeneration) tty->print_cr("Report result pass");
2181
2182 // We now want to report the result of the parse
2183 _report_result = true;
2184
2185 // Prolog code
2186 fill_stackmap_prolog(_gc_points);
2187
2188 // Mark everything changed, then do one interpretation pass.
2189 for (int i = 0; i<_bb_count; i++) {
2190 if (_basic_blocks[i].is_reachable()) {
2191 _basic_blocks[i].set_changed(true);
2192 interp_bb(&_basic_blocks[i]);
2193 }
2194 }
2195
2196 // Note: Since we are skipping dead-code when we are reporting results, then
2197 // the no. of encountered gc-points might be fewer than the previously number
2198 // we have counted. (dead-code is a pain - it should be removed before we get here)
2199 fill_stackmap_epilog();
2200
2201 // Report initvars
2202 fill_init_vars(_init_vars);
2203
2204 _report_result = false;
2205}
2206
2207void GenerateOopMap::result_for_basicblock(int bci) {
2208 if (TraceNewOopMapGeneration) tty->print_cr("Report result pass for basicblock");
2209
2210 // We now want to report the result of the parse
2211 _report_result = true;
2212
2213 // Find basicblock and report results
2214 BasicBlock* bb = get_basic_block_containing(bci);
2215 guarantee(bb != NULL, "no basic block for bci")do { if (!(bb != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2215, "guarantee(" "bb != NULL" ") failed", "no basic block for bci"
); ::breakpoint(); } } while (0)
;
2216 assert(bb->is_reachable(), "getting result from unreachable basicblock")do { if (!(bb->is_reachable())) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2216, "assert(" "bb->is_reachable()" ") failed", "getting result from unreachable basicblock"
); ::breakpoint(); } } while (0)
;
2217 bb->set_changed(true);
2218 interp_bb(bb);
2219}
2220
2221//
2222// Conflict handling code
2223//
2224
2225void GenerateOopMap::record_refval_conflict(int varNo) {
2226 assert(varNo>=0 && varNo< _max_locals, "index out of range")do { if (!(varNo>=0 && varNo< _max_locals)) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2226, "assert(" "varNo>=0 && varNo< _max_locals"
") failed", "index out of range"); ::breakpoint(); } } while
(0)
;
2227
2228 if (TraceOopMapRewrites) {
2229 tty->print("### Conflict detected (local no: %d)\n", varNo);
2230 }
2231
2232 if (!_new_var_map) {
2233 _new_var_map = NEW_RESOURCE_ARRAY(int, _max_locals)(int*) resource_allocate_bytes((_max_locals) * sizeof(int));
2234 for (int k = 0; k < _max_locals; k++) _new_var_map[k] = k;
2235 }
2236
2237 if ( _new_var_map[varNo] == varNo) {
2238 // Check if max. number of locals has been reached
2239 if (_max_locals + _nof_refval_conflicts >= MAX_LOCAL_VARS65536) {
2240 report_error("Rewriting exceeded local variable limit");
2241 return;
2242 }
2243 _new_var_map[varNo] = _max_locals + _nof_refval_conflicts;
2244 _nof_refval_conflicts++;
2245 }
2246}
2247
2248void GenerateOopMap::rewrite_refval_conflicts()
2249{
2250 // We can get here two ways: Either a rewrite conflict was detected, or
2251 // an uninitialize reference was detected. In the second case, we do not
2252 // do any rewriting, we just want to recompute the reference set with the
2253 // new information
2254
2255 int nof_conflicts = 0; // Used for debugging only
2256
2257 if ( _nof_refval_conflicts == 0 )
2258 return;
2259
2260 // Check if rewrites are allowed in this parse.
2261 if (!allow_rewrites()) {
2262 fatal("Rewriting method not allowed at this stage")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2262, "Rewriting method not allowed at this stage"); ::breakpoint
(); } while (0)
;
2263 }
2264
2265
2266 // Tracing flag
2267 _did_rewriting = true;
2268
2269 if (TraceOopMapRewrites) {
2270 tty->print_cr("ref/value conflict for method %s - bytecodes are getting rewritten", method()->name()->as_C_string());
2271 method()->print();
2272 method()->print_codes();
2273 }
2274
2275 assert(_new_var_map!=NULL, "nothing to rewrite")do { if (!(_new_var_map!=__null)) { (*g_assert_poison) = 'X';
; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2275, "assert(" "_new_var_map!=__null" ") failed", "nothing to rewrite"
); ::breakpoint(); } } while (0)
;
2276 assert(_conflict==true, "We should not be here")do { if (!(_conflict==true)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2276, "assert(" "_conflict==true" ") failed", "We should not be here"
); ::breakpoint(); } } while (0)
;
2277
2278 compute_ret_adr_at_TOS();
2279 if (!_got_error) {
2280 for (int k = 0; k < _max_locals && !_got_error; k++) {
2281 if (_new_var_map[k] != k) {
2282 if (TraceOopMapRewrites) {
2283 tty->print_cr("Rewriting: %d -> %d", k, _new_var_map[k]);
2284 }
2285 rewrite_refval_conflict(k, _new_var_map[k]);
2286 if (_got_error) return;
2287 nof_conflicts++;
2288 }
2289 }
2290 }
2291
2292 assert(nof_conflicts == _nof_refval_conflicts, "sanity check")do { if (!(nof_conflicts == _nof_refval_conflicts)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2292, "assert(" "nof_conflicts == _nof_refval_conflicts" ") failed"
, "sanity check"); ::breakpoint(); } } while (0)
;
2293
2294 // Adjust the number of locals
2295 method()->set_max_locals(_max_locals+_nof_refval_conflicts);
2296 _max_locals += _nof_refval_conflicts;
2297
2298 // That was that...
2299 _new_var_map = NULL__null;
2300 _nof_refval_conflicts = 0;
2301}
2302
2303void GenerateOopMap::rewrite_refval_conflict(int from, int to) {
2304 bool startOver;
2305 do {
2306 // Make sure that the BytecodeStream is constructed in the loop, since
2307 // during rewriting a new method is going to be used, and the next time
2308 // around we want to use that.
2309 BytecodeStream bcs(_method);
2310 startOver = false;
2311
2312 while( !startOver && !_got_error &&
2313 // test bcs in case method changed and it became invalid
2314 bcs.next() >=0) {
2315 startOver = rewrite_refval_conflict_inst(&bcs, from, to);
2316 }
2317 } while (startOver && !_got_error);
2318}
2319
2320/* If the current instruction is one that uses local variable "from"
2321 in a ref way, change it to use "to". There's a subtle reason why we
2322 renumber the ref uses and not the non-ref uses: non-ref uses may be
2323 2 slots wide (double, long) which would necessitate keeping track of
2324 whether we should add one or two variables to the method. If the change
2325 affected the width of some instruction, returns "TRUE"; otherwise, returns "FALSE".
2326 Another reason for moving ref's value is for solving (addr, ref) conflicts, which
2327 both uses aload/astore methods.
2328*/
2329bool GenerateOopMap::rewrite_refval_conflict_inst(BytecodeStream *itr, int from, int to) {
2330 Bytecodes::Code bc = itr->code();
2331 int index;
2332 int bci = itr->bci();
2333
2334 if (is_aload(itr, &index) && index == from) {
2335 if (TraceOopMapRewrites) {
2336 tty->print_cr("Rewriting aload at bci: %d", bci);
2337 }
2338 return rewrite_load_or_store(itr, Bytecodes::_aload, Bytecodes::_aload_0, to);
2339 }
2340
2341 if (is_astore(itr, &index) && index == from) {
2342 if (!stack_top_holds_ret_addr(bci)) {
2343 if (TraceOopMapRewrites) {
2344 tty->print_cr("Rewriting astore at bci: %d", bci);
2345 }
2346 return rewrite_load_or_store(itr, Bytecodes::_astore, Bytecodes::_astore_0, to);
2347 } else {
2348 if (TraceOopMapRewrites) {
2349 tty->print_cr("Supress rewriting of astore at bci: %d", bci);
2350 }
2351 }
2352 }
2353
2354 return false;
2355}
2356
2357// The argument to this method is:
2358// bc : Current bytecode
2359// bcN : either _aload or _astore
2360// bc0 : either _aload_0 or _astore_0
2361bool GenerateOopMap::rewrite_load_or_store(BytecodeStream *bcs, Bytecodes::Code bcN, Bytecodes::Code bc0, unsigned int varNo) {
2362 assert(bcN == Bytecodes::_astore || bcN == Bytecodes::_aload, "wrong argument (bcN)")do { if (!(bcN == Bytecodes::_astore || bcN == Bytecodes::_aload
)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2362, "assert(" "bcN == Bytecodes::_astore || bcN == Bytecodes::_aload"
") failed", "wrong argument (bcN)"); ::breakpoint(); } } while
(0)
;
2363 assert(bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0, "wrong argument (bc0)")do { if (!(bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0
)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2363, "assert(" "bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0"
") failed", "wrong argument (bc0)"); ::breakpoint(); } } while
(0)
;
2364 int ilen = Bytecodes::length_at(_method(), bcs->bcp());
2365 int newIlen;
2366
2367 if (ilen == 4) {
2368 // Original instruction was wide; keep it wide for simplicity
2369 newIlen = 4;
2370 } else if (varNo < 4)
2371 newIlen = 1;
2372 else if (varNo >= 256)
2373 newIlen = 4;
2374 else
2375 newIlen = 2;
2376
2377 // If we need to relocate in order to patch the byte, we
2378 // do the patching in a temp. buffer, that is passed to the reloc.
2379 // The patching of the bytecode stream is then done by the Relocator.
2380 // This is neccesary, since relocating the instruction at a certain bci, might
2381 // also relocate that instruction, e.g., if a _goto before it gets widen to a _goto_w.
2382 // Hence, we do not know which bci to patch after relocation.
2383
2384 assert(newIlen <= 4, "sanity check")do { if (!(newIlen <= 4)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2384, "assert(" "newIlen <= 4" ") failed", "sanity check"
); ::breakpoint(); } } while (0)
;
2385 u_char inst_buffer[4]; // Max. instruction size is 4.
2386 address bcp;
2387
2388 if (newIlen != ilen) {
2389 // Relocation needed do patching in temp. buffer
2390 bcp = (address)inst_buffer;
2391 } else {
2392 bcp = _method->bcp_from(bcs->bci());
2393 }
2394
2395 // Patch either directly in Method* or in temp. buffer
2396 if (newIlen == 1) {
2397 assert(varNo < 4, "varNo too large")do { if (!(varNo < 4)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2397, "assert(" "varNo < 4" ") failed", "varNo too large"
); ::breakpoint(); } } while (0)
;
2398 *bcp = bc0 + varNo;
2399 } else if (newIlen == 2) {
2400 assert(varNo < 256, "2-byte index needed!")do { if (!(varNo < 256)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2400, "assert(" "varNo < 256" ") failed", "2-byte index needed!"
); ::breakpoint(); } } while (0)
;
2401 *(bcp + 0) = bcN;
2402 *(bcp + 1) = varNo;
2403 } else {
2404 assert(newIlen == 4, "Wrong instruction length")do { if (!(newIlen == 4)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2404, "assert(" "newIlen == 4" ") failed", "Wrong instruction length"
); ::breakpoint(); } } while (0)
;
2405 *(bcp + 0) = Bytecodes::_wide;
2406 *(bcp + 1) = bcN;
2407 Bytes::put_Java_u2(bcp+2, varNo);
2408 }
2409
2410 if (newIlen != ilen) {
2411 expand_current_instr(bcs->bci(), ilen, newIlen, inst_buffer);
2412 }
2413
2414
2415 return (newIlen != ilen);
2416}
2417
2418class RelocCallback : public RelocatorListener {
2419 private:
2420 GenerateOopMap* _gom;
2421 public:
2422 RelocCallback(GenerateOopMap* gom) { _gom = gom; };
2423
2424 // Callback method
2425 virtual void relocated(int bci, int delta, int new_code_length) {
2426 _gom->update_basic_blocks (bci, delta, new_code_length);
2427 _gom->update_ret_adr_at_TOS(bci, delta);
2428 _gom->_rt.update_ret_table (bci, delta);
2429 }
2430};
2431
2432// Returns true if expanding was succesful. Otherwise, reports an error and
2433// returns false.
2434void GenerateOopMap::expand_current_instr(int bci, int ilen, int newIlen, u_char inst_buffer[]) {
2435 JavaThread* THREAD__the_thread__ = JavaThread::current(); // For exception macros.
2436 RelocCallback rcb(this);
2437 Relocator rc(_method, &rcb);
2438 methodHandle m= rc.insert_space_at(bci, newIlen, inst_buffer, THREAD__the_thread__);
2439 if (m.is_null() || HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) {
2440 report_error("could not rewrite method - exception occurred or bytecode buffer overflow");
2441 return;
2442 }
2443
2444 // Relocator returns a new method.
2445 _did_relocation = true;
2446 _method = m;
2447}
2448
2449
2450bool GenerateOopMap::is_astore(BytecodeStream *itr, int *index) {
2451 Bytecodes::Code bc = itr->code();
2452 switch(bc) {
2453 case Bytecodes::_astore_0:
2454 case Bytecodes::_astore_1:
2455 case Bytecodes::_astore_2:
2456 case Bytecodes::_astore_3:
2457 *index = bc - Bytecodes::_astore_0;
2458 return true;
2459 case Bytecodes::_astore:
2460 *index = itr->get_index();
2461 return true;
2462 default:
2463 return false;
2464 }
2465}
2466
2467bool GenerateOopMap::is_aload(BytecodeStream *itr, int *index) {
2468 Bytecodes::Code bc = itr->code();
2469 switch(bc) {
2470 case Bytecodes::_aload_0:
2471 case Bytecodes::_aload_1:
2472 case Bytecodes::_aload_2:
2473 case Bytecodes::_aload_3:
2474 *index = bc - Bytecodes::_aload_0;
2475 return true;
2476
2477 case Bytecodes::_aload:
2478 *index = itr->get_index();
2479 return true;
2480
2481 default:
2482 return false;
2483 }
2484}
2485
2486
2487// Return true iff the top of the operand stack holds a return address at
2488// the current instruction
2489bool GenerateOopMap::stack_top_holds_ret_addr(int bci) {
2490 for(int i = 0; i < _ret_adr_tos->length(); i++) {
2491 if (_ret_adr_tos->at(i) == bci)
2492 return true;
2493 }
2494
2495 return false;
2496}
2497
2498void GenerateOopMap::compute_ret_adr_at_TOS() {
2499 assert(_ret_adr_tos != NULL, "must be initialized")do { if (!(_ret_adr_tos != __null)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2499, "assert(" "_ret_adr_tos != __null" ") failed", "must be initialized"
); ::breakpoint(); } } while (0)
;
2500 _ret_adr_tos->clear();
2501
2502 for (int i = 0; i < bb_count(); i++) {
2503 BasicBlock* bb = &_basic_blocks[i];
2504
2505 // Make sure to only check basicblocks that are reachable
2506 if (bb->is_reachable()) {
2507
2508 // For each Basic block we check all instructions
2509 BytecodeStream bcs(_method);
2510 bcs.set_interval(bb->_bci, next_bb_start_pc(bb));
2511
2512 restore_state(bb);
2513
2514 while (bcs.next()>=0 && !_got_error) {
2515 // TDT: should this be is_good_address() ?
2516 if (_stack_top > 0 && stack()[_stack_top-1].is_address()) {
2517 _ret_adr_tos->append(bcs.bci());
2518 if (TraceNewOopMapGeneration) {
2519 tty->print_cr("Ret_adr TOS at bci: %d", bcs.bci());
2520 }
2521 }
2522 interp1(&bcs);
2523 }
2524 }
2525 }
2526}
2527
2528void GenerateOopMap::update_ret_adr_at_TOS(int bci, int delta) {
2529 for(int i = 0; i < _ret_adr_tos->length(); i++) {
2530 int v = _ret_adr_tos->at(i);
2531 if (v > bci) _ret_adr_tos->at_put(i, v + delta);
2532 }
2533}
2534
2535// ===================================================================
2536
2537#ifndef PRODUCT
2538int ResolveOopMapConflicts::_nof_invocations = 0;
2539int ResolveOopMapConflicts::_nof_rewrites = 0;
2540int ResolveOopMapConflicts::_nof_relocations = 0;
2541#endif
2542
2543methodHandle ResolveOopMapConflicts::do_potential_rewrite(TRAPSJavaThread* __the_thread__) {
2544 if (!compute_map(THREAD__the_thread__)) {
2545 THROW_HANDLE_(exception(), methodHandle()){ Exceptions::_throw(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/oops/generateOopMap.cpp"
, 2545, exception()); return methodHandle(); }
;
2546 }
2547
2548#ifndef PRODUCT
2549 // Tracking and statistics
2550 if (PrintRewrites) {
2551 _nof_invocations++;
2552 if (did_rewriting()) {
2553 _nof_rewrites++;
2554 if (did_relocation()) _nof_relocations++;
2555 tty->print("Method was rewritten %s: ", (did_relocation()) ? "and relocated" : "");
2556 method()->print_value(); tty->cr();
2557 tty->print_cr("Cand.: %d rewrts: %d (%d%%) reloc.: %d (%d%%)",
2558 _nof_invocations,
2559 _nof_rewrites, (_nof_rewrites * 100) / _nof_invocations,
2560 _nof_relocations, (_nof_relocations * 100) / _nof_invocations);
2561 }
2562 }
2563#endif
2564 return methodHandle(THREAD__the_thread__, method());
2565}