Path: blob/master/src/hotspot/share/oops/generateOopMap.cpp
40951 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/vmSymbols.hpp"26#include "interpreter/bytecodeStream.hpp"27#include "logging/log.hpp"28#include "logging/logStream.hpp"29#include "memory/allocation.inline.hpp"30#include "memory/resourceArea.hpp"31#include "oops/constantPool.hpp"32#include "oops/generateOopMap.hpp"33#include "oops/oop.inline.hpp"34#include "oops/symbol.hpp"35#include "runtime/handles.inline.hpp"36#include "runtime/java.hpp"37#include "runtime/os.hpp"38#include "runtime/relocator.hpp"39#include "runtime/timerTrace.hpp"40#include "utilities/bitMap.inline.hpp"41#include "utilities/ostream.hpp"4243//44//45// Compute stack layouts for each instruction in method.46//47// Problems:48// - What to do about jsr with different types of local vars?49// Need maps that are conditional on jsr path?50// - Jsr and exceptions should be done more efficiently (the retAddr stuff)51//52// Alternative:53// - Could extend verifier to provide this information.54// For: one fewer abstract interpreter to maintain. Against: the verifier55// solves a bigger problem so slower (undesirable to force verification of56// everything?).57//58// Algorithm:59// Partition bytecodes into basic blocks60// For each basic block: store entry state (vars, stack). For instructions61// inside basic blocks we do not store any state (instead we recompute it62// from state produced by previous instruction).63//64// Perform abstract interpretation of bytecodes over this lattice:65//66// _--'#'--_67// / / \ \68// / / \ \69// / | | \70// 'r' 'v' 'p' ' '71// \ | | /72// \ \ / /73// \ \ / /74// -- '@' --75//76// '#' top, result of conflict merge77// 'r' reference type78// 'v' value type79// 'p' pc type for jsr/ret80// ' ' uninitialized; never occurs on operand stack in Java81// '@' bottom/unexecuted; initial state each bytecode.82//83// Basic block headers are the only merge points. We use this iteration to84// compute the information:85//86// find basic blocks;87// initialize them with uninitialized state;88// initialize first BB according to method signature;89// mark first BB changed90// while (some BB is changed) do {91// perform abstract interpration of all bytecodes in BB;92// merge exit state of BB into entry state of all successor BBs,93// noting if any of these change;94// }95//96// One additional complication is necessary. The jsr instruction pushes97// a return PC on the stack (a 'p' type in the abstract interpretation).98// To be able to process "ret" bytecodes, we keep track of these return99// PC's in a 'retAddrs' structure in abstract interpreter context (when100// processing a "ret" bytecodes, it is not sufficient to know that it gets101// an argument of the right type 'p'; we need to know which address it102// returns to).103//104// (Note this comment is borrowed form the original author of the algorithm)105106// ComputeCallStack107//108// Specialization of SignatureIterator - compute the effects of a call109//110class ComputeCallStack : public SignatureIterator {111CellTypeState *_effect;112int _idx;113114void setup();115void set(CellTypeState state) { _effect[_idx++] = state; }116int length() { return _idx; };117118friend class SignatureIterator; // so do_parameters_on can call do_type119void do_type(BasicType type, bool for_return = false) {120if (for_return && type == T_VOID) {121set(CellTypeState::bottom);122} else if (is_reference_type(type)) {123set(CellTypeState::ref);124} else {125assert(is_java_primitive(type), "");126set(CellTypeState::value);127if (is_double_word_type(type)) {128set(CellTypeState::value);129}130}131}132133public:134ComputeCallStack(Symbol* signature) : SignatureIterator(signature) {};135136// Compute methods137int compute_for_parameters(bool is_static, CellTypeState *effect) {138_idx = 0;139_effect = effect;140141if (!is_static)142effect[_idx++] = CellTypeState::ref;143144do_parameters_on(this);145146return length();147};148149int compute_for_returntype(CellTypeState *effect) {150_idx = 0;151_effect = effect;152do_type(return_type(), true);153set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works154155return length();156}157};158159//=========================================================================================160// ComputeEntryStack161//162// Specialization of SignatureIterator - in order to set up first stack frame163//164class ComputeEntryStack : public SignatureIterator {165CellTypeState *_effect;166int _idx;167168void setup();169void set(CellTypeState state) { _effect[_idx++] = state; }170int length() { return _idx; };171172friend class SignatureIterator; // so do_parameters_on can call do_type173void do_type(BasicType type, bool for_return = false) {174if (for_return && type == T_VOID) {175set(CellTypeState::bottom);176} else if (is_reference_type(type)) {177set(CellTypeState::make_slot_ref(_idx));178} else {179assert(is_java_primitive(type), "");180set(CellTypeState::value);181if (is_double_word_type(type)) {182set(CellTypeState::value);183}184}185}186187public:188ComputeEntryStack(Symbol* signature) : SignatureIterator(signature) {};189190// Compute methods191int compute_for_parameters(bool is_static, CellTypeState *effect) {192_idx = 0;193_effect = effect;194195if (!is_static)196effect[_idx++] = CellTypeState::make_slot_ref(0);197198do_parameters_on(this);199200return length();201};202203int compute_for_returntype(CellTypeState *effect) {204_idx = 0;205_effect = effect;206do_type(return_type(), true);207set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works208209return length();210}211};212213//=====================================================================================214//215// Implementation of RetTable/RetTableEntry216//217// Contains function to itereate through all bytecodes218// and find all return entry points219//220int RetTable::_init_nof_entries = 10;221int RetTableEntry::_init_nof_jsrs = 5;222223RetTableEntry::RetTableEntry(int target, RetTableEntry *next) {224_target_bci = target;225_jsrs = new GrowableArray<intptr_t>(_init_nof_jsrs);226_next = next;227}228229void RetTableEntry::add_delta(int bci, int delta) {230if (_target_bci > bci) _target_bci += delta;231232for (int k = 0; k < _jsrs->length(); k++) {233int jsr = _jsrs->at(k);234if (jsr > bci) _jsrs->at_put(k, jsr+delta);235}236}237238void RetTable::compute_ret_table(const methodHandle& method) {239BytecodeStream i(method);240Bytecodes::Code bytecode;241242while( (bytecode = i.next()) >= 0) {243switch (bytecode) {244case Bytecodes::_jsr:245add_jsr(i.next_bci(), i.dest());246break;247case Bytecodes::_jsr_w:248add_jsr(i.next_bci(), i.dest_w());249break;250default:251break;252}253}254}255256void RetTable::add_jsr(int return_bci, int target_bci) {257RetTableEntry* entry = _first;258259// Scan table for entry260for (;entry && entry->target_bci() != target_bci; entry = entry->next());261262if (!entry) {263// Allocate new entry and put in list264entry = new RetTableEntry(target_bci, _first);265_first = entry;266}267268// Now "entry" is set. Make sure that the entry is initialized269// and has room for the new jsr.270entry->add_jsr(return_bci);271}272273RetTableEntry* RetTable::find_jsrs_for_target(int targBci) {274RetTableEntry *cur = _first;275276while(cur) {277assert(cur->target_bci() != -1, "sanity check");278if (cur->target_bci() == targBci) return cur;279cur = cur->next();280}281ShouldNotReachHere();282return NULL;283}284285// The instruction at bci is changing size by "delta". Update the return map.286void RetTable::update_ret_table(int bci, int delta) {287RetTableEntry *cur = _first;288while(cur) {289cur->add_delta(bci, delta);290cur = cur->next();291}292}293294//295// Celltype state296//297298CellTypeState CellTypeState::bottom = CellTypeState::make_bottom();299CellTypeState CellTypeState::uninit = CellTypeState::make_any(uninit_value);300CellTypeState CellTypeState::ref = CellTypeState::make_any(ref_conflict);301CellTypeState CellTypeState::value = CellTypeState::make_any(val_value);302CellTypeState CellTypeState::refUninit = CellTypeState::make_any(ref_conflict | uninit_value);303CellTypeState CellTypeState::top = CellTypeState::make_top();304CellTypeState CellTypeState::addr = CellTypeState::make_any(addr_conflict);305306// Commonly used constants307static CellTypeState epsilonCTS[1] = { CellTypeState::bottom };308static CellTypeState refCTS = CellTypeState::ref;309static CellTypeState valCTS = CellTypeState::value;310static CellTypeState vCTS[2] = { CellTypeState::value, CellTypeState::bottom };311static CellTypeState rCTS[2] = { CellTypeState::ref, CellTypeState::bottom };312static CellTypeState rrCTS[3] = { CellTypeState::ref, CellTypeState::ref, CellTypeState::bottom };313static CellTypeState vrCTS[3] = { CellTypeState::value, CellTypeState::ref, CellTypeState::bottom };314static CellTypeState vvCTS[3] = { CellTypeState::value, CellTypeState::value, CellTypeState::bottom };315static CellTypeState rvrCTS[4] = { CellTypeState::ref, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom };316static CellTypeState vvrCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom };317static CellTypeState vvvCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom };318static CellTypeState vvvrCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom };319static CellTypeState vvvvCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom };320321char CellTypeState::to_char() const {322if (can_be_reference()) {323if (can_be_value() || can_be_address())324return '#'; // Conflict that needs to be rewritten325else326return 'r';327} else if (can_be_value())328return 'v';329else if (can_be_address())330return 'p';331else if (can_be_uninit())332return ' ';333else334return '@';335}336337338// Print a detailed CellTypeState. Indicate all bits that are set. If339// the CellTypeState represents an address or a reference, print the340// value of the additional information.341void CellTypeState::print(outputStream *os) {342if (can_be_address()) {343os->print("(p");344} else {345os->print("( ");346}347if (can_be_reference()) {348os->print("r");349} else {350os->print(" ");351}352if (can_be_value()) {353os->print("v");354} else {355os->print(" ");356}357if (can_be_uninit()) {358os->print("u|");359} else {360os->print(" |");361}362if (is_info_top()) {363os->print("Top)");364} else if (is_info_bottom()) {365os->print("Bot)");366} else {367if (is_reference()) {368int info = get_info();369int data = info & ~(ref_not_lock_bit | ref_slot_bit);370if (info & ref_not_lock_bit) {371// Not a monitor lock reference.372if (info & ref_slot_bit) {373// slot374os->print("slot%d)", data);375} else {376// line377os->print("line%d)", data);378}379} else {380// lock381os->print("lock%d)", data);382}383} else {384os->print("%d)", get_info());385}386}387}388389//390// Basicblock handling methods391//392393void GenerateOopMap::initialize_bb() {394_gc_points = 0;395_bb_count = 0;396_bb_hdr_bits.reinitialize(method()->code_size());397}398399void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) {400assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds");401if (c->is_bb_header(bci))402return;403404if (TraceNewOopMapGeneration) {405tty->print_cr("Basicblock#%d begins at: %d", c->_bb_count, bci);406}407c->set_bbmark_bit(bci);408c->_bb_count++;409}410411412void GenerateOopMap::mark_bbheaders_and_count_gc_points() {413initialize_bb();414415bool fellThrough = false; // False to get first BB marked.416417// First mark all exception handlers as start of a basic-block418ExceptionTable excps(method());419for(int i = 0; i < excps.length(); i ++) {420bb_mark_fct(this, excps.handler_pc(i), NULL);421}422423// Then iterate through the code424BytecodeStream bcs(_method);425Bytecodes::Code bytecode;426427while( (bytecode = bcs.next()) >= 0) {428int bci = bcs.bci();429430if (!fellThrough)431bb_mark_fct(this, bci, NULL);432433fellThrough = jump_targets_do(&bcs, &GenerateOopMap::bb_mark_fct, NULL);434435/* We will also mark successors of jsr's as basic block headers. */436switch (bytecode) {437case Bytecodes::_jsr:438assert(!fellThrough, "should not happen");439bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL);440break;441case Bytecodes::_jsr_w:442assert(!fellThrough, "should not happen");443bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL);444break;445default:446break;447}448449if (possible_gc_point(&bcs))450_gc_points++;451}452}453454void GenerateOopMap::set_bbmark_bit(int bci) {455_bb_hdr_bits.at_put(bci, true);456}457458void GenerateOopMap::reachable_basicblock(GenerateOopMap *c, int bci, int *data) {459assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds");460BasicBlock* bb = c->get_basic_block_at(bci);461if (bb->is_dead()) {462bb->mark_as_alive();463*data = 1; // Mark basicblock as changed464}465}466467468void GenerateOopMap::mark_reachable_code() {469int change = 1; // int to get function pointers to work470471// Mark entry basic block as alive and all exception handlers472_basic_blocks[0].mark_as_alive();473ExceptionTable excps(method());474for(int i = 0; i < excps.length(); i++) {475BasicBlock *bb = get_basic_block_at(excps.handler_pc(i));476// If block is not already alive (due to multiple exception handlers to same bb), then477// make it alive478if (bb->is_dead()) bb->mark_as_alive();479}480481BytecodeStream bcs(_method);482483// Iterate through all basic blocks until we reach a fixpoint484while (change) {485change = 0;486487for (int i = 0; i < _bb_count; i++) {488BasicBlock *bb = &_basic_blocks[i];489if (bb->is_alive()) {490// Position bytecodestream at last bytecode in basicblock491bcs.set_start(bb->_end_bci);492bcs.next();493Bytecodes::Code bytecode = bcs.code();494int bci = bcs.bci();495assert(bci == bb->_end_bci, "wrong bci");496497bool fell_through = jump_targets_do(&bcs, &GenerateOopMap::reachable_basicblock, &change);498499// We will also mark successors of jsr's as alive.500switch (bytecode) {501case Bytecodes::_jsr:502case Bytecodes::_jsr_w:503assert(!fell_through, "should not happen");504reachable_basicblock(this, bci + Bytecodes::length_for(bytecode), &change);505break;506default:507break;508}509if (fell_through) {510// Mark successor as alive511if (bb[1].is_dead()) {512bb[1].mark_as_alive();513change = 1;514}515}516}517}518}519}520521/* If the current instruction in "c" has no effect on control flow,522returns "true". Otherwise, calls "jmpFct" one or more times, with523"c", an appropriate "pcDelta", and "data" as arguments, then524returns "false". There is one exception: if the current525instruction is a "ret", returns "false" without calling "jmpFct".526Arrangements for tracking the control flow of a "ret" must be made527externally. */528bool GenerateOopMap::jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int *data) {529int bci = bcs->bci();530531switch (bcs->code()) {532case Bytecodes::_ifeq:533case Bytecodes::_ifne:534case Bytecodes::_iflt:535case Bytecodes::_ifge:536case Bytecodes::_ifgt:537case Bytecodes::_ifle:538case Bytecodes::_if_icmpeq:539case Bytecodes::_if_icmpne:540case Bytecodes::_if_icmplt:541case Bytecodes::_if_icmpge:542case Bytecodes::_if_icmpgt:543case Bytecodes::_if_icmple:544case Bytecodes::_if_acmpeq:545case Bytecodes::_if_acmpne:546case Bytecodes::_ifnull:547case Bytecodes::_ifnonnull:548(*jmpFct)(this, bcs->dest(), data);549(*jmpFct)(this, bci + 3, data);550break;551552case Bytecodes::_goto:553(*jmpFct)(this, bcs->dest(), data);554break;555case Bytecodes::_goto_w:556(*jmpFct)(this, bcs->dest_w(), data);557break;558case Bytecodes::_tableswitch:559{ Bytecode_tableswitch tableswitch(method(), bcs->bcp());560int len = tableswitch.length();561562(*jmpFct)(this, bci + tableswitch.default_offset(), data); /* Default. jump address */563while (--len >= 0) {564(*jmpFct)(this, bci + tableswitch.dest_offset_at(len), data);565}566break;567}568569case Bytecodes::_lookupswitch:570{ Bytecode_lookupswitch lookupswitch(method(), bcs->bcp());571int npairs = lookupswitch.number_of_pairs();572(*jmpFct)(this, bci + lookupswitch.default_offset(), data); /* Default. */573while(--npairs >= 0) {574LookupswitchPair pair = lookupswitch.pair_at(npairs);575(*jmpFct)(this, bci + pair.offset(), data);576}577break;578}579case Bytecodes::_jsr:580assert(bcs->is_wide()==false, "sanity check");581(*jmpFct)(this, bcs->dest(), data);582583584585break;586case Bytecodes::_jsr_w:587(*jmpFct)(this, bcs->dest_w(), data);588break;589case Bytecodes::_wide:590ShouldNotReachHere();591return true;592break;593case Bytecodes::_athrow:594case Bytecodes::_ireturn:595case Bytecodes::_lreturn:596case Bytecodes::_freturn:597case Bytecodes::_dreturn:598case Bytecodes::_areturn:599case Bytecodes::_return:600case Bytecodes::_ret:601break;602default:603return true;604}605return false;606}607608/* Requires "pc" to be the head of a basic block; returns that basic609block. */610BasicBlock *GenerateOopMap::get_basic_block_at(int bci) const {611BasicBlock* bb = get_basic_block_containing(bci);612assert(bb->_bci == bci, "should have found BB");613return bb;614}615616// Requires "pc" to be the start of an instruction; returns the basic617// block containing that instruction. */618BasicBlock *GenerateOopMap::get_basic_block_containing(int bci) const {619BasicBlock *bbs = _basic_blocks;620int lo = 0, hi = _bb_count - 1;621622while (lo <= hi) {623int m = (lo + hi) / 2;624int mbci = bbs[m]._bci;625int nbci;626627if ( m == _bb_count-1) {628assert( bci >= mbci && bci < method()->code_size(), "sanity check failed");629return bbs+m;630} else {631nbci = bbs[m+1]._bci;632}633634if ( mbci <= bci && bci < nbci) {635return bbs+m;636} else if (mbci < bci) {637lo = m + 1;638} else {639assert(mbci > bci, "sanity check");640hi = m - 1;641}642}643644fatal("should have found BB");645return NULL;646}647648void GenerateOopMap::restore_state(BasicBlock *bb)649{650memcpy(_state, bb->_state, _state_len*sizeof(CellTypeState));651_stack_top = bb->_stack_top;652_monitor_top = bb->_monitor_top;653}654655int GenerateOopMap::next_bb_start_pc(BasicBlock *bb) {656int bbNum = bb - _basic_blocks + 1;657if (bbNum == _bb_count)658return method()->code_size();659660return _basic_blocks[bbNum]._bci;661}662663//664// CellType handling methods665//666667// Allocate memory and throw LinkageError if failure.668#define ALLOC_RESOURCE_ARRAY(var, type, count) \669var = NEW_RESOURCE_ARRAY_RETURN_NULL(type, count); \670if (var == NULL) { \671report_error("Cannot reserve enough memory to analyze this method"); \672return; \673}674675676void GenerateOopMap::init_state() {677_state_len = _max_locals + _max_stack + _max_monitors;678ALLOC_RESOURCE_ARRAY(_state, CellTypeState, _state_len);679memset(_state, 0, _state_len * sizeof(CellTypeState));680int count = MAX3(_max_locals, _max_stack, _max_monitors) + 1/*for null terminator char */;681ALLOC_RESOURCE_ARRAY(_state_vec_buf, char, count);682}683684void GenerateOopMap::make_context_uninitialized() {685CellTypeState* vs = vars();686687for (int i = 0; i < _max_locals; i++)688vs[i] = CellTypeState::uninit;689690_stack_top = 0;691_monitor_top = 0;692}693694int GenerateOopMap::methodsig_to_effect(Symbol* signature, bool is_static, CellTypeState* effect) {695ComputeEntryStack ces(signature);696return ces.compute_for_parameters(is_static, effect);697}698699// Return result of merging cts1 and cts2.700CellTypeState CellTypeState::merge(CellTypeState cts, int slot) const {701CellTypeState result;702703assert(!is_bottom() && !cts.is_bottom(),704"merge of bottom values is handled elsewhere");705706result._state = _state | cts._state;707708// If the top bit is set, we don't need to do any more work.709if (!result.is_info_top()) {710assert((result.can_be_address() || result.can_be_reference()),711"only addresses and references have non-top info");712713if (!equal(cts)) {714// The two values being merged are different. Raise to top.715if (result.is_reference()) {716result = CellTypeState::make_slot_ref(slot);717} else {718result._state |= info_conflict;719}720}721}722assert(result.is_valid_state(), "checking that CTS merge maintains legal state");723724return result;725}726727// Merge the variable state for locals and stack from cts into bbts.728bool GenerateOopMap::merge_local_state_vectors(CellTypeState* cts,729CellTypeState* bbts) {730int i;731int len = _max_locals + _stack_top;732bool change = false;733734for (i = len - 1; i >= 0; i--) {735CellTypeState v = cts[i].merge(bbts[i], i);736change = change || !v.equal(bbts[i]);737bbts[i] = v;738}739740return change;741}742743// Merge the monitor stack state from cts into bbts.744bool GenerateOopMap::merge_monitor_state_vectors(CellTypeState* cts,745CellTypeState* bbts) {746bool change = false;747if (_max_monitors > 0 && _monitor_top != bad_monitors) {748// If there are no monitors in the program, or there has been749// a monitor matching error before this point in the program,750// then we do not merge in the monitor state.751752int base = _max_locals + _max_stack;753int len = base + _monitor_top;754for (int i = len - 1; i >= base; i--) {755CellTypeState v = cts[i].merge(bbts[i], i);756757// Can we prove that, when there has been a change, it will already758// have been detected at this point? That would make this equal759// check here unnecessary.760change = change || !v.equal(bbts[i]);761bbts[i] = v;762}763}764765return change;766}767768void GenerateOopMap::copy_state(CellTypeState *dst, CellTypeState *src) {769int len = _max_locals + _stack_top;770for (int i = 0; i < len; i++) {771if (src[i].is_nonlock_reference()) {772dst[i] = CellTypeState::make_slot_ref(i);773} else {774dst[i] = src[i];775}776}777if (_max_monitors > 0 && _monitor_top != bad_monitors) {778int base = _max_locals + _max_stack;779len = base + _monitor_top;780for (int i = base; i < len; i++) {781dst[i] = src[i];782}783}784}785786787// Merge the states for the current block and the next. As long as a788// block is reachable the locals and stack must be merged. If the789// stack heights don't match then this is a verification error and790// it's impossible to interpret the code. Simultaneously monitor791// states are being check to see if they nest statically. If monitor792// depths match up then their states are merged. Otherwise the793// mismatch is simply recorded and interpretation continues since794// monitor matching is purely informational and doesn't say anything795// about the correctness of the code.796void GenerateOopMap::merge_state_into_bb(BasicBlock *bb) {797guarantee(bb != NULL, "null basicblock");798assert(bb->is_alive(), "merging state into a dead basicblock");799800if (_stack_top == bb->_stack_top) {801// always merge local state even if monitors don't match.802if (merge_local_state_vectors(_state, bb->_state)) {803bb->set_changed(true);804}805if (_monitor_top == bb->_monitor_top) {806// monitors still match so continue merging monitor states.807if (merge_monitor_state_vectors(_state, bb->_state)) {808bb->set_changed(true);809}810} else {811if (log_is_enabled(Info, monitormismatch)) {812report_monitor_mismatch("monitor stack height merge conflict");813}814// When the monitor stacks are not matched, we set _monitor_top to815// bad_monitors. This signals that, from here on, the monitor stack cannot816// be trusted. In particular, monitorexit bytecodes may throw817// exceptions. We mark this block as changed so that the change818// propagates properly.819bb->_monitor_top = bad_monitors;820bb->set_changed(true);821_monitor_safe = false;822}823} else if (!bb->is_reachable()) {824// First time we look at this BB825copy_state(bb->_state, _state);826bb->_stack_top = _stack_top;827bb->_monitor_top = _monitor_top;828bb->set_changed(true);829} else {830verify_error("stack height conflict: %d vs. %d", _stack_top, bb->_stack_top);831}832}833834void GenerateOopMap::merge_state(GenerateOopMap *gom, int bci, int* data) {835gom->merge_state_into_bb(gom->get_basic_block_at(bci));836}837838void GenerateOopMap::set_var(int localNo, CellTypeState cts) {839assert(cts.is_reference() || cts.is_value() || cts.is_address(),840"wrong celltypestate");841if (localNo < 0 || localNo > _max_locals) {842verify_error("variable write error: r%d", localNo);843return;844}845vars()[localNo] = cts;846}847848CellTypeState GenerateOopMap::get_var(int localNo) {849assert(localNo < _max_locals + _nof_refval_conflicts, "variable read error");850if (localNo < 0 || localNo > _max_locals) {851verify_error("variable read error: r%d", localNo);852return valCTS; // just to pick something;853}854return vars()[localNo];855}856857CellTypeState GenerateOopMap::pop() {858if ( _stack_top <= 0) {859verify_error("stack underflow");860return valCTS; // just to pick something861}862return stack()[--_stack_top];863}864865void GenerateOopMap::push(CellTypeState cts) {866if ( _stack_top >= _max_stack) {867verify_error("stack overflow");868return;869}870stack()[_stack_top++] = cts;871}872873CellTypeState GenerateOopMap::monitor_pop() {874assert(_monitor_top != bad_monitors, "monitor_pop called on error monitor stack");875if (_monitor_top == 0) {876// We have detected a pop of an empty monitor stack.877_monitor_safe = false;878_monitor_top = bad_monitors;879880if (log_is_enabled(Info, monitormismatch)) {881report_monitor_mismatch("monitor stack underflow");882}883return CellTypeState::ref; // just to keep the analysis going.884}885return monitors()[--_monitor_top];886}887888void GenerateOopMap::monitor_push(CellTypeState cts) {889assert(_monitor_top != bad_monitors, "monitor_push called on error monitor stack");890if (_monitor_top >= _max_monitors) {891// Some monitorenter is being executed more than once.892// This means that the monitor stack cannot be simulated.893_monitor_safe = false;894_monitor_top = bad_monitors;895896if (log_is_enabled(Info, monitormismatch)) {897report_monitor_mismatch("monitor stack overflow");898}899return;900}901monitors()[_monitor_top++] = cts;902}903904//905// Interpretation handling methods906//907908void GenerateOopMap::do_interpretation()909{910// "i" is just for debugging, so we can detect cases where this loop is911// iterated more than once.912int i = 0;913do {914#ifndef PRODUCT915if (TraceNewOopMapGeneration) {916tty->print("\n\nIteration #%d of do_interpretation loop, method:\n", i);917method()->print_name(tty);918tty->print("\n\n");919}920#endif921_conflict = false;922_monitor_safe = true;923// init_state is now called from init_basic_blocks. The length of a924// state vector cannot be determined until we have made a pass through925// the bytecodes counting the possible monitor entries.926if (!_got_error) init_basic_blocks();927if (!_got_error) setup_method_entry_state();928if (!_got_error) interp_all();929if (!_got_error) rewrite_refval_conflicts();930i++;931} while (_conflict && !_got_error);932}933934void GenerateOopMap::init_basic_blocks() {935// Note: Could consider reserving only the needed space for each BB's state936// (entry stack may not be of maximal height for every basic block).937// But cumbersome since we don't know the stack heights yet. (Nor the938// monitor stack heights...)939940ALLOC_RESOURCE_ARRAY(_basic_blocks, BasicBlock, _bb_count);941942// Make a pass through the bytecodes. Count the number of monitorenters.943// This can be used an upper bound on the monitor stack depth in programs944// which obey stack discipline with their monitor usage. Initialize the945// known information about basic blocks.946BytecodeStream j(_method);947Bytecodes::Code bytecode;948949int bbNo = 0;950int monitor_count = 0;951int prev_bci = -1;952while( (bytecode = j.next()) >= 0) {953if (j.code() == Bytecodes::_monitorenter) {954monitor_count++;955}956957int bci = j.bci();958if (is_bb_header(bci)) {959// Initialize the basicblock structure960BasicBlock *bb = _basic_blocks + bbNo;961bb->_bci = bci;962bb->_max_locals = _max_locals;963bb->_max_stack = _max_stack;964bb->set_changed(false);965bb->_stack_top = BasicBlock::_dead_basic_block; // Initialize all basicblocks are dead.966bb->_monitor_top = bad_monitors;967968if (bbNo > 0) {969_basic_blocks[bbNo - 1]._end_bci = prev_bci;970}971972bbNo++;973}974// Remember prevous bci.975prev_bci = bci;976}977// Set978_basic_blocks[bbNo-1]._end_bci = prev_bci;979980981// Check that the correct number of basicblocks was found982if (bbNo !=_bb_count) {983if (bbNo < _bb_count) {984verify_error("jump into the middle of instruction?");985return;986} else {987verify_error("extra basic blocks - should not happen?");988return;989}990}991992_max_monitors = monitor_count;993994// Now that we have a bound on the depth of the monitor stack, we can995// initialize the CellTypeState-related information.996init_state();997998// We allocate space for all state-vectors for all basicblocks in one huge999// chunk. Then in the next part of the code, we set a pointer in each1000// _basic_block that points to each piece.10011002// The product of bbNo and _state_len can get large if there are lots of1003// basic blocks and stack/locals/monitors. Need to check to make sure1004// we don't overflow the capacity of a pointer.1005if ((unsigned)bbNo > UINTPTR_MAX / sizeof(CellTypeState) / _state_len) {1006report_error("The amount of memory required to analyze this method "1007"exceeds addressable range");1008return;1009}10101011CellTypeState *basicBlockState;1012ALLOC_RESOURCE_ARRAY(basicBlockState, CellTypeState, bbNo * _state_len);1013memset(basicBlockState, 0, bbNo * _state_len * sizeof(CellTypeState));10141015// Make a pass over the basicblocks and assign their state vectors.1016for (int blockNum=0; blockNum < bbNo; blockNum++) {1017BasicBlock *bb = _basic_blocks + blockNum;1018bb->_state = basicBlockState + blockNum * _state_len;10191020#ifdef ASSERT1021if (blockNum + 1 < bbNo) {1022address bcp = _method->bcp_from(bb->_end_bci);1023int bc_len = Bytecodes::java_length_at(_method(), bcp);1024assert(bb->_end_bci + bc_len == bb[1]._bci, "unmatched bci info in basicblock");1025}1026#endif1027}1028#ifdef ASSERT1029{ BasicBlock *bb = &_basic_blocks[bbNo-1];1030address bcp = _method->bcp_from(bb->_end_bci);1031int bc_len = Bytecodes::java_length_at(_method(), bcp);1032assert(bb->_end_bci + bc_len == _method->code_size(), "wrong end bci");1033}1034#endif10351036// Mark all alive blocks1037mark_reachable_code();1038}10391040void GenerateOopMap::setup_method_entry_state() {10411042// Initialize all locals to 'uninit' and set stack-height to 01043make_context_uninitialized();10441045// Initialize CellState type of arguments1046methodsig_to_effect(method()->signature(), method()->is_static(), vars());10471048// If some references must be pre-assigned to null, then set that up1049initialize_vars();10501051// This is the start state1052merge_state_into_bb(&_basic_blocks[0]);10531054assert(_basic_blocks[0].changed(), "we are not getting off the ground");1055}10561057// The instruction at bci is changing size by "delta". Update the basic blocks.1058void GenerateOopMap::update_basic_blocks(int bci, int delta,1059int new_method_size) {1060assert(new_method_size >= method()->code_size() + delta,1061"new method size is too small");10621063_bb_hdr_bits.reinitialize(new_method_size);10641065for(int k = 0; k < _bb_count; k++) {1066if (_basic_blocks[k]._bci > bci) {1067_basic_blocks[k]._bci += delta;1068_basic_blocks[k]._end_bci += delta;1069}1070_bb_hdr_bits.at_put(_basic_blocks[k]._bci, true);1071}1072}10731074//1075// Initvars handling1076//10771078void GenerateOopMap::initialize_vars() {1079for (int k = 0; k < _init_vars->length(); k++)1080_state[_init_vars->at(k)] = CellTypeState::make_slot_ref(k);1081}10821083void GenerateOopMap::add_to_ref_init_set(int localNo) {10841085if (TraceNewOopMapGeneration)1086tty->print_cr("Added init vars: %d", localNo);10871088// Is it already in the set?1089if (_init_vars->contains(localNo) )1090return;10911092_init_vars->append(localNo);1093}10941095//1096// Interpreration code1097//10981099void GenerateOopMap::interp_all() {1100bool change = true;11011102while (change && !_got_error) {1103change = false;1104for (int i = 0; i < _bb_count && !_got_error; i++) {1105BasicBlock *bb = &_basic_blocks[i];1106if (bb->changed()) {1107if (_got_error) return;1108change = true;1109bb->set_changed(false);1110interp_bb(bb);1111}1112}1113}1114}11151116void GenerateOopMap::interp_bb(BasicBlock *bb) {11171118// We do not want to do anything in case the basic-block has not been initialized. This1119// will happen in the case where there is dead-code hang around in a method.1120assert(bb->is_reachable(), "should be reachable or deadcode exist");1121restore_state(bb);11221123BytecodeStream itr(_method);11241125// Set iterator interval to be the current basicblock1126int lim_bci = next_bb_start_pc(bb);1127itr.set_interval(bb->_bci, lim_bci);1128assert(lim_bci != bb->_bci, "must be at least one instruction in a basicblock");1129itr.next(); // read first instruction11301131// Iterates through all bytecodes except the last in a basic block.1132// We handle the last one special, since there is controlflow change.1133while(itr.next_bci() < lim_bci && !_got_error) {1134if (_has_exceptions || _monitor_top != 0) {1135// We do not need to interpret the results of exceptional1136// continuation from this instruction when the method has no1137// exception handlers and the monitor stack is currently1138// empty.1139do_exception_edge(&itr);1140}1141interp1(&itr);1142itr.next();1143}11441145// Handle last instruction.1146if (!_got_error) {1147assert(itr.next_bci() == lim_bci, "must point to end");1148if (_has_exceptions || _monitor_top != 0) {1149do_exception_edge(&itr);1150}1151interp1(&itr);11521153bool fall_through = jump_targets_do(&itr, GenerateOopMap::merge_state, NULL);1154if (_got_error) return;11551156if (itr.code() == Bytecodes::_ret) {1157assert(!fall_through, "cannot be set if ret instruction");1158// Automatically handles 'wide' ret indicies1159ret_jump_targets_do(&itr, GenerateOopMap::merge_state, itr.get_index(), NULL);1160} else if (fall_through) {1161// Hit end of BB, but the instr. was a fall-through instruction,1162// so perform transition as if the BB ended in a "jump".1163if (lim_bci != bb[1]._bci) {1164verify_error("bytecodes fell through last instruction");1165return;1166}1167merge_state_into_bb(bb + 1);1168}1169}1170}11711172void GenerateOopMap::do_exception_edge(BytecodeStream* itr) {1173// Only check exception edge, if bytecode can trap1174if (!Bytecodes::can_trap(itr->code())) return;1175switch (itr->code()) {1176case Bytecodes::_aload_0:1177// These bytecodes can trap for rewriting. We need to assume that1178// they do not throw exceptions to make the monitor analysis work.1179return;11801181case Bytecodes::_ireturn:1182case Bytecodes::_lreturn:1183case Bytecodes::_freturn:1184case Bytecodes::_dreturn:1185case Bytecodes::_areturn:1186case Bytecodes::_return:1187// If the monitor stack height is not zero when we leave the method,1188// then we are either exiting with a non-empty stack or we have1189// found monitor trouble earlier in our analysis. In either case,1190// assume an exception could be taken here.1191if (_monitor_top == 0) {1192return;1193}1194break;11951196case Bytecodes::_monitorexit:1197// If the monitor stack height is bad_monitors, then we have detected a1198// monitor matching problem earlier in the analysis. If the1199// monitor stack height is 0, we are about to pop a monitor1200// off of an empty stack. In either case, the bytecode1201// could throw an exception.1202if (_monitor_top != bad_monitors && _monitor_top != 0) {1203return;1204}1205break;12061207default:1208break;1209}12101211if (_has_exceptions) {1212int bci = itr->bci();1213ExceptionTable exct(method());1214for(int i = 0; i< exct.length(); i++) {1215int start_pc = exct.start_pc(i);1216int end_pc = exct.end_pc(i);1217int handler_pc = exct.handler_pc(i);1218int catch_type = exct.catch_type_index(i);12191220if (start_pc <= bci && bci < end_pc) {1221BasicBlock *excBB = get_basic_block_at(handler_pc);1222guarantee(excBB != NULL, "no basic block for exception");1223CellTypeState *excStk = excBB->stack();1224CellTypeState *cOpStck = stack();1225CellTypeState cOpStck_0 = cOpStck[0];1226int cOpStackTop = _stack_top;12271228// Exception stacks are always the same.1229assert(method()->max_stack() > 0, "sanity check");12301231// We remembered the size and first element of "cOpStck"1232// above; now we temporarily set them to the appropriate1233// values for an exception handler. */1234cOpStck[0] = CellTypeState::make_slot_ref(_max_locals);1235_stack_top = 1;12361237merge_state_into_bb(excBB);12381239// Now undo the temporary change.1240cOpStck[0] = cOpStck_0;1241_stack_top = cOpStackTop;12421243// If this is a "catch all" handler, then we do not need to1244// consider any additional handlers.1245if (catch_type == 0) {1246return;1247}1248}1249}1250}12511252// It is possible that none of the exception handlers would have caught1253// the exception. In this case, we will exit the method. We must1254// ensure that the monitor stack is empty in this case.1255if (_monitor_top == 0) {1256return;1257}12581259// We pessimistically assume that this exception can escape the1260// method. (It is possible that it will always be caught, but1261// we don't care to analyse the types of the catch clauses.)12621263// We don't set _monitor_top to bad_monitors because there are no successors1264// to this exceptional exit.12651266if (log_is_enabled(Info, monitormismatch) && _monitor_safe) {1267// We check _monitor_safe so that we only report the first mismatched1268// exceptional exit.1269report_monitor_mismatch("non-empty monitor stack at exceptional exit");1270}1271_monitor_safe = false;12721273}12741275void GenerateOopMap::report_monitor_mismatch(const char *msg) {1276ResourceMark rm;1277LogStream ls(Log(monitormismatch)::info());1278ls.print("Monitor mismatch in method ");1279method()->print_short_name(&ls);1280ls.print_cr(": %s", msg);1281}12821283void GenerateOopMap::print_states(outputStream *os,1284CellTypeState* vec, int num) {1285for (int i = 0; i < num; i++) {1286vec[i].print(tty);1287}1288}12891290// Print the state values at the current bytecode.1291void GenerateOopMap::print_current_state(outputStream *os,1292BytecodeStream *currentBC,1293bool detailed) {1294if (detailed) {1295os->print(" %4d vars = ", currentBC->bci());1296print_states(os, vars(), _max_locals);1297os->print(" %s", Bytecodes::name(currentBC->code()));1298} else {1299os->print(" %4d vars = '%s' ", currentBC->bci(), state_vec_to_string(vars(), _max_locals));1300os->print(" stack = '%s' ", state_vec_to_string(stack(), _stack_top));1301if (_monitor_top != bad_monitors) {1302os->print(" monitors = '%s' \t%s", state_vec_to_string(monitors(), _monitor_top), Bytecodes::name(currentBC->code()));1303} else {1304os->print(" [bad monitor stack]");1305}1306}13071308switch(currentBC->code()) {1309case Bytecodes::_invokevirtual:1310case Bytecodes::_invokespecial:1311case Bytecodes::_invokestatic:1312case Bytecodes::_invokedynamic:1313case Bytecodes::_invokeinterface: {1314int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2_cpcache();1315ConstantPool* cp = method()->constants();1316int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx);1317int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);1318Symbol* signature = cp->symbol_at(signatureIdx);1319os->print("%s", signature->as_C_string());1320}1321default:1322break;1323}13241325if (detailed) {1326os->cr();1327os->print(" stack = ");1328print_states(os, stack(), _stack_top);1329os->cr();1330if (_monitor_top != bad_monitors) {1331os->print(" monitors = ");1332print_states(os, monitors(), _monitor_top);1333} else {1334os->print(" [bad monitor stack]");1335}1336}13371338os->cr();1339}13401341// Sets the current state to be the state after executing the1342// current instruction, starting in the current state.1343void GenerateOopMap::interp1(BytecodeStream *itr) {1344if (TraceNewOopMapGeneration) {1345print_current_state(tty, itr, TraceNewOopMapGenerationDetailed);1346}13471348// Should we report the results? Result is reported *before* the instruction at the current bci is executed.1349// However, not for calls. For calls we do not want to include the arguments, so we postpone the reporting until1350// they have been popped (in method ppl).1351if (_report_result == true) {1352switch(itr->code()) {1353case Bytecodes::_invokevirtual:1354case Bytecodes::_invokespecial:1355case Bytecodes::_invokestatic:1356case Bytecodes::_invokedynamic:1357case Bytecodes::_invokeinterface:1358_itr_send = itr;1359_report_result_for_send = true;1360break;1361default:1362fill_stackmap_for_opcodes(itr, vars(), stack(), _stack_top);1363break;1364}1365}13661367// abstract interpretation of current opcode1368switch(itr->code()) {1369case Bytecodes::_nop: break;1370case Bytecodes::_goto: break;1371case Bytecodes::_goto_w: break;1372case Bytecodes::_iinc: break;1373case Bytecodes::_return: do_return_monitor_check();1374break;13751376case Bytecodes::_aconst_null:1377case Bytecodes::_new: ppush1(CellTypeState::make_line_ref(itr->bci()));1378break;13791380case Bytecodes::_iconst_m1:1381case Bytecodes::_iconst_0:1382case Bytecodes::_iconst_1:1383case Bytecodes::_iconst_2:1384case Bytecodes::_iconst_3:1385case Bytecodes::_iconst_4:1386case Bytecodes::_iconst_5:1387case Bytecodes::_fconst_0:1388case Bytecodes::_fconst_1:1389case Bytecodes::_fconst_2:1390case Bytecodes::_bipush:1391case Bytecodes::_sipush: ppush1(valCTS); break;13921393case Bytecodes::_lconst_0:1394case Bytecodes::_lconst_1:1395case Bytecodes::_dconst_0:1396case Bytecodes::_dconst_1: ppush(vvCTS); break;13971398case Bytecodes::_ldc2_w: ppush(vvCTS); break;13991400case Bytecodes::_ldc: // fall through:1401case Bytecodes::_ldc_w: do_ldc(itr->bci()); break;14021403case Bytecodes::_iload:1404case Bytecodes::_fload: ppload(vCTS, itr->get_index()); break;14051406case Bytecodes::_lload:1407case Bytecodes::_dload: ppload(vvCTS,itr->get_index()); break;14081409case Bytecodes::_aload: ppload(rCTS, itr->get_index()); break;14101411case Bytecodes::_iload_0:1412case Bytecodes::_fload_0: ppload(vCTS, 0); break;1413case Bytecodes::_iload_1:1414case Bytecodes::_fload_1: ppload(vCTS, 1); break;1415case Bytecodes::_iload_2:1416case Bytecodes::_fload_2: ppload(vCTS, 2); break;1417case Bytecodes::_iload_3:1418case Bytecodes::_fload_3: ppload(vCTS, 3); break;14191420case Bytecodes::_lload_0:1421case Bytecodes::_dload_0: ppload(vvCTS, 0); break;1422case Bytecodes::_lload_1:1423case Bytecodes::_dload_1: ppload(vvCTS, 1); break;1424case Bytecodes::_lload_2:1425case Bytecodes::_dload_2: ppload(vvCTS, 2); break;1426case Bytecodes::_lload_3:1427case Bytecodes::_dload_3: ppload(vvCTS, 3); break;14281429case Bytecodes::_aload_0: ppload(rCTS, 0); break;1430case Bytecodes::_aload_1: ppload(rCTS, 1); break;1431case Bytecodes::_aload_2: ppload(rCTS, 2); break;1432case Bytecodes::_aload_3: ppload(rCTS, 3); break;14331434case Bytecodes::_iaload:1435case Bytecodes::_faload:1436case Bytecodes::_baload:1437case Bytecodes::_caload:1438case Bytecodes::_saload: pp(vrCTS, vCTS); break;14391440case Bytecodes::_laload: pp(vrCTS, vvCTS); break;1441case Bytecodes::_daload: pp(vrCTS, vvCTS); break;14421443case Bytecodes::_aaload: pp_new_ref(vrCTS, itr->bci()); break;14441445case Bytecodes::_istore:1446case Bytecodes::_fstore: ppstore(vCTS, itr->get_index()); break;14471448case Bytecodes::_lstore:1449case Bytecodes::_dstore: ppstore(vvCTS, itr->get_index()); break;14501451case Bytecodes::_astore: do_astore(itr->get_index()); break;14521453case Bytecodes::_istore_0:1454case Bytecodes::_fstore_0: ppstore(vCTS, 0); break;1455case Bytecodes::_istore_1:1456case Bytecodes::_fstore_1: ppstore(vCTS, 1); break;1457case Bytecodes::_istore_2:1458case Bytecodes::_fstore_2: ppstore(vCTS, 2); break;1459case Bytecodes::_istore_3:1460case Bytecodes::_fstore_3: ppstore(vCTS, 3); break;14611462case Bytecodes::_lstore_0:1463case Bytecodes::_dstore_0: ppstore(vvCTS, 0); break;1464case Bytecodes::_lstore_1:1465case Bytecodes::_dstore_1: ppstore(vvCTS, 1); break;1466case Bytecodes::_lstore_2:1467case Bytecodes::_dstore_2: ppstore(vvCTS, 2); break;1468case Bytecodes::_lstore_3:1469case Bytecodes::_dstore_3: ppstore(vvCTS, 3); break;14701471case Bytecodes::_astore_0: do_astore(0); break;1472case Bytecodes::_astore_1: do_astore(1); break;1473case Bytecodes::_astore_2: do_astore(2); break;1474case Bytecodes::_astore_3: do_astore(3); break;14751476case Bytecodes::_iastore:1477case Bytecodes::_fastore:1478case Bytecodes::_bastore:1479case Bytecodes::_castore:1480case Bytecodes::_sastore: ppop(vvrCTS); break;1481case Bytecodes::_lastore:1482case Bytecodes::_dastore: ppop(vvvrCTS); break;1483case Bytecodes::_aastore: ppop(rvrCTS); break;14841485case Bytecodes::_pop: ppop_any(1); break;1486case Bytecodes::_pop2: ppop_any(2); break;14871488case Bytecodes::_dup: ppdupswap(1, "11"); break;1489case Bytecodes::_dup_x1: ppdupswap(2, "121"); break;1490case Bytecodes::_dup_x2: ppdupswap(3, "1321"); break;1491case Bytecodes::_dup2: ppdupswap(2, "2121"); break;1492case Bytecodes::_dup2_x1: ppdupswap(3, "21321"); break;1493case Bytecodes::_dup2_x2: ppdupswap(4, "214321"); break;1494case Bytecodes::_swap: ppdupswap(2, "12"); break;14951496case Bytecodes::_iadd:1497case Bytecodes::_fadd:1498case Bytecodes::_isub:1499case Bytecodes::_fsub:1500case Bytecodes::_imul:1501case Bytecodes::_fmul:1502case Bytecodes::_idiv:1503case Bytecodes::_fdiv:1504case Bytecodes::_irem:1505case Bytecodes::_frem:1506case Bytecodes::_ishl:1507case Bytecodes::_ishr:1508case Bytecodes::_iushr:1509case Bytecodes::_iand:1510case Bytecodes::_ior:1511case Bytecodes::_ixor:1512case Bytecodes::_l2f:1513case Bytecodes::_l2i:1514case Bytecodes::_d2f:1515case Bytecodes::_d2i:1516case Bytecodes::_fcmpl:1517case Bytecodes::_fcmpg: pp(vvCTS, vCTS); break;15181519case Bytecodes::_ladd:1520case Bytecodes::_dadd:1521case Bytecodes::_lsub:1522case Bytecodes::_dsub:1523case Bytecodes::_lmul:1524case Bytecodes::_dmul:1525case Bytecodes::_ldiv:1526case Bytecodes::_ddiv:1527case Bytecodes::_lrem:1528case Bytecodes::_drem:1529case Bytecodes::_land:1530case Bytecodes::_lor:1531case Bytecodes::_lxor: pp(vvvvCTS, vvCTS); break;15321533case Bytecodes::_ineg:1534case Bytecodes::_fneg:1535case Bytecodes::_i2f:1536case Bytecodes::_f2i:1537case Bytecodes::_i2c:1538case Bytecodes::_i2s:1539case Bytecodes::_i2b: pp(vCTS, vCTS); break;15401541case Bytecodes::_lneg:1542case Bytecodes::_dneg:1543case Bytecodes::_l2d:1544case Bytecodes::_d2l: pp(vvCTS, vvCTS); break;15451546case Bytecodes::_lshl:1547case Bytecodes::_lshr:1548case Bytecodes::_lushr: pp(vvvCTS, vvCTS); break;15491550case Bytecodes::_i2l:1551case Bytecodes::_i2d:1552case Bytecodes::_f2l:1553case Bytecodes::_f2d: pp(vCTS, vvCTS); break;15541555case Bytecodes::_lcmp: pp(vvvvCTS, vCTS); break;1556case Bytecodes::_dcmpl:1557case Bytecodes::_dcmpg: pp(vvvvCTS, vCTS); break;15581559case Bytecodes::_ifeq:1560case Bytecodes::_ifne:1561case Bytecodes::_iflt:1562case Bytecodes::_ifge:1563case Bytecodes::_ifgt:1564case Bytecodes::_ifle:1565case Bytecodes::_tableswitch: ppop1(valCTS);1566break;1567case Bytecodes::_ireturn:1568case Bytecodes::_freturn: do_return_monitor_check();1569ppop1(valCTS);1570break;1571case Bytecodes::_if_icmpeq:1572case Bytecodes::_if_icmpne:1573case Bytecodes::_if_icmplt:1574case Bytecodes::_if_icmpge:1575case Bytecodes::_if_icmpgt:1576case Bytecodes::_if_icmple: ppop(vvCTS);1577break;15781579case Bytecodes::_lreturn: do_return_monitor_check();1580ppop(vvCTS);1581break;15821583case Bytecodes::_dreturn: do_return_monitor_check();1584ppop(vvCTS);1585break;15861587case Bytecodes::_if_acmpeq:1588case Bytecodes::_if_acmpne: ppop(rrCTS); break;15891590case Bytecodes::_jsr: do_jsr(itr->dest()); break;1591case Bytecodes::_jsr_w: do_jsr(itr->dest_w()); break;15921593case Bytecodes::_getstatic: do_field(true, true, itr->get_index_u2_cpcache(), itr->bci()); break;1594case Bytecodes::_putstatic: do_field(false, true, itr->get_index_u2_cpcache(), itr->bci()); break;1595case Bytecodes::_getfield: do_field(true, false, itr->get_index_u2_cpcache(), itr->bci()); break;1596case Bytecodes::_putfield: do_field(false, false, itr->get_index_u2_cpcache(), itr->bci()); break;15971598case Bytecodes::_invokevirtual:1599case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_u2_cpcache(), itr->bci()); break;1600case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_u2_cpcache(), itr->bci()); break;1601case Bytecodes::_invokedynamic: do_method(true, false, itr->get_index_u4(), itr->bci()); break;1602case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_u2_cpcache(), itr->bci()); break;1603case Bytecodes::_newarray:1604case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break;1605case Bytecodes::_checkcast: do_checkcast(); break;1606case Bytecodes::_arraylength:1607case Bytecodes::_instanceof: pp(rCTS, vCTS); break;1608case Bytecodes::_monitorenter: do_monitorenter(itr->bci()); break;1609case Bytecodes::_monitorexit: do_monitorexit(itr->bci()); break;16101611case Bytecodes::_athrow: // handled by do_exception_edge() BUT ...1612// vlh(apple): do_exception_edge() does not get1613// called if method has no exception handlers1614if ((!_has_exceptions) && (_monitor_top > 0)) {1615_monitor_safe = false;1616}1617break;16181619case Bytecodes::_areturn: do_return_monitor_check();1620ppop1(refCTS);1621break;1622case Bytecodes::_ifnull:1623case Bytecodes::_ifnonnull: ppop1(refCTS); break;1624case Bytecodes::_multianewarray: do_multianewarray(*(itr->bcp()+3), itr->bci()); break;16251626case Bytecodes::_wide: fatal("Iterator should skip this bytecode"); break;1627case Bytecodes::_ret: break;16281629// Java opcodes1630case Bytecodes::_lookupswitch: ppop1(valCTS); break;16311632default:1633tty->print("unexpected opcode: %d\n", itr->code());1634ShouldNotReachHere();1635break;1636}1637}16381639void GenerateOopMap::check_type(CellTypeState expected, CellTypeState actual) {1640if (!expected.equal_kind(actual)) {1641verify_error("wrong type on stack (found: %c expected: %c)", actual.to_char(), expected.to_char());1642}1643}16441645void GenerateOopMap::ppstore(CellTypeState *in, int loc_no) {1646while(!(*in).is_bottom()) {1647CellTypeState expected =*in++;1648CellTypeState actual = pop();1649check_type(expected, actual);1650assert(loc_no >= 0, "sanity check");1651set_var(loc_no++, actual);1652}1653}16541655void GenerateOopMap::ppload(CellTypeState *out, int loc_no) {1656while(!(*out).is_bottom()) {1657CellTypeState out1 = *out++;1658CellTypeState vcts = get_var(loc_no);1659assert(out1.can_be_reference() || out1.can_be_value(),1660"can only load refs. and values.");1661if (out1.is_reference()) {1662assert(loc_no>=0, "sanity check");1663if (!vcts.is_reference()) {1664// We were asked to push a reference, but the type of the1665// variable can be something else1666_conflict = true;1667if (vcts.can_be_uninit()) {1668// It is a ref-uninit conflict (at least). If there are other1669// problems, we'll get them in the next round1670add_to_ref_init_set(loc_no);1671vcts = out1;1672} else {1673// It wasn't a ref-uninit conflict. So must be a1674// ref-val or ref-pc conflict. Split the variable.1675record_refval_conflict(loc_no);1676vcts = out1;1677}1678push(out1); // recover...1679} else {1680push(vcts); // preserve reference.1681}1682// Otherwise it is a conflict, but one that verification would1683// have caught if illegal. In particular, it can't be a topCTS1684// resulting from mergeing two difference pcCTS's since the verifier1685// would have rejected any use of such a merge.1686} else {1687push(out1); // handle val/init conflict1688}1689loc_no++;1690}1691}16921693void GenerateOopMap::ppdupswap(int poplen, const char *out) {1694CellTypeState actual[5];1695assert(poplen < 5, "this must be less than length of actual vector");16961697// Pop all arguments.1698for (int i = 0; i < poplen; i++) {1699actual[i] = pop();1700}1701// Field _state is uninitialized when calling push.1702for (int i = poplen; i < 5; i++) {1703actual[i] = CellTypeState::uninit;1704}17051706// put them back1707char push_ch = *out++;1708while (push_ch != '\0') {1709int idx = push_ch - '1';1710assert(idx >= 0 && idx < poplen, "wrong arguments");1711push(actual[idx]);1712push_ch = *out++;1713}1714}17151716void GenerateOopMap::ppop1(CellTypeState out) {1717CellTypeState actual = pop();1718check_type(out, actual);1719}17201721void GenerateOopMap::ppop(CellTypeState *out) {1722while (!(*out).is_bottom()) {1723ppop1(*out++);1724}1725}17261727void GenerateOopMap::ppush1(CellTypeState in) {1728assert(in.is_reference() | in.is_value(), "sanity check");1729push(in);1730}17311732void GenerateOopMap::ppush(CellTypeState *in) {1733while (!(*in).is_bottom()) {1734ppush1(*in++);1735}1736}17371738void GenerateOopMap::pp(CellTypeState *in, CellTypeState *out) {1739ppop(in);1740ppush(out);1741}17421743void GenerateOopMap::pp_new_ref(CellTypeState *in, int bci) {1744ppop(in);1745ppush1(CellTypeState::make_line_ref(bci));1746}17471748void GenerateOopMap::ppop_any(int poplen) {1749if (_stack_top >= poplen) {1750_stack_top -= poplen;1751} else {1752verify_error("stack underflow");1753}1754}17551756// Replace all occurences of the state 'match' with the state 'replace'1757// in our current state vector.1758void GenerateOopMap::replace_all_CTS_matches(CellTypeState match,1759CellTypeState replace) {1760int i;1761int len = _max_locals + _stack_top;1762bool change = false;17631764for (i = len - 1; i >= 0; i--) {1765if (match.equal(_state[i])) {1766_state[i] = replace;1767}1768}17691770if (_monitor_top > 0) {1771int base = _max_locals + _max_stack;1772len = base + _monitor_top;1773for (i = len - 1; i >= base; i--) {1774if (match.equal(_state[i])) {1775_state[i] = replace;1776}1777}1778}1779}17801781void GenerateOopMap::do_checkcast() {1782CellTypeState actual = pop();1783check_type(refCTS, actual);1784push(actual);1785}17861787void GenerateOopMap::do_monitorenter(int bci) {1788CellTypeState actual = pop();1789if (_monitor_top == bad_monitors) {1790return;1791}17921793// Bail out when we get repeated locks on an identical monitor. This case1794// isn't too hard to handle and can be made to work if supporting nested1795// redundant synchronized statements becomes a priority.1796//1797// See also "Note" in do_monitorexit(), below.1798if (actual.is_lock_reference()) {1799_monitor_top = bad_monitors;1800_monitor_safe = false;18011802if (log_is_enabled(Info, monitormismatch)) {1803report_monitor_mismatch("nested redundant lock -- bailout...");1804}1805return;1806}18071808CellTypeState lock = CellTypeState::make_lock_ref(bci);1809check_type(refCTS, actual);1810if (!actual.is_info_top()) {1811replace_all_CTS_matches(actual, lock);1812monitor_push(lock);1813}1814}18151816void GenerateOopMap::do_monitorexit(int bci) {1817CellTypeState actual = pop();1818if (_monitor_top == bad_monitors) {1819return;1820}1821check_type(refCTS, actual);1822CellTypeState expected = monitor_pop();1823if (!actual.is_lock_reference() || !expected.equal(actual)) {1824// The monitor we are exiting is not verifiably the one1825// on the top of our monitor stack. This causes a monitor1826// mismatch.1827_monitor_top = bad_monitors;1828_monitor_safe = false;18291830// We need to mark this basic block as changed so that1831// this monitorexit will be visited again. We need to1832// do this to ensure that we have accounted for the1833// possibility that this bytecode will throw an1834// exception.1835BasicBlock* bb = get_basic_block_containing(bci);1836guarantee(bb != NULL, "no basic block for bci");1837bb->set_changed(true);1838bb->_monitor_top = bad_monitors;18391840if (log_is_enabled(Info, monitormismatch)) {1841report_monitor_mismatch("improper monitor pair");1842}1843} else {1844// This code is a fix for the case where we have repeated1845// locking of the same object in straightline code. We clear1846// out the lock when it is popped from the monitor stack1847// and replace it with an unobtrusive reference value that can1848// be locked again.1849//1850// Note: when generateOopMap is fixed to properly handle repeated,1851// nested, redundant locks on the same object, then this1852// fix will need to be removed at that time.1853replace_all_CTS_matches(actual, CellTypeState::make_line_ref(bci));1854}1855}18561857void GenerateOopMap::do_return_monitor_check() {1858if (_monitor_top > 0) {1859// The monitor stack must be empty when we leave the method1860// for the monitors to be properly matched.1861_monitor_safe = false;18621863// Since there are no successors to the *return bytecode, it1864// isn't necessary to set _monitor_top to bad_monitors.18651866if (log_is_enabled(Info, monitormismatch)) {1867report_monitor_mismatch("non-empty monitor stack at return");1868}1869}1870}18711872void GenerateOopMap::do_jsr(int targ_bci) {1873push(CellTypeState::make_addr(targ_bci));1874}1875187618771878void GenerateOopMap::do_ldc(int bci) {1879Bytecode_loadconstant ldc(methodHandle(Thread::current(), method()), bci);1880ConstantPool* cp = method()->constants();1881constantTag tag = cp->tag_at(ldc.pool_index()); // idx is index in resolved_references1882BasicType bt = ldc.result_type();1883#ifdef ASSERT1884BasicType tag_bt = (tag.is_dynamic_constant() || tag.is_dynamic_constant_in_error()) ? bt : tag.basic_type();1885assert(bt == tag_bt, "same result");1886#endif1887CellTypeState cts;1888if (is_reference_type(bt)) { // could be T_ARRAY with condy1889assert(!tag.is_string_index() && !tag.is_klass_index(), "Unexpected index tag");1890cts = CellTypeState::make_line_ref(bci);1891} else {1892cts = valCTS;1893}1894ppush1(cts);1895}18961897void GenerateOopMap::do_multianewarray(int dims, int bci) {1898assert(dims >= 1, "sanity check");1899for(int i = dims -1; i >=0; i--) {1900ppop1(valCTS);1901}1902ppush1(CellTypeState::make_line_ref(bci));1903}19041905void GenerateOopMap::do_astore(int idx) {1906CellTypeState r_or_p = pop();1907if (!r_or_p.is_address() && !r_or_p.is_reference()) {1908// We actually expected ref or pc, but we only report that we expected a ref. It does not1909// really matter (at least for now)1910verify_error("wrong type on stack (found: %c, expected: {pr})", r_or_p.to_char());1911return;1912}1913set_var(idx, r_or_p);1914}19151916// Copies bottom/zero terminated CTS string from "src" into "dst".1917// Does NOT terminate with a bottom. Returns the number of cells copied.1918int GenerateOopMap::copy_cts(CellTypeState *dst, CellTypeState *src) {1919int idx = 0;1920while (!src[idx].is_bottom()) {1921dst[idx] = src[idx];1922idx++;1923}1924return idx;1925}19261927void GenerateOopMap::do_field(int is_get, int is_static, int idx, int bci) {1928// Dig up signature for field in constant pool1929ConstantPool* cp = method()->constants();1930int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx);1931int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);1932Symbol* signature = cp->symbol_at(signatureIdx);19331934CellTypeState temp[4];1935CellTypeState *eff = signature_to_effect(signature, bci, temp);19361937CellTypeState in[4];1938CellTypeState *out;1939int i = 0;19401941if (is_get) {1942out = eff;1943} else {1944out = epsilonCTS;1945i = copy_cts(in, eff);1946}1947if (!is_static) in[i++] = CellTypeState::ref;1948in[i] = CellTypeState::bottom;1949assert(i<=3, "sanity check");1950pp(in, out);1951}19521953void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci) {1954// Dig up signature for field in constant pool1955ConstantPool* cp = _method->constants();1956Symbol* signature = cp->signature_ref_at(idx);19571958// Parse method signature1959CellTypeState out[4];1960CellTypeState in[MAXARGSIZE+1]; // Includes result1961ComputeCallStack cse(signature);19621963// Compute return type1964int res_length= cse.compute_for_returntype(out);19651966// Temporary hack.1967if (out[0].equal(CellTypeState::ref) && out[1].equal(CellTypeState::bottom)) {1968out[0] = CellTypeState::make_line_ref(bci);1969}19701971assert(res_length<=4, "max value should be vv");19721973// Compute arguments1974int arg_length = cse.compute_for_parameters(is_static != 0, in);1975assert(arg_length<=MAXARGSIZE, "too many locals");19761977// Pop arguments1978for (int i = arg_length - 1; i >= 0; i--) ppop1(in[i]);// Do args in reverse order.19791980// Report results1981if (_report_result_for_send == true) {1982fill_stackmap_for_opcodes(_itr_send, vars(), stack(), _stack_top);1983_report_result_for_send = false;1984}19851986// Push return address1987ppush(out);1988}19891990// This is used to parse the signature for fields, since they are very simple...1991CellTypeState *GenerateOopMap::signature_to_effect(const Symbol* sig, int bci, CellTypeState *out) {1992// Object and array1993BasicType bt = Signature::basic_type(sig);1994if (is_reference_type(bt)) {1995out[0] = CellTypeState::make_line_ref(bci);1996out[1] = CellTypeState::bottom;1997return out;1998}1999if (is_double_word_type(bt)) return vvCTS; // Long and Double2000if (bt == T_VOID) return epsilonCTS; // Void2001return vCTS; // Otherwise2002}20032004uint64_t GenerateOopMap::_total_byte_count = 0;2005elapsedTimer GenerateOopMap::_total_oopmap_time;20062007// This function assumes "bcs" is at a "ret" instruction and that the vars2008// state is valid for that instruction. Furthermore, the ret instruction2009// must be the last instruction in "bb" (we store information about the2010// "ret" in "bb").2011void GenerateOopMap::ret_jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int varNo, int *data) {2012CellTypeState ra = vars()[varNo];2013if (!ra.is_good_address()) {2014verify_error("ret returns from two jsr subroutines?");2015return;2016}2017int target = ra.get_info();20182019RetTableEntry* rtEnt = _rt.find_jsrs_for_target(target);2020int bci = bcs->bci();2021for (int i = 0; i < rtEnt->nof_jsrs(); i++) {2022int target_bci = rtEnt->jsrs(i);2023// Make sure a jrtRet does not set the changed bit for dead basicblock.2024BasicBlock* jsr_bb = get_basic_block_containing(target_bci - 1);2025debug_only(BasicBlock* target_bb = &jsr_bb[1];)2026assert(target_bb == get_basic_block_at(target_bci), "wrong calc. of successor basicblock");2027bool alive = jsr_bb->is_alive();2028if (TraceNewOopMapGeneration) {2029tty->print("pc = %d, ret -> %d alive: %s\n", bci, target_bci, alive ? "true" : "false");2030}2031if (alive) jmpFct(this, target_bci, data);2032}2033}20342035//2036// Debug method2037//2038char* GenerateOopMap::state_vec_to_string(CellTypeState* vec, int len) {2039#ifdef ASSERT2040int checklen = MAX3(_max_locals, _max_stack, _max_monitors) + 1;2041assert(len < checklen, "state_vec_buf overflow");2042#endif2043for (int i = 0; i < len; i++) _state_vec_buf[i] = vec[i].to_char();2044_state_vec_buf[len] = 0;2045return _state_vec_buf;2046}20472048void GenerateOopMap::print_time() {2049tty->print_cr ("Accumulated oopmap times:");2050tty->print_cr ("---------------------------");2051tty->print_cr (" Total : %3.3f sec.", GenerateOopMap::_total_oopmap_time.seconds());2052tty->print_cr (" (%3.0f bytecodes per sec) ",2053GenerateOopMap::_total_byte_count / GenerateOopMap::_total_oopmap_time.seconds());2054}20552056//2057// ============ Main Entry Point ===========2058//2059GenerateOopMap::GenerateOopMap(const methodHandle& method) {2060// We have to initialize all variables here, that can be queried directly2061_method = method;2062_max_locals=0;2063_init_vars = NULL;20642065#ifndef PRODUCT2066// If we are doing a detailed trace, include the regular trace information.2067if (TraceNewOopMapGenerationDetailed) {2068TraceNewOopMapGeneration = true;2069}2070#endif2071}20722073bool GenerateOopMap::compute_map(Thread* current) {2074#ifndef PRODUCT2075if (TimeOopMap2) {2076method()->print_short_name(tty);2077tty->print(" ");2078}2079if (TimeOopMap) {2080_total_byte_count += method()->code_size();2081}2082#endif2083TraceTime t_single("oopmap time", TimeOopMap2);2084TraceTime t_all(NULL, &_total_oopmap_time, TimeOopMap);20852086// Initialize values2087_got_error = false;2088_conflict = false;2089_max_locals = method()->max_locals();2090_max_stack = method()->max_stack();2091_has_exceptions = (method()->has_exception_handler());2092_nof_refval_conflicts = 0;2093_init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars2094_report_result = false;2095_report_result_for_send = false;2096_new_var_map = NULL;2097_ret_adr_tos = new GrowableArray<intptr_t>(5); // 5 seems like a good number;2098_did_rewriting = false;2099_did_relocation = false;21002101if (TraceNewOopMapGeneration) {2102tty->print("Method name: %s\n", method()->name()->as_C_string());2103if (Verbose) {2104_method->print_codes();2105tty->print_cr("Exception table:");2106ExceptionTable excps(method());2107for(int i = 0; i < excps.length(); i ++) {2108tty->print_cr("[%d - %d] -> %d",2109excps.start_pc(i), excps.end_pc(i), excps.handler_pc(i));2110}2111}2112}21132114// if no code - do nothing2115// compiler needs info2116if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) {2117fill_stackmap_prolog(0);2118fill_stackmap_epilog();2119return true;2120}2121// Step 1: Compute all jump targets and their return value2122if (!_got_error)2123_rt.compute_ret_table(_method);21242125// Step 2: Find all basic blocks and count GC points2126if (!_got_error)2127mark_bbheaders_and_count_gc_points();21282129// Step 3: Calculate stack maps2130if (!_got_error)2131do_interpretation();21322133// Step 4:Return results2134if (!_got_error && report_results())2135report_result();21362137return !_got_error;2138}21392140// Error handling methods2141//2142// If we compute from a suitable JavaThread then we create an exception for the GenerateOopMap2143// calling code to retrieve (via exception()) and throw if desired (in most cases errors are ignored).2144// Otherwise it is considered a fatal error to hit malformed bytecode.2145void GenerateOopMap::error_work(const char *format, va_list ap) {2146_got_error = true;2147char msg_buffer[512];2148os::vsnprintf(msg_buffer, sizeof(msg_buffer), format, ap);2149// Append method name2150char msg_buffer2[512];2151os::snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg_buffer, method()->name()->as_C_string());2152Thread* current = Thread::current();2153if (current->can_call_java()) {2154_exception = Exceptions::new_exception(current->as_Java_thread(),2155vmSymbols::java_lang_LinkageError(),2156msg_buffer2);2157} else {2158fatal("%s", msg_buffer2);2159}2160}21612162void GenerateOopMap::report_error(const char *format, ...) {2163va_list ap;2164va_start(ap, format);2165error_work(format, ap);2166}21672168void GenerateOopMap::verify_error(const char *format, ...) {2169// We do not distinguish between different types of errors for verification2170// errors. Let the verifier give a better message.2171report_error("Illegal class file encountered. Try running with -Xverify:all");2172}21732174//2175// Report result opcodes2176//2177void GenerateOopMap::report_result() {21782179if (TraceNewOopMapGeneration) tty->print_cr("Report result pass");21802181// We now want to report the result of the parse2182_report_result = true;21832184// Prolog code2185fill_stackmap_prolog(_gc_points);21862187// Mark everything changed, then do one interpretation pass.2188for (int i = 0; i<_bb_count; i++) {2189if (_basic_blocks[i].is_reachable()) {2190_basic_blocks[i].set_changed(true);2191interp_bb(&_basic_blocks[i]);2192}2193}21942195// Note: Since we are skipping dead-code when we are reporting results, then2196// the no. of encountered gc-points might be fewer than the previously number2197// we have counted. (dead-code is a pain - it should be removed before we get here)2198fill_stackmap_epilog();21992200// Report initvars2201fill_init_vars(_init_vars);22022203_report_result = false;2204}22052206void GenerateOopMap::result_for_basicblock(int bci) {2207if (TraceNewOopMapGeneration) tty->print_cr("Report result pass for basicblock");22082209// We now want to report the result of the parse2210_report_result = true;22112212// Find basicblock and report results2213BasicBlock* bb = get_basic_block_containing(bci);2214guarantee(bb != NULL, "no basic block for bci");2215assert(bb->is_reachable(), "getting result from unreachable basicblock");2216bb->set_changed(true);2217interp_bb(bb);2218}22192220//2221// Conflict handling code2222//22232224void GenerateOopMap::record_refval_conflict(int varNo) {2225assert(varNo>=0 && varNo< _max_locals, "index out of range");22262227if (TraceOopMapRewrites) {2228tty->print("### Conflict detected (local no: %d)\n", varNo);2229}22302231if (!_new_var_map) {2232_new_var_map = NEW_RESOURCE_ARRAY(int, _max_locals);2233for (int k = 0; k < _max_locals; k++) _new_var_map[k] = k;2234}22352236if ( _new_var_map[varNo] == varNo) {2237// Check if max. number of locals has been reached2238if (_max_locals + _nof_refval_conflicts >= MAX_LOCAL_VARS) {2239report_error("Rewriting exceeded local variable limit");2240return;2241}2242_new_var_map[varNo] = _max_locals + _nof_refval_conflicts;2243_nof_refval_conflicts++;2244}2245}22462247void GenerateOopMap::rewrite_refval_conflicts()2248{2249// We can get here two ways: Either a rewrite conflict was detected, or2250// an uninitialize reference was detected. In the second case, we do not2251// do any rewriting, we just want to recompute the reference set with the2252// new information22532254int nof_conflicts = 0; // Used for debugging only22552256if ( _nof_refval_conflicts == 0 )2257return;22582259// Check if rewrites are allowed in this parse.2260if (!allow_rewrites()) {2261fatal("Rewriting method not allowed at this stage");2262}226322642265// Tracing flag2266_did_rewriting = true;22672268if (TraceOopMapRewrites) {2269tty->print_cr("ref/value conflict for method %s - bytecodes are getting rewritten", method()->name()->as_C_string());2270method()->print();2271method()->print_codes();2272}22732274assert(_new_var_map!=NULL, "nothing to rewrite");2275assert(_conflict==true, "We should not be here");22762277compute_ret_adr_at_TOS();2278if (!_got_error) {2279for (int k = 0; k < _max_locals && !_got_error; k++) {2280if (_new_var_map[k] != k) {2281if (TraceOopMapRewrites) {2282tty->print_cr("Rewriting: %d -> %d", k, _new_var_map[k]);2283}2284rewrite_refval_conflict(k, _new_var_map[k]);2285if (_got_error) return;2286nof_conflicts++;2287}2288}2289}22902291assert(nof_conflicts == _nof_refval_conflicts, "sanity check");22922293// Adjust the number of locals2294method()->set_max_locals(_max_locals+_nof_refval_conflicts);2295_max_locals += _nof_refval_conflicts;22962297// That was that...2298_new_var_map = NULL;2299_nof_refval_conflicts = 0;2300}23012302void GenerateOopMap::rewrite_refval_conflict(int from, int to) {2303bool startOver;2304do {2305// Make sure that the BytecodeStream is constructed in the loop, since2306// during rewriting a new method is going to be used, and the next time2307// around we want to use that.2308BytecodeStream bcs(_method);2309startOver = false;23102311while( !startOver && !_got_error &&2312// test bcs in case method changed and it became invalid2313bcs.next() >=0) {2314startOver = rewrite_refval_conflict_inst(&bcs, from, to);2315}2316} while (startOver && !_got_error);2317}23182319/* If the current instruction is one that uses local variable "from"2320in a ref way, change it to use "to". There's a subtle reason why we2321renumber the ref uses and not the non-ref uses: non-ref uses may be23222 slots wide (double, long) which would necessitate keeping track of2323whether we should add one or two variables to the method. If the change2324affected the width of some instruction, returns "TRUE"; otherwise, returns "FALSE".2325Another reason for moving ref's value is for solving (addr, ref) conflicts, which2326both uses aload/astore methods.2327*/2328bool GenerateOopMap::rewrite_refval_conflict_inst(BytecodeStream *itr, int from, int to) {2329Bytecodes::Code bc = itr->code();2330int index;2331int bci = itr->bci();23322333if (is_aload(itr, &index) && index == from) {2334if (TraceOopMapRewrites) {2335tty->print_cr("Rewriting aload at bci: %d", bci);2336}2337return rewrite_load_or_store(itr, Bytecodes::_aload, Bytecodes::_aload_0, to);2338}23392340if (is_astore(itr, &index) && index == from) {2341if (!stack_top_holds_ret_addr(bci)) {2342if (TraceOopMapRewrites) {2343tty->print_cr("Rewriting astore at bci: %d", bci);2344}2345return rewrite_load_or_store(itr, Bytecodes::_astore, Bytecodes::_astore_0, to);2346} else {2347if (TraceOopMapRewrites) {2348tty->print_cr("Supress rewriting of astore at bci: %d", bci);2349}2350}2351}23522353return false;2354}23552356// The argument to this method is:2357// bc : Current bytecode2358// bcN : either _aload or _astore2359// bc0 : either _aload_0 or _astore_02360bool GenerateOopMap::rewrite_load_or_store(BytecodeStream *bcs, Bytecodes::Code bcN, Bytecodes::Code bc0, unsigned int varNo) {2361assert(bcN == Bytecodes::_astore || bcN == Bytecodes::_aload, "wrong argument (bcN)");2362assert(bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0, "wrong argument (bc0)");2363int ilen = Bytecodes::length_at(_method(), bcs->bcp());2364int newIlen;23652366if (ilen == 4) {2367// Original instruction was wide; keep it wide for simplicity2368newIlen = 4;2369} else if (varNo < 4)2370newIlen = 1;2371else if (varNo >= 256)2372newIlen = 4;2373else2374newIlen = 2;23752376// If we need to relocate in order to patch the byte, we2377// do the patching in a temp. buffer, that is passed to the reloc.2378// The patching of the bytecode stream is then done by the Relocator.2379// This is neccesary, since relocating the instruction at a certain bci, might2380// also relocate that instruction, e.g., if a _goto before it gets widen to a _goto_w.2381// Hence, we do not know which bci to patch after relocation.23822383assert(newIlen <= 4, "sanity check");2384u_char inst_buffer[4]; // Max. instruction size is 4.2385address bcp;23862387if (newIlen != ilen) {2388// Relocation needed do patching in temp. buffer2389bcp = (address)inst_buffer;2390} else {2391bcp = _method->bcp_from(bcs->bci());2392}23932394// Patch either directly in Method* or in temp. buffer2395if (newIlen == 1) {2396assert(varNo < 4, "varNo too large");2397*bcp = bc0 + varNo;2398} else if (newIlen == 2) {2399assert(varNo < 256, "2-byte index needed!");2400*(bcp + 0) = bcN;2401*(bcp + 1) = varNo;2402} else {2403assert(newIlen == 4, "Wrong instruction length");2404*(bcp + 0) = Bytecodes::_wide;2405*(bcp + 1) = bcN;2406Bytes::put_Java_u2(bcp+2, varNo);2407}24082409if (newIlen != ilen) {2410expand_current_instr(bcs->bci(), ilen, newIlen, inst_buffer);2411}241224132414return (newIlen != ilen);2415}24162417class RelocCallback : public RelocatorListener {2418private:2419GenerateOopMap* _gom;2420public:2421RelocCallback(GenerateOopMap* gom) { _gom = gom; };24222423// Callback method2424virtual void relocated(int bci, int delta, int new_code_length) {2425_gom->update_basic_blocks (bci, delta, new_code_length);2426_gom->update_ret_adr_at_TOS(bci, delta);2427_gom->_rt.update_ret_table (bci, delta);2428}2429};24302431// Returns true if expanding was succesful. Otherwise, reports an error and2432// returns false.2433void GenerateOopMap::expand_current_instr(int bci, int ilen, int newIlen, u_char inst_buffer[]) {2434JavaThread* THREAD = JavaThread::current(); // For exception macros.2435RelocCallback rcb(this);2436Relocator rc(_method, &rcb);2437methodHandle m= rc.insert_space_at(bci, newIlen, inst_buffer, THREAD);2438if (m.is_null() || HAS_PENDING_EXCEPTION) {2439report_error("could not rewrite method - exception occurred or bytecode buffer overflow");2440return;2441}24422443// Relocator returns a new method.2444_did_relocation = true;2445_method = m;2446}244724482449bool GenerateOopMap::is_astore(BytecodeStream *itr, int *index) {2450Bytecodes::Code bc = itr->code();2451switch(bc) {2452case Bytecodes::_astore_0:2453case Bytecodes::_astore_1:2454case Bytecodes::_astore_2:2455case Bytecodes::_astore_3:2456*index = bc - Bytecodes::_astore_0;2457return true;2458case Bytecodes::_astore:2459*index = itr->get_index();2460return true;2461default:2462return false;2463}2464}24652466bool GenerateOopMap::is_aload(BytecodeStream *itr, int *index) {2467Bytecodes::Code bc = itr->code();2468switch(bc) {2469case Bytecodes::_aload_0:2470case Bytecodes::_aload_1:2471case Bytecodes::_aload_2:2472case Bytecodes::_aload_3:2473*index = bc - Bytecodes::_aload_0;2474return true;24752476case Bytecodes::_aload:2477*index = itr->get_index();2478return true;24792480default:2481return false;2482}2483}248424852486// Return true iff the top of the operand stack holds a return address at2487// the current instruction2488bool GenerateOopMap::stack_top_holds_ret_addr(int bci) {2489for(int i = 0; i < _ret_adr_tos->length(); i++) {2490if (_ret_adr_tos->at(i) == bci)2491return true;2492}24932494return false;2495}24962497void GenerateOopMap::compute_ret_adr_at_TOS() {2498assert(_ret_adr_tos != NULL, "must be initialized");2499_ret_adr_tos->clear();25002501for (int i = 0; i < bb_count(); i++) {2502BasicBlock* bb = &_basic_blocks[i];25032504// Make sure to only check basicblocks that are reachable2505if (bb->is_reachable()) {25062507// For each Basic block we check all instructions2508BytecodeStream bcs(_method);2509bcs.set_interval(bb->_bci, next_bb_start_pc(bb));25102511restore_state(bb);25122513while (bcs.next()>=0 && !_got_error) {2514// TDT: should this be is_good_address() ?2515if (_stack_top > 0 && stack()[_stack_top-1].is_address()) {2516_ret_adr_tos->append(bcs.bci());2517if (TraceNewOopMapGeneration) {2518tty->print_cr("Ret_adr TOS at bci: %d", bcs.bci());2519}2520}2521interp1(&bcs);2522}2523}2524}2525}25262527void GenerateOopMap::update_ret_adr_at_TOS(int bci, int delta) {2528for(int i = 0; i < _ret_adr_tos->length(); i++) {2529int v = _ret_adr_tos->at(i);2530if (v > bci) _ret_adr_tos->at_put(i, v + delta);2531}2532}25332534// ===================================================================25352536#ifndef PRODUCT2537int ResolveOopMapConflicts::_nof_invocations = 0;2538int ResolveOopMapConflicts::_nof_rewrites = 0;2539int ResolveOopMapConflicts::_nof_relocations = 0;2540#endif25412542methodHandle ResolveOopMapConflicts::do_potential_rewrite(TRAPS) {2543if (!compute_map(THREAD)) {2544THROW_HANDLE_(exception(), methodHandle());2545}25462547#ifndef PRODUCT2548// Tracking and statistics2549if (PrintRewrites) {2550_nof_invocations++;2551if (did_rewriting()) {2552_nof_rewrites++;2553if (did_relocation()) _nof_relocations++;2554tty->print("Method was rewritten %s: ", (did_relocation()) ? "and relocated" : "");2555method()->print_value(); tty->cr();2556tty->print_cr("Cand.: %d rewrts: %d (%d%%) reloc.: %d (%d%%)",2557_nof_invocations,2558_nof_rewrites, (_nof_rewrites * 100) / _nof_invocations,2559_nof_relocations, (_nof_relocations * 100) / _nof_invocations);2560}2561}2562#endif2563return methodHandle(THREAD, method());2564}256525662567