Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp
32285 views
/*1* Copyright (c) 2005, 2014, 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 "ci/bcEscapeAnalyzer.hpp"26#include "ci/ciConstant.hpp"27#include "ci/ciField.hpp"28#include "ci/ciMethodBlocks.hpp"29#include "ci/ciStreams.hpp"30#include "interpreter/bytecode.hpp"31#include "utilities/bitMap.inline.hpp"32333435#ifndef PRODUCT36#define TRACE_BCEA(level, code) \37if (EstimateArgEscape && BCEATraceLevel >= level) { \38code; \39}40#else41#define TRACE_BCEA(level, code)42#endif4344// Maintain a map of which arguments a local variable or45// stack slot may contain. In addition to tracking46// arguments, it tracks two special values, "allocated"47// which represents any object allocated in the current48// method, and "unknown" which is any other object.49// Up to 30 arguments are handled, with the last one50// representing summary information for any extra arguments51class BCEscapeAnalyzer::ArgumentMap {52uint _bits;53enum {MAXBIT = 29,54ALLOCATED = 1,55UNKNOWN = 2};5657uint int_to_bit(uint e) const {58if (e > MAXBIT)59e = MAXBIT;60return (1 << (e + 2));61}6263public:64ArgumentMap() { _bits = 0;}65void set_bits(uint bits) { _bits = bits;}66uint get_bits() const { return _bits;}67void clear() { _bits = 0;}68void set_all() { _bits = ~0u; }69bool is_empty() const { return _bits == 0; }70bool contains(uint var) const { return (_bits & int_to_bit(var)) != 0; }71bool is_singleton(uint var) const { return (_bits == int_to_bit(var)); }72bool contains_unknown() const { return (_bits & UNKNOWN) != 0; }73bool contains_allocated() const { return (_bits & ALLOCATED) != 0; }74bool contains_vars() const { return (_bits & (((1 << MAXBIT) -1) << 2)) != 0; }75void set(uint var) { _bits = int_to_bit(var); }76void add(uint var) { _bits |= int_to_bit(var); }77void add_unknown() { _bits = UNKNOWN; }78void add_allocated() { _bits = ALLOCATED; }79void set_union(const ArgumentMap &am) { _bits |= am._bits; }80void set_intersect(const ArgumentMap &am) { _bits |= am._bits; }81void set_difference(const ArgumentMap &am) { _bits &= ~am._bits; }82void operator=(const ArgumentMap &am) { _bits = am._bits; }83bool operator==(const ArgumentMap &am) { return _bits == am._bits; }84bool operator!=(const ArgumentMap &am) { return _bits != am._bits; }85};8687class BCEscapeAnalyzer::StateInfo {88public:89ArgumentMap *_vars;90ArgumentMap *_stack;91int _stack_height;92int _max_stack;93bool _initialized;94ArgumentMap empty_map;9596StateInfo() {97empty_map.clear();98}99100ArgumentMap raw_pop() { guarantee(_stack_height > 0, "stack underflow"); return _stack[--_stack_height]; }101ArgumentMap apop() { return raw_pop(); }102void spop() { raw_pop(); }103void lpop() { spop(); spop(); }104void raw_push(ArgumentMap i) { guarantee(_stack_height < _max_stack, "stack overflow"); _stack[_stack_height++] = i; }105void apush(ArgumentMap i) { raw_push(i); }106void spush() { raw_push(empty_map); }107void lpush() { spush(); spush(); }108109};110111void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {112for (int i = 0; i < _arg_size; i++) {113if (vars.contains(i))114_arg_returned.set(i);115}116_return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated());117_return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());118}119120// return true if any element of vars is an argument121bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) {122for (int i = 0; i < _arg_size; i++) {123if (vars.contains(i))124return true;125}126return false;127}128129// return true if any element of vars is an arg_stack argument130bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){131if (_conservative)132return true;133for (int i = 0; i < _arg_size; i++) {134if (vars.contains(i) && _arg_stack.test(i))135return true;136}137return false;138}139140// return true if all argument elements of vars are returned141bool BCEscapeAnalyzer::returns_all(ArgumentMap vars) {142for (int i = 0; i < _arg_size; i++) {143if (vars.contains(i) && !_arg_returned.test(i)) {144return false;145}146}147return true;148}149150void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {151for (int i = 0; i < _arg_size; i++) {152if (vars.contains(i)) {153bm >>= i;154}155}156}157158void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) {159clear_bits(vars, _arg_local);160if (vars.contains_allocated()) {161_allocated_escapes = true;162}163}164165void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars, bool merge) {166clear_bits(vars, _arg_local);167clear_bits(vars, _arg_stack);168if (vars.contains_allocated())169_allocated_escapes = true;170171if (merge && !vars.is_empty()) {172// Merge new state into already processed block.173// New state is not taken into account and174// it may invalidate set_returned() result.175if (vars.contains_unknown() || vars.contains_allocated()) {176_return_local = false;177}178if (vars.contains_unknown() || vars.contains_vars()) {179_return_allocated = false;180}181if (_return_local && vars.contains_vars() && !returns_all(vars)) {182// Return result should be invalidated if args in new183// state are not recorded in return state.184_return_local = false;185}186}187}188189void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) {190clear_bits(vars, _dirty);191}192193void BCEscapeAnalyzer::set_modified(ArgumentMap vars, int offs, int size) {194195for (int i = 0; i < _arg_size; i++) {196if (vars.contains(i)) {197set_arg_modified(i, offs, size);198}199}200if (vars.contains_unknown())201_unknown_modified = true;202}203204bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) {205for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) {206if (scope->method() == callee) {207return true;208}209}210return false;211}212213bool BCEscapeAnalyzer::is_arg_modified(int arg, int offset, int size_in_bytes) {214if (offset == OFFSET_ANY)215return _arg_modified[arg] != 0;216assert(arg >= 0 && arg < _arg_size, "must be an argument.");217bool modified = false;218int l = offset / HeapWordSize;219int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;220if (l > ARG_OFFSET_MAX)221l = ARG_OFFSET_MAX;222if (h > ARG_OFFSET_MAX+1)223h = ARG_OFFSET_MAX + 1;224for (int i = l; i < h; i++) {225modified = modified || (_arg_modified[arg] & (1 << i)) != 0;226}227return modified;228}229230void BCEscapeAnalyzer::set_arg_modified(int arg, int offset, int size_in_bytes) {231if (offset == OFFSET_ANY) {232_arg_modified[arg] = (uint) -1;233return;234}235assert(arg >= 0 && arg < _arg_size, "must be an argument.");236int l = offset / HeapWordSize;237int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;238if (l > ARG_OFFSET_MAX)239l = ARG_OFFSET_MAX;240if (h > ARG_OFFSET_MAX+1)241h = ARG_OFFSET_MAX + 1;242for (int i = l; i < h; i++) {243_arg_modified[arg] |= (1 << i);244}245}246247void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) {248int i;249250// retrieve information about the callee251ciInstanceKlass* klass = target->holder();252ciInstanceKlass* calling_klass = method()->holder();253ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder);254ciInstanceKlass* actual_recv = callee_holder;255256// Some methods are obviously bindable without any type checks so257// convert them directly to an invokespecial or invokestatic.258if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) {259switch (code) {260case Bytecodes::_invokevirtual:261code = Bytecodes::_invokespecial;262break;263case Bytecodes::_invokehandle:264code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial;265break;266}267}268269// compute size of arguments270int arg_size = target->invoke_arg_size(code);271int arg_base = MAX2(state._stack_height - arg_size, 0);272273// direct recursive calls are skipped if they can be bound statically without introducing274// dependencies and if parameters are passed at the same position as in the current method275// other calls are skipped if there are no unescaped arguments passed to them276bool directly_recursive = (method() == target) &&277(code != Bytecodes::_invokevirtual || target->is_final_method() || state._stack[arg_base] .is_empty());278279// check if analysis of callee can safely be skipped280bool skip_callee = true;281for (i = state._stack_height - 1; i >= arg_base && skip_callee; i--) {282ArgumentMap arg = state._stack[i];283skip_callee = !is_argument(arg) || !is_arg_stack(arg) || (directly_recursive && arg.is_singleton(i - arg_base));284}285// For now we conservatively skip invokedynamic.286if (code == Bytecodes::_invokedynamic) {287skip_callee = true;288}289if (skip_callee) {290TRACE_BCEA(3, tty->print_cr("[EA] skipping method %s::%s", holder->name()->as_utf8(), target->name()->as_utf8()));291for (i = 0; i < arg_size; i++) {292set_method_escape(state.raw_pop());293}294_unknown_modified = true; // assume the worst since we don't analyze the called method295return;296}297298// determine actual method (use CHA if necessary)299ciMethod* inline_target = NULL;300if (target->is_loaded() && klass->is_loaded()301&& (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized())302&& target->is_loaded()) {303if (code == Bytecodes::_invokestatic304|| code == Bytecodes::_invokespecial305|| code == Bytecodes::_invokevirtual && target->is_final_method()) {306inline_target = target;307} else {308inline_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv);309}310}311312if (inline_target != NULL && !is_recursive_call(inline_target)) {313// analyze callee314BCEscapeAnalyzer analyzer(inline_target, this);315316// adjust escape state of actual parameters317bool must_record_dependencies = false;318for (i = arg_size - 1; i >= 0; i--) {319ArgumentMap arg = state.raw_pop();320// Check if callee arg is a caller arg or an allocated object321bool allocated = arg.contains_allocated();322if (!(is_argument(arg) || allocated))323continue;324for (int j = 0; j < _arg_size; j++) {325if (arg.contains(j)) {326_arg_modified[j] |= analyzer._arg_modified[i];327}328}329if (!(is_arg_stack(arg) || allocated)) {330// arguments have already been recognized as escaping331} else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) {332set_method_escape(arg);333must_record_dependencies = true;334} else {335set_global_escape(arg);336}337}338_unknown_modified = _unknown_modified || analyzer.has_non_arg_side_affects();339340// record dependencies if at least one parameter retained stack-allocatable341if (must_record_dependencies) {342if (code == Bytecodes::_invokeinterface || code == Bytecodes::_invokevirtual && !target->is_final_method()) {343_dependencies.append(actual_recv);344_dependencies.append(inline_target);345}346_dependencies.appendAll(analyzer.dependencies());347}348} else {349TRACE_BCEA(1, tty->print_cr("[EA] virtual method %s is not monomorphic.",350target->name()->as_utf8()));351// conservatively mark all actual parameters as escaping globally352for (i = 0; i < arg_size; i++) {353ArgumentMap arg = state.raw_pop();354if (!is_argument(arg))355continue;356set_modified(arg, OFFSET_ANY, type2size[T_INT]*HeapWordSize);357set_global_escape(arg);358}359_unknown_modified = true; // assume the worst since we don't know the called method360}361}362363bool BCEscapeAnalyzer::contains(uint arg_set1, uint arg_set2) {364return ((~arg_set1) | arg_set2) == 0;365}366367368void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, GrowableArray<ciBlock *> &successors) {369370blk->set_processed();371ciBytecodeStream s(method());372int limit_bci = blk->limit_bci();373bool fall_through = false;374ArgumentMap allocated_obj;375allocated_obj.add_allocated();376ArgumentMap unknown_obj;377unknown_obj.add_unknown();378ArgumentMap empty_map;379380s.reset_to_bci(blk->start_bci());381while (s.next() != ciBytecodeStream::EOBC() && s.cur_bci() < limit_bci) {382fall_through = true;383switch (s.cur_bc()) {384case Bytecodes::_nop:385break;386case Bytecodes::_aconst_null:387state.apush(unknown_obj);388break;389case Bytecodes::_iconst_m1:390case Bytecodes::_iconst_0:391case Bytecodes::_iconst_1:392case Bytecodes::_iconst_2:393case Bytecodes::_iconst_3:394case Bytecodes::_iconst_4:395case Bytecodes::_iconst_5:396case Bytecodes::_fconst_0:397case Bytecodes::_fconst_1:398case Bytecodes::_fconst_2:399case Bytecodes::_bipush:400case Bytecodes::_sipush:401state.spush();402break;403case Bytecodes::_lconst_0:404case Bytecodes::_lconst_1:405case Bytecodes::_dconst_0:406case Bytecodes::_dconst_1:407state.lpush();408break;409case Bytecodes::_ldc:410case Bytecodes::_ldc_w:411case Bytecodes::_ldc2_w:412{413// Avoid calling get_constant() which will try to allocate414// unloaded constant. We need only constant's type.415int index = s.get_constant_pool_index();416constantTag tag = s.get_constant_pool_tag(index);417if (tag.is_long() || tag.is_double()) {418// Only longs and doubles use 2 stack slots.419state.lpush();420} else if (tag.basic_type() == T_OBJECT) {421state.apush(unknown_obj);422} else {423state.spush();424}425break;426}427case Bytecodes::_aload:428state.apush(state._vars[s.get_index()]);429break;430case Bytecodes::_iload:431case Bytecodes::_fload:432case Bytecodes::_iload_0:433case Bytecodes::_iload_1:434case Bytecodes::_iload_2:435case Bytecodes::_iload_3:436case Bytecodes::_fload_0:437case Bytecodes::_fload_1:438case Bytecodes::_fload_2:439case Bytecodes::_fload_3:440state.spush();441break;442case Bytecodes::_lload:443case Bytecodes::_dload:444case Bytecodes::_lload_0:445case Bytecodes::_lload_1:446case Bytecodes::_lload_2:447case Bytecodes::_lload_3:448case Bytecodes::_dload_0:449case Bytecodes::_dload_1:450case Bytecodes::_dload_2:451case Bytecodes::_dload_3:452state.lpush();453break;454case Bytecodes::_aload_0:455state.apush(state._vars[0]);456break;457case Bytecodes::_aload_1:458state.apush(state._vars[1]);459break;460case Bytecodes::_aload_2:461state.apush(state._vars[2]);462break;463case Bytecodes::_aload_3:464state.apush(state._vars[3]);465break;466case Bytecodes::_iaload:467case Bytecodes::_faload:468case Bytecodes::_baload:469case Bytecodes::_caload:470case Bytecodes::_saload:471state.spop();472set_method_escape(state.apop());473state.spush();474break;475case Bytecodes::_laload:476case Bytecodes::_daload:477state.spop();478set_method_escape(state.apop());479state.lpush();480break;481case Bytecodes::_aaload:482{ state.spop();483ArgumentMap array = state.apop();484set_method_escape(array);485state.apush(unknown_obj);486set_dirty(array);487}488break;489case Bytecodes::_istore:490case Bytecodes::_fstore:491case Bytecodes::_istore_0:492case Bytecodes::_istore_1:493case Bytecodes::_istore_2:494case Bytecodes::_istore_3:495case Bytecodes::_fstore_0:496case Bytecodes::_fstore_1:497case Bytecodes::_fstore_2:498case Bytecodes::_fstore_3:499state.spop();500break;501case Bytecodes::_lstore:502case Bytecodes::_dstore:503case Bytecodes::_lstore_0:504case Bytecodes::_lstore_1:505case Bytecodes::_lstore_2:506case Bytecodes::_lstore_3:507case Bytecodes::_dstore_0:508case Bytecodes::_dstore_1:509case Bytecodes::_dstore_2:510case Bytecodes::_dstore_3:511state.lpop();512break;513case Bytecodes::_astore:514state._vars[s.get_index()] = state.apop();515break;516case Bytecodes::_astore_0:517state._vars[0] = state.apop();518break;519case Bytecodes::_astore_1:520state._vars[1] = state.apop();521break;522case Bytecodes::_astore_2:523state._vars[2] = state.apop();524break;525case Bytecodes::_astore_3:526state._vars[3] = state.apop();527break;528case Bytecodes::_iastore:529case Bytecodes::_fastore:530case Bytecodes::_bastore:531case Bytecodes::_castore:532case Bytecodes::_sastore:533{534state.spop();535state.spop();536ArgumentMap arr = state.apop();537set_method_escape(arr);538set_modified(arr, OFFSET_ANY, type2size[T_INT]*HeapWordSize);539break;540}541case Bytecodes::_lastore:542case Bytecodes::_dastore:543{544state.lpop();545state.spop();546ArgumentMap arr = state.apop();547set_method_escape(arr);548set_modified(arr, OFFSET_ANY, type2size[T_LONG]*HeapWordSize);549break;550}551case Bytecodes::_aastore:552{553set_global_escape(state.apop());554state.spop();555ArgumentMap arr = state.apop();556set_modified(arr, OFFSET_ANY, type2size[T_OBJECT]*HeapWordSize);557break;558}559case Bytecodes::_pop:560state.raw_pop();561break;562case Bytecodes::_pop2:563state.raw_pop();564state.raw_pop();565break;566case Bytecodes::_dup:567{ ArgumentMap w1 = state.raw_pop();568state.raw_push(w1);569state.raw_push(w1);570}571break;572case Bytecodes::_dup_x1:573{ ArgumentMap w1 = state.raw_pop();574ArgumentMap w2 = state.raw_pop();575state.raw_push(w1);576state.raw_push(w2);577state.raw_push(w1);578}579break;580case Bytecodes::_dup_x2:581{ ArgumentMap w1 = state.raw_pop();582ArgumentMap w2 = state.raw_pop();583ArgumentMap w3 = state.raw_pop();584state.raw_push(w1);585state.raw_push(w3);586state.raw_push(w2);587state.raw_push(w1);588}589break;590case Bytecodes::_dup2:591{ ArgumentMap w1 = state.raw_pop();592ArgumentMap w2 = state.raw_pop();593state.raw_push(w2);594state.raw_push(w1);595state.raw_push(w2);596state.raw_push(w1);597}598break;599case Bytecodes::_dup2_x1:600{ ArgumentMap w1 = state.raw_pop();601ArgumentMap w2 = state.raw_pop();602ArgumentMap w3 = state.raw_pop();603state.raw_push(w2);604state.raw_push(w1);605state.raw_push(w3);606state.raw_push(w2);607state.raw_push(w1);608}609break;610case Bytecodes::_dup2_x2:611{ ArgumentMap w1 = state.raw_pop();612ArgumentMap w2 = state.raw_pop();613ArgumentMap w3 = state.raw_pop();614ArgumentMap w4 = state.raw_pop();615state.raw_push(w2);616state.raw_push(w1);617state.raw_push(w4);618state.raw_push(w3);619state.raw_push(w2);620state.raw_push(w1);621}622break;623case Bytecodes::_swap:624{ ArgumentMap w1 = state.raw_pop();625ArgumentMap w2 = state.raw_pop();626state.raw_push(w1);627state.raw_push(w2);628}629break;630case Bytecodes::_iadd:631case Bytecodes::_fadd:632case Bytecodes::_isub:633case Bytecodes::_fsub:634case Bytecodes::_imul:635case Bytecodes::_fmul:636case Bytecodes::_idiv:637case Bytecodes::_fdiv:638case Bytecodes::_irem:639case Bytecodes::_frem:640case Bytecodes::_iand:641case Bytecodes::_ior:642case Bytecodes::_ixor:643state.spop();644state.spop();645state.spush();646break;647case Bytecodes::_ladd:648case Bytecodes::_dadd:649case Bytecodes::_lsub:650case Bytecodes::_dsub:651case Bytecodes::_lmul:652case Bytecodes::_dmul:653case Bytecodes::_ldiv:654case Bytecodes::_ddiv:655case Bytecodes::_lrem:656case Bytecodes::_drem:657case Bytecodes::_land:658case Bytecodes::_lor:659case Bytecodes::_lxor:660state.lpop();661state.lpop();662state.lpush();663break;664case Bytecodes::_ishl:665case Bytecodes::_ishr:666case Bytecodes::_iushr:667state.spop();668state.spop();669state.spush();670break;671case Bytecodes::_lshl:672case Bytecodes::_lshr:673case Bytecodes::_lushr:674state.spop();675state.lpop();676state.lpush();677break;678case Bytecodes::_ineg:679case Bytecodes::_fneg:680state.spop();681state.spush();682break;683case Bytecodes::_lneg:684case Bytecodes::_dneg:685state.lpop();686state.lpush();687break;688case Bytecodes::_iinc:689break;690case Bytecodes::_i2l:691case Bytecodes::_i2d:692case Bytecodes::_f2l:693case Bytecodes::_f2d:694state.spop();695state.lpush();696break;697case Bytecodes::_i2f:698case Bytecodes::_f2i:699state.spop();700state.spush();701break;702case Bytecodes::_l2i:703case Bytecodes::_l2f:704case Bytecodes::_d2i:705case Bytecodes::_d2f:706state.lpop();707state.spush();708break;709case Bytecodes::_l2d:710case Bytecodes::_d2l:711state.lpop();712state.lpush();713break;714case Bytecodes::_i2b:715case Bytecodes::_i2c:716case Bytecodes::_i2s:717state.spop();718state.spush();719break;720case Bytecodes::_lcmp:721case Bytecodes::_dcmpl:722case Bytecodes::_dcmpg:723state.lpop();724state.lpop();725state.spush();726break;727case Bytecodes::_fcmpl:728case Bytecodes::_fcmpg:729state.spop();730state.spop();731state.spush();732break;733case Bytecodes::_ifeq:734case Bytecodes::_ifne:735case Bytecodes::_iflt:736case Bytecodes::_ifge:737case Bytecodes::_ifgt:738case Bytecodes::_ifle:739{740state.spop();741int dest_bci = s.get_dest();742assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");743assert(s.next_bci() == limit_bci, "branch must end block");744successors.push(_methodBlocks->block_containing(dest_bci));745break;746}747case Bytecodes::_if_icmpeq:748case Bytecodes::_if_icmpne:749case Bytecodes::_if_icmplt:750case Bytecodes::_if_icmpge:751case Bytecodes::_if_icmpgt:752case Bytecodes::_if_icmple:753{754state.spop();755state.spop();756int dest_bci = s.get_dest();757assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");758assert(s.next_bci() == limit_bci, "branch must end block");759successors.push(_methodBlocks->block_containing(dest_bci));760break;761}762case Bytecodes::_if_acmpeq:763case Bytecodes::_if_acmpne:764{765set_method_escape(state.apop());766set_method_escape(state.apop());767int dest_bci = s.get_dest();768assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");769assert(s.next_bci() == limit_bci, "branch must end block");770successors.push(_methodBlocks->block_containing(dest_bci));771break;772}773case Bytecodes::_goto:774{775int dest_bci = s.get_dest();776assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");777assert(s.next_bci() == limit_bci, "branch must end block");778successors.push(_methodBlocks->block_containing(dest_bci));779fall_through = false;780break;781}782case Bytecodes::_jsr:783{784int dest_bci = s.get_dest();785assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");786assert(s.next_bci() == limit_bci, "branch must end block");787state.apush(empty_map);788successors.push(_methodBlocks->block_containing(dest_bci));789fall_through = false;790break;791}792case Bytecodes::_ret:793// we don't track the destination of a "ret" instruction794assert(s.next_bci() == limit_bci, "branch must end block");795fall_through = false;796break;797case Bytecodes::_return:798assert(s.next_bci() == limit_bci, "return must end block");799fall_through = false;800break;801case Bytecodes::_tableswitch:802{803state.spop();804Bytecode_tableswitch sw(&s);805int len = sw.length();806int dest_bci;807for (int i = 0; i < len; i++) {808dest_bci = s.cur_bci() + sw.dest_offset_at(i);809assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");810successors.push(_methodBlocks->block_containing(dest_bci));811}812dest_bci = s.cur_bci() + sw.default_offset();813assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");814successors.push(_methodBlocks->block_containing(dest_bci));815assert(s.next_bci() == limit_bci, "branch must end block");816fall_through = false;817break;818}819case Bytecodes::_lookupswitch:820{821state.spop();822Bytecode_lookupswitch sw(&s);823int len = sw.number_of_pairs();824int dest_bci;825for (int i = 0; i < len; i++) {826dest_bci = s.cur_bci() + sw.pair_at(i).offset();827assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");828successors.push(_methodBlocks->block_containing(dest_bci));829}830dest_bci = s.cur_bci() + sw.default_offset();831assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");832successors.push(_methodBlocks->block_containing(dest_bci));833fall_through = false;834break;835}836case Bytecodes::_ireturn:837case Bytecodes::_freturn:838state.spop();839fall_through = false;840break;841case Bytecodes::_lreturn:842case Bytecodes::_dreturn:843state.lpop();844fall_through = false;845break;846case Bytecodes::_areturn:847set_returned(state.apop());848fall_through = false;849break;850case Bytecodes::_getstatic:851case Bytecodes::_getfield:852{ bool ignored_will_link;853ciField* field = s.get_field(ignored_will_link);854BasicType field_type = field->type()->basic_type();855if (s.cur_bc() != Bytecodes::_getstatic) {856set_method_escape(state.apop());857}858if (field_type == T_OBJECT || field_type == T_ARRAY) {859state.apush(unknown_obj);860} else if (type2size[field_type] == 1) {861state.spush();862} else {863state.lpush();864}865}866break;867case Bytecodes::_putstatic:868case Bytecodes::_putfield:869{ bool will_link;870ciField* field = s.get_field(will_link);871BasicType field_type = field->type()->basic_type();872if (field_type == T_OBJECT || field_type == T_ARRAY) {873set_global_escape(state.apop());874} else if (type2size[field_type] == 1) {875state.spop();876} else {877state.lpop();878}879if (s.cur_bc() != Bytecodes::_putstatic) {880ArgumentMap p = state.apop();881set_method_escape(p);882set_modified(p, will_link ? field->offset() : OFFSET_ANY, type2size[field_type]*HeapWordSize);883}884}885break;886case Bytecodes::_invokevirtual:887case Bytecodes::_invokespecial:888case Bytecodes::_invokestatic:889case Bytecodes::_invokedynamic:890case Bytecodes::_invokeinterface:891{ bool ignored_will_link;892ciSignature* declared_signature = NULL;893ciMethod* target = s.get_method(ignored_will_link, &declared_signature);894ciKlass* holder = s.get_declared_method_holder();895assert(declared_signature != NULL, "cannot be null");896// Push appendix argument, if one.897if (s.has_appendix()) {898state.apush(unknown_obj);899}900// Pass in raw bytecode because we need to see invokehandle instructions.901invoke(state, s.cur_bc_raw(), target, holder);902// We are using the return type of the declared signature here because903// it might be a more concrete type than the one from the target (for904// e.g. invokedynamic and invokehandle).905ciType* return_type = declared_signature->return_type();906if (!return_type->is_primitive_type()) {907state.apush(unknown_obj);908} else if (return_type->is_one_word()) {909state.spush();910} else if (return_type->is_two_word()) {911state.lpush();912}913}914break;915case Bytecodes::_new:916state.apush(allocated_obj);917break;918case Bytecodes::_newarray:919case Bytecodes::_anewarray:920state.spop();921state.apush(allocated_obj);922break;923case Bytecodes::_multianewarray:924{ int i = s.cur_bcp()[3];925while (i-- > 0) state.spop();926state.apush(allocated_obj);927}928break;929case Bytecodes::_arraylength:930set_method_escape(state.apop());931state.spush();932break;933case Bytecodes::_athrow:934set_global_escape(state.apop());935fall_through = false;936break;937case Bytecodes::_checkcast:938{ ArgumentMap obj = state.apop();939set_method_escape(obj);940state.apush(obj);941}942break;943case Bytecodes::_instanceof:944set_method_escape(state.apop());945state.spush();946break;947case Bytecodes::_monitorenter:948case Bytecodes::_monitorexit:949state.apop();950break;951case Bytecodes::_wide:952ShouldNotReachHere();953break;954case Bytecodes::_ifnull:955case Bytecodes::_ifnonnull:956{957set_method_escape(state.apop());958int dest_bci = s.get_dest();959assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");960assert(s.next_bci() == limit_bci, "branch must end block");961successors.push(_methodBlocks->block_containing(dest_bci));962break;963}964case Bytecodes::_goto_w:965{966int dest_bci = s.get_far_dest();967assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");968assert(s.next_bci() == limit_bci, "branch must end block");969successors.push(_methodBlocks->block_containing(dest_bci));970fall_through = false;971break;972}973case Bytecodes::_jsr_w:974{975int dest_bci = s.get_far_dest();976assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");977assert(s.next_bci() == limit_bci, "branch must end block");978state.apush(empty_map);979successors.push(_methodBlocks->block_containing(dest_bci));980fall_through = false;981break;982}983case Bytecodes::_breakpoint:984break;985default:986ShouldNotReachHere();987break;988}989990}991if (fall_through) {992int fall_through_bci = s.cur_bci();993if (fall_through_bci < _method->code_size()) {994assert(_methodBlocks->is_block_start(fall_through_bci), "must fall through to block start.");995successors.push(_methodBlocks->block_containing(fall_through_bci));996}997}998}9991000void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) {1001StateInfo *d_state = blockstates + dest->index();1002int nlocals = _method->max_locals();10031004// exceptions may cause transfer of control to handlers in the middle of a1005// block, so we don't merge the incoming state of exception handlers1006if (dest->is_handler())1007return;1008if (!d_state->_initialized ) {1009// destination not initialized, just copy1010for (int i = 0; i < nlocals; i++) {1011d_state->_vars[i] = s_state->_vars[i];1012}1013for (int i = 0; i < s_state->_stack_height; i++) {1014d_state->_stack[i] = s_state->_stack[i];1015}1016d_state->_stack_height = s_state->_stack_height;1017d_state->_max_stack = s_state->_max_stack;1018d_state->_initialized = true;1019} else if (!dest->processed()) {1020// we have not yet walked the bytecodes of dest, we can merge1021// the states1022assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match");1023for (int i = 0; i < nlocals; i++) {1024d_state->_vars[i].set_union(s_state->_vars[i]);1025}1026for (int i = 0; i < s_state->_stack_height; i++) {1027d_state->_stack[i].set_union(s_state->_stack[i]);1028}1029} else {1030// the bytecodes of dest have already been processed, mark any1031// arguments in the source state which are not in the dest state1032// as global escape.1033// Future refinement: we only need to mark these variable to the1034// maximum escape of any variables in dest state1035assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match");1036ArgumentMap extra_vars;1037for (int i = 0; i < nlocals; i++) {1038ArgumentMap t;1039t = s_state->_vars[i];1040t.set_difference(d_state->_vars[i]);1041extra_vars.set_union(t);1042}1043for (int i = 0; i < s_state->_stack_height; i++) {1044ArgumentMap t;1045//extra_vars |= !d_state->_vars[i] & s_state->_vars[i];1046t.clear();1047t = s_state->_stack[i];1048t.set_difference(d_state->_stack[i]);1049extra_vars.set_union(t);1050}1051set_global_escape(extra_vars, true);1052}1053}10541055void BCEscapeAnalyzer::iterate_blocks(Arena *arena) {1056int numblocks = _methodBlocks->num_blocks();1057int stkSize = _method->max_stack();1058int numLocals = _method->max_locals();1059StateInfo state;10601061int datacount = (numblocks + 1) * (stkSize + numLocals);1062int datasize = datacount * sizeof(ArgumentMap);1063StateInfo *blockstates = (StateInfo *) arena->Amalloc(numblocks * sizeof(StateInfo));1064ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize);1065for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap();1066ArgumentMap *dp = statedata;1067state._vars = dp;1068dp += numLocals;1069state._stack = dp;1070dp += stkSize;1071state._initialized = false;1072state._max_stack = stkSize;1073for (int i = 0; i < numblocks; i++) {1074blockstates[i]._vars = dp;1075dp += numLocals;1076blockstates[i]._stack = dp;1077dp += stkSize;1078blockstates[i]._initialized = false;1079blockstates[i]._stack_height = 0;1080blockstates[i]._max_stack = stkSize;1081}1082GrowableArray<ciBlock *> worklist(arena, numblocks / 4, 0, NULL);1083GrowableArray<ciBlock *> successors(arena, 4, 0, NULL);10841085_methodBlocks->clear_processed();10861087// initialize block 0 state from method signature1088ArgumentMap allVars; // all oop arguments to method1089ciSignature* sig = method()->signature();1090int j = 0;1091ciBlock* first_blk = _methodBlocks->block_containing(0);1092int fb_i = first_blk->index();1093if (!method()->is_static()) {1094// record information for "this"1095blockstates[fb_i]._vars[j].set(j);1096allVars.add(j);1097j++;1098}1099for (int i = 0; i < sig->count(); i++) {1100ciType* t = sig->type_at(i);1101if (!t->is_primitive_type()) {1102blockstates[fb_i]._vars[j].set(j);1103allVars.add(j);1104}1105j += t->size();1106}1107blockstates[fb_i]._initialized = true;1108assert(j == _arg_size, "just checking");11091110ArgumentMap unknown_map;1111unknown_map.add_unknown();11121113worklist.push(first_blk);1114while(worklist.length() > 0) {1115ciBlock *blk = worklist.pop();1116StateInfo *blkState = blockstates + blk->index();1117if (blk->is_handler() || blk->is_ret_target()) {1118// for an exception handler or a target of a ret instruction, we assume the worst case,1119// that any variable could contain any argument1120for (int i = 0; i < numLocals; i++) {1121state._vars[i] = allVars;1122}1123if (blk->is_handler()) {1124state._stack_height = 1;1125} else {1126state._stack_height = blkState->_stack_height;1127}1128for (int i = 0; i < state._stack_height; i++) {1129// ??? should this be unknown_map ???1130state._stack[i] = allVars;1131}1132} else {1133for (int i = 0; i < numLocals; i++) {1134state._vars[i] = blkState->_vars[i];1135}1136for (int i = 0; i < blkState->_stack_height; i++) {1137state._stack[i] = blkState->_stack[i];1138}1139state._stack_height = blkState->_stack_height;1140}1141iterate_one_block(blk, state, successors);1142// if this block has any exception handlers, push them1143// onto successor list1144if (blk->has_handler()) {1145DEBUG_ONLY(int handler_count = 0;)1146int blk_start = blk->start_bci();1147int blk_end = blk->limit_bci();1148for (int i = 0; i < numblocks; i++) {1149ciBlock *b = _methodBlocks->block(i);1150if (b->is_handler()) {1151int ex_start = b->ex_start_bci();1152int ex_end = b->ex_limit_bci();1153if ((ex_start >= blk_start && ex_start < blk_end) ||1154(ex_end > blk_start && ex_end <= blk_end)) {1155successors.push(b);1156}1157DEBUG_ONLY(handler_count++;)1158}1159}1160assert(handler_count > 0, "must find at least one handler");1161}1162// merge computed variable state with successors1163while(successors.length() > 0) {1164ciBlock *succ = successors.pop();1165merge_block_states(blockstates, succ, &state);1166if (!succ->processed())1167worklist.push(succ);1168}1169}1170}11711172void BCEscapeAnalyzer::do_analysis() {1173Arena* arena = CURRENT_ENV->arena();1174// identify basic blocks1175_methodBlocks = _method->get_method_blocks();11761177iterate_blocks(arena);1178}11791180vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {1181vmIntrinsics::ID iid = method()->intrinsic_id();1182if (iid == vmIntrinsics::_getClass ||1183iid == vmIntrinsics::_fillInStackTrace ||1184iid == vmIntrinsics::_hashCode) {1185return iid;1186} else {1187return vmIntrinsics::_none;1188}1189}11901191void BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {1192ArgumentMap arg;1193arg.clear();1194switch (iid) {1195case vmIntrinsics::_getClass:1196_return_local = false;1197_return_allocated = false;1198break;1199case vmIntrinsics::_fillInStackTrace:1200arg.set(0); // 'this'1201set_returned(arg);1202break;1203case vmIntrinsics::_hashCode:1204// initialized state is correct1205break;1206default:1207assert(false, "unexpected intrinsic");1208}1209}12101211void BCEscapeAnalyzer::initialize() {1212int i;12131214// clear escape information (method may have been deoptimized)1215methodData()->clear_escape_info();12161217// initialize escape state of object parameters1218ciSignature* sig = method()->signature();1219int j = 0;1220if (!method()->is_static()) {1221_arg_local.set(0);1222_arg_stack.set(0);1223j++;1224}1225for (i = 0; i < sig->count(); i++) {1226ciType* t = sig->type_at(i);1227if (!t->is_primitive_type()) {1228_arg_local.set(j);1229_arg_stack.set(j);1230}1231j += t->size();1232}1233assert(j == _arg_size, "just checking");12341235// start with optimistic assumption1236ciType *rt = _method->return_type();1237if (rt->is_primitive_type()) {1238_return_local = false;1239_return_allocated = false;1240} else {1241_return_local = true;1242_return_allocated = true;1243}1244_allocated_escapes = false;1245_unknown_modified = false;1246}12471248void BCEscapeAnalyzer::clear_escape_info() {1249ciSignature* sig = method()->signature();1250int arg_count = sig->count();1251ArgumentMap var;1252if (!method()->is_static()) {1253arg_count++; // allow for "this"1254}1255for (int i = 0; i < arg_count; i++) {1256set_arg_modified(i, OFFSET_ANY, 4);1257var.clear();1258var.set(i);1259set_modified(var, OFFSET_ANY, 4);1260set_global_escape(var);1261}1262_arg_local.Clear();1263_arg_stack.Clear();1264_arg_returned.Clear();1265_return_local = false;1266_return_allocated = false;1267_allocated_escapes = true;1268_unknown_modified = true;1269}127012711272void BCEscapeAnalyzer::compute_escape_info() {1273int i;1274assert(!methodData()->has_escape_info(), "do not overwrite escape info");12751276vmIntrinsics::ID iid = known_intrinsic();12771278// check if method can be analyzed1279if (iid == vmIntrinsics::_none && (method()->is_abstract() || method()->is_native() || !method()->holder()->is_initialized()1280|| _level > MaxBCEAEstimateLevel1281|| method()->code_size() > MaxBCEAEstimateSize)) {1282if (BCEATraceLevel >= 1) {1283tty->print("Skipping method because: ");1284if (method()->is_abstract())1285tty->print_cr("method is abstract.");1286else if (method()->is_native())1287tty->print_cr("method is native.");1288else if (!method()->holder()->is_initialized())1289tty->print_cr("class of method is not initialized.");1290else if (_level > MaxBCEAEstimateLevel)1291tty->print_cr("level (%d) exceeds MaxBCEAEstimateLevel (%d).",1292_level, (int) MaxBCEAEstimateLevel);1293else if (method()->code_size() > MaxBCEAEstimateSize)1294tty->print_cr("code size (%d) exceeds MaxBCEAEstimateSize (%d).",1295method()->code_size(), (int) MaxBCEAEstimateSize);1296else1297ShouldNotReachHere();1298}1299clear_escape_info();13001301return;1302}13031304if (BCEATraceLevel >= 1) {1305tty->print("[EA] estimating escape information for");1306if (iid != vmIntrinsics::_none)1307tty->print(" intrinsic");1308method()->print_short_name();1309tty->print_cr(" (%d bytes)", method()->code_size());1310}13111312initialize();13131314// Do not scan method if it has no object parameters and1315// does not returns an object (_return_allocated is set in initialize()).1316if (_arg_local.Size() == 0 && !_return_allocated) {1317// Clear all info since method's bytecode was not analysed and1318// set pessimistic escape information.1319clear_escape_info();1320methodData()->set_eflag(MethodData::allocated_escapes);1321methodData()->set_eflag(MethodData::unknown_modified);1322methodData()->set_eflag(MethodData::estimated);1323return;1324}13251326if (iid != vmIntrinsics::_none)1327compute_escape_for_intrinsic(iid);1328else {1329do_analysis();1330}13311332// don't store interprocedural escape information if it introduces1333// dependencies or if method data is empty1334//1335if (!has_dependencies() && !methodData()->is_empty()) {1336for (i = 0; i < _arg_size; i++) {1337if (_arg_local.test(i)) {1338assert(_arg_stack.test(i), "inconsistent escape info");1339methodData()->set_arg_local(i);1340methodData()->set_arg_stack(i);1341} else if (_arg_stack.test(i)) {1342methodData()->set_arg_stack(i);1343}1344if (_arg_returned.test(i)) {1345methodData()->set_arg_returned(i);1346}1347methodData()->set_arg_modified(i, _arg_modified[i]);1348}1349if (_return_local) {1350methodData()->set_eflag(MethodData::return_local);1351}1352if (_return_allocated) {1353methodData()->set_eflag(MethodData::return_allocated);1354}1355if (_allocated_escapes) {1356methodData()->set_eflag(MethodData::allocated_escapes);1357}1358if (_unknown_modified) {1359methodData()->set_eflag(MethodData::unknown_modified);1360}1361methodData()->set_eflag(MethodData::estimated);1362}1363}13641365void BCEscapeAnalyzer::read_escape_info() {1366assert(methodData()->has_escape_info(), "no escape info available");13671368// read escape information from method descriptor1369for (int i = 0; i < _arg_size; i++) {1370if (methodData()->is_arg_local(i))1371_arg_local.set(i);1372if (methodData()->is_arg_stack(i))1373_arg_stack.set(i);1374if (methodData()->is_arg_returned(i))1375_arg_returned.set(i);1376_arg_modified[i] = methodData()->arg_modified(i);1377}1378_return_local = methodData()->eflag_set(MethodData::return_local);1379_return_allocated = methodData()->eflag_set(MethodData::return_allocated);1380_allocated_escapes = methodData()->eflag_set(MethodData::allocated_escapes);1381_unknown_modified = methodData()->eflag_set(MethodData::unknown_modified);13821383}13841385#ifndef PRODUCT1386void BCEscapeAnalyzer::dump() {1387tty->print("[EA] estimated escape information for");1388method()->print_short_name();1389tty->print_cr(has_dependencies() ? " (not stored)" : "");1390tty->print(" non-escaping args: ");1391_arg_local.print_on(tty);1392tty->print(" stack-allocatable args: ");1393_arg_stack.print_on(tty);1394if (_return_local) {1395tty->print(" returned args: ");1396_arg_returned.print_on(tty);1397} else if (is_return_allocated()) {1398tty->print_cr(" return allocated value");1399} else {1400tty->print_cr(" return non-local value");1401}1402tty->print(" modified args: ");1403for (int i = 0; i < _arg_size; i++) {1404if (_arg_modified[i] == 0)1405tty->print(" 0");1406else1407tty->print(" 0x%x", _arg_modified[i]);1408}1409tty->cr();1410tty->print(" flags: ");1411if (_return_allocated)1412tty->print(" return_allocated");1413if (_allocated_escapes)1414tty->print(" allocated_escapes");1415if (_unknown_modified)1416tty->print(" unknown_modified");1417tty->cr();1418}1419#endif14201421BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)1422: _conservative(method == NULL || !EstimateArgEscape)1423, _arena(CURRENT_ENV->arena())1424, _method(method)1425, _methodData(method ? method->method_data() : NULL)1426, _arg_size(method ? method->arg_size() : 0)1427, _arg_local(_arena)1428, _arg_stack(_arena)1429, _arg_returned(_arena)1430, _dirty(_arena)1431, _return_local(false)1432, _return_allocated(false)1433, _allocated_escapes(false)1434, _unknown_modified(false)1435, _dependencies(_arena, 4, 0, NULL)1436, _parent(parent)1437, _level(parent == NULL ? 0 : parent->level() + 1) {1438if (!_conservative) {1439_arg_local.Clear();1440_arg_stack.Clear();1441_arg_returned.Clear();1442_dirty.Clear();1443Arena* arena = CURRENT_ENV->arena();1444_arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));1445Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));14461447if (methodData() == NULL)1448return;1449bool printit = _method->should_print_assembly();1450if (methodData()->has_escape_info()) {1451TRACE_BCEA(2, tty->print_cr("[EA] Reading previous results for %s.%s",1452method->holder()->name()->as_utf8(),1453method->name()->as_utf8()));1454read_escape_info();1455} else {1456TRACE_BCEA(2, tty->print_cr("[EA] computing results for %s.%s",1457method->holder()->name()->as_utf8(),1458method->name()->as_utf8()));14591460compute_escape_info();1461methodData()->update_escape_info();1462}1463#ifndef PRODUCT1464if (BCEATraceLevel >= 3) {1465// dump escape information1466dump();1467}1468#endif1469}1470}14711472void BCEscapeAnalyzer::copy_dependencies(Dependencies *deps) {1473if (ciEnv::current()->jvmti_can_hotswap_or_post_breakpoint()) {1474// Also record evol dependencies so redefinition of the1475// callee will trigger recompilation.1476deps->assert_evol_method(method());1477}1478for (int i = 0; i < _dependencies.length(); i+=2) {1479ciKlass *k = _dependencies.at(i)->as_klass();1480ciMethod *m = _dependencies.at(i+1)->as_method();1481deps->assert_unique_concrete_method(k, m);1482}1483}148414851486