1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,1486 @@ 1.4 +/* 1.5 + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "ci/bcEscapeAnalyzer.hpp" 1.30 +#include "ci/ciConstant.hpp" 1.31 +#include "ci/ciField.hpp" 1.32 +#include "ci/ciMethodBlocks.hpp" 1.33 +#include "ci/ciStreams.hpp" 1.34 +#include "interpreter/bytecode.hpp" 1.35 +#include "utilities/bitMap.inline.hpp" 1.36 + 1.37 + 1.38 + 1.39 +#ifndef PRODUCT 1.40 + #define TRACE_BCEA(level, code) \ 1.41 + if (EstimateArgEscape && BCEATraceLevel >= level) { \ 1.42 + code; \ 1.43 + } 1.44 +#else 1.45 + #define TRACE_BCEA(level, code) 1.46 +#endif 1.47 + 1.48 +// Maintain a map of which aguments a local variable or 1.49 +// stack slot may contain. In addition to tracking 1.50 +// arguments, it tracks two special values, "allocated" 1.51 +// which represents any object allocated in the current 1.52 +// method, and "unknown" which is any other object. 1.53 +// Up to 30 arguments are handled, with the last one 1.54 +// representing summary information for any extra arguments 1.55 +class BCEscapeAnalyzer::ArgumentMap { 1.56 + uint _bits; 1.57 + enum {MAXBIT = 29, 1.58 + ALLOCATED = 1, 1.59 + UNKNOWN = 2}; 1.60 + 1.61 + uint int_to_bit(uint e) const { 1.62 + if (e > MAXBIT) 1.63 + e = MAXBIT; 1.64 + return (1 << (e + 2)); 1.65 + } 1.66 + 1.67 +public: 1.68 + ArgumentMap() { _bits = 0;} 1.69 + void set_bits(uint bits) { _bits = bits;} 1.70 + uint get_bits() const { return _bits;} 1.71 + void clear() { _bits = 0;} 1.72 + void set_all() { _bits = ~0u; } 1.73 + bool is_empty() const { return _bits == 0; } 1.74 + bool contains(uint var) const { return (_bits & int_to_bit(var)) != 0; } 1.75 + bool is_singleton(uint var) const { return (_bits == int_to_bit(var)); } 1.76 + bool contains_unknown() const { return (_bits & UNKNOWN) != 0; } 1.77 + bool contains_allocated() const { return (_bits & ALLOCATED) != 0; } 1.78 + bool contains_vars() const { return (_bits & (((1 << MAXBIT) -1) << 2)) != 0; } 1.79 + void set(uint var) { _bits = int_to_bit(var); } 1.80 + void add(uint var) { _bits |= int_to_bit(var); } 1.81 + void add_unknown() { _bits = UNKNOWN; } 1.82 + void add_allocated() { _bits = ALLOCATED; } 1.83 + void set_union(const ArgumentMap &am) { _bits |= am._bits; } 1.84 + void set_intersect(const ArgumentMap &am) { _bits |= am._bits; } 1.85 + void set_difference(const ArgumentMap &am) { _bits &= ~am._bits; } 1.86 + void operator=(const ArgumentMap &am) { _bits = am._bits; } 1.87 + bool operator==(const ArgumentMap &am) { return _bits == am._bits; } 1.88 + bool operator!=(const ArgumentMap &am) { return _bits != am._bits; } 1.89 +}; 1.90 + 1.91 +class BCEscapeAnalyzer::StateInfo { 1.92 +public: 1.93 + ArgumentMap *_vars; 1.94 + ArgumentMap *_stack; 1.95 + short _stack_height; 1.96 + short _max_stack; 1.97 + bool _initialized; 1.98 + ArgumentMap empty_map; 1.99 + 1.100 + StateInfo() { 1.101 + empty_map.clear(); 1.102 + } 1.103 + 1.104 + ArgumentMap raw_pop() { guarantee(_stack_height > 0, "stack underflow"); return _stack[--_stack_height]; } 1.105 + ArgumentMap apop() { return raw_pop(); } 1.106 + void spop() { raw_pop(); } 1.107 + void lpop() { spop(); spop(); } 1.108 + void raw_push(ArgumentMap i) { guarantee(_stack_height < _max_stack, "stack overflow"); _stack[_stack_height++] = i; } 1.109 + void apush(ArgumentMap i) { raw_push(i); } 1.110 + void spush() { raw_push(empty_map); } 1.111 + void lpush() { spush(); spush(); } 1.112 + 1.113 +}; 1.114 + 1.115 +void BCEscapeAnalyzer::set_returned(ArgumentMap vars) { 1.116 + for (int i = 0; i < _arg_size; i++) { 1.117 + if (vars.contains(i)) 1.118 + _arg_returned.set(i); 1.119 + } 1.120 + _return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated()); 1.121 + _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars()); 1.122 +} 1.123 + 1.124 +// return true if any element of vars is an argument 1.125 +bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) { 1.126 + for (int i = 0; i < _arg_size; i++) { 1.127 + if (vars.contains(i)) 1.128 + return true; 1.129 + } 1.130 + return false; 1.131 +} 1.132 + 1.133 +// return true if any element of vars is an arg_stack argument 1.134 +bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ 1.135 + if (_conservative) 1.136 + return true; 1.137 + for (int i = 0; i < _arg_size; i++) { 1.138 + if (vars.contains(i) && _arg_stack.test(i)) 1.139 + return true; 1.140 + } 1.141 + return false; 1.142 +} 1.143 + 1.144 +// return true if all argument elements of vars are returned 1.145 +bool BCEscapeAnalyzer::returns_all(ArgumentMap vars) { 1.146 + for (int i = 0; i < _arg_size; i++) { 1.147 + if (vars.contains(i) && !_arg_returned.test(i)) { 1.148 + return false; 1.149 + } 1.150 + } 1.151 + return true; 1.152 +} 1.153 + 1.154 +void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) { 1.155 + for (int i = 0; i < _arg_size; i++) { 1.156 + if (vars.contains(i)) { 1.157 + bm >>= i; 1.158 + } 1.159 + } 1.160 +} 1.161 + 1.162 +void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) { 1.163 + clear_bits(vars, _arg_local); 1.164 + if (vars.contains_allocated()) { 1.165 + _allocated_escapes = true; 1.166 + } 1.167 +} 1.168 + 1.169 +void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars, bool merge) { 1.170 + clear_bits(vars, _arg_local); 1.171 + clear_bits(vars, _arg_stack); 1.172 + if (vars.contains_allocated()) 1.173 + _allocated_escapes = true; 1.174 + 1.175 + if (merge && !vars.is_empty()) { 1.176 + // Merge new state into already processed block. 1.177 + // New state is not taken into account and 1.178 + // it may invalidate set_returned() result. 1.179 + if (vars.contains_unknown() || vars.contains_allocated()) { 1.180 + _return_local = false; 1.181 + } 1.182 + if (vars.contains_unknown() || vars.contains_vars()) { 1.183 + _return_allocated = false; 1.184 + } 1.185 + if (_return_local && vars.contains_vars() && !returns_all(vars)) { 1.186 + // Return result should be invalidated if args in new 1.187 + // state are not recorded in return state. 1.188 + _return_local = false; 1.189 + } 1.190 + } 1.191 +} 1.192 + 1.193 +void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) { 1.194 + clear_bits(vars, _dirty); 1.195 +} 1.196 + 1.197 +void BCEscapeAnalyzer::set_modified(ArgumentMap vars, int offs, int size) { 1.198 + 1.199 + for (int i = 0; i < _arg_size; i++) { 1.200 + if (vars.contains(i)) { 1.201 + set_arg_modified(i, offs, size); 1.202 + } 1.203 + } 1.204 + if (vars.contains_unknown()) 1.205 + _unknown_modified = true; 1.206 +} 1.207 + 1.208 +bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) { 1.209 + for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) { 1.210 + if (scope->method() == callee) { 1.211 + return true; 1.212 + } 1.213 + } 1.214 + return false; 1.215 +} 1.216 + 1.217 +bool BCEscapeAnalyzer::is_arg_modified(int arg, int offset, int size_in_bytes) { 1.218 + if (offset == OFFSET_ANY) 1.219 + return _arg_modified[arg] != 0; 1.220 + assert(arg >= 0 && arg < _arg_size, "must be an argument."); 1.221 + bool modified = false; 1.222 + int l = offset / HeapWordSize; 1.223 + int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize; 1.224 + if (l > ARG_OFFSET_MAX) 1.225 + l = ARG_OFFSET_MAX; 1.226 + if (h > ARG_OFFSET_MAX+1) 1.227 + h = ARG_OFFSET_MAX + 1; 1.228 + for (int i = l; i < h; i++) { 1.229 + modified = modified || (_arg_modified[arg] & (1 << i)) != 0; 1.230 + } 1.231 + return modified; 1.232 +} 1.233 + 1.234 +void BCEscapeAnalyzer::set_arg_modified(int arg, int offset, int size_in_bytes) { 1.235 + if (offset == OFFSET_ANY) { 1.236 + _arg_modified[arg] = (uint) -1; 1.237 + return; 1.238 + } 1.239 + assert(arg >= 0 && arg < _arg_size, "must be an argument."); 1.240 + int l = offset / HeapWordSize; 1.241 + int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize; 1.242 + if (l > ARG_OFFSET_MAX) 1.243 + l = ARG_OFFSET_MAX; 1.244 + if (h > ARG_OFFSET_MAX+1) 1.245 + h = ARG_OFFSET_MAX + 1; 1.246 + for (int i = l; i < h; i++) { 1.247 + _arg_modified[arg] |= (1 << i); 1.248 + } 1.249 +} 1.250 + 1.251 +void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) { 1.252 + int i; 1.253 + 1.254 + // retrieve information about the callee 1.255 + ciInstanceKlass* klass = target->holder(); 1.256 + ciInstanceKlass* calling_klass = method()->holder(); 1.257 + ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder); 1.258 + ciInstanceKlass* actual_recv = callee_holder; 1.259 + 1.260 + // Some methods are obviously bindable without any type checks so 1.261 + // convert them directly to an invokespecial or invokestatic. 1.262 + if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) { 1.263 + switch (code) { 1.264 + case Bytecodes::_invokevirtual: 1.265 + code = Bytecodes::_invokespecial; 1.266 + break; 1.267 + case Bytecodes::_invokehandle: 1.268 + code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial; 1.269 + break; 1.270 + } 1.271 + } 1.272 + 1.273 + // compute size of arguments 1.274 + int arg_size = target->invoke_arg_size(code); 1.275 + int arg_base = MAX2(state._stack_height - arg_size, 0); 1.276 + 1.277 + // direct recursive calls are skipped if they can be bound statically without introducing 1.278 + // dependencies and if parameters are passed at the same position as in the current method 1.279 + // other calls are skipped if there are no unescaped arguments passed to them 1.280 + bool directly_recursive = (method() == target) && 1.281 + (code != Bytecodes::_invokevirtual || target->is_final_method() || state._stack[arg_base] .is_empty()); 1.282 + 1.283 + // check if analysis of callee can safely be skipped 1.284 + bool skip_callee = true; 1.285 + for (i = state._stack_height - 1; i >= arg_base && skip_callee; i--) { 1.286 + ArgumentMap arg = state._stack[i]; 1.287 + skip_callee = !is_argument(arg) || !is_arg_stack(arg) || (directly_recursive && arg.is_singleton(i - arg_base)); 1.288 + } 1.289 + // For now we conservatively skip invokedynamic. 1.290 + if (code == Bytecodes::_invokedynamic) { 1.291 + skip_callee = true; 1.292 + } 1.293 + if (skip_callee) { 1.294 + TRACE_BCEA(3, tty->print_cr("[EA] skipping method %s::%s", holder->name()->as_utf8(), target->name()->as_utf8())); 1.295 + for (i = 0; i < arg_size; i++) { 1.296 + set_method_escape(state.raw_pop()); 1.297 + } 1.298 + _unknown_modified = true; // assume the worst since we don't analyze the called method 1.299 + return; 1.300 + } 1.301 + 1.302 + // determine actual method (use CHA if necessary) 1.303 + ciMethod* inline_target = NULL; 1.304 + if (target->is_loaded() && klass->is_loaded() 1.305 + && (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) 1.306 + && target->is_loaded()) { 1.307 + if (code == Bytecodes::_invokestatic 1.308 + || code == Bytecodes::_invokespecial 1.309 + || code == Bytecodes::_invokevirtual && target->is_final_method()) { 1.310 + inline_target = target; 1.311 + } else { 1.312 + inline_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv); 1.313 + } 1.314 + } 1.315 + 1.316 + if (inline_target != NULL && !is_recursive_call(inline_target)) { 1.317 + // analyze callee 1.318 + BCEscapeAnalyzer analyzer(inline_target, this); 1.319 + 1.320 + // adjust escape state of actual parameters 1.321 + bool must_record_dependencies = false; 1.322 + for (i = arg_size - 1; i >= 0; i--) { 1.323 + ArgumentMap arg = state.raw_pop(); 1.324 + if (!is_argument(arg)) 1.325 + continue; 1.326 + for (int j = 0; j < _arg_size; j++) { 1.327 + if (arg.contains(j)) { 1.328 + _arg_modified[j] |= analyzer._arg_modified[i]; 1.329 + } 1.330 + } 1.331 + if (!is_arg_stack(arg)) { 1.332 + // arguments have already been recognized as escaping 1.333 + } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) { 1.334 + set_method_escape(arg); 1.335 + must_record_dependencies = true; 1.336 + } else { 1.337 + set_global_escape(arg); 1.338 + } 1.339 + } 1.340 + _unknown_modified = _unknown_modified || analyzer.has_non_arg_side_affects(); 1.341 + 1.342 + // record dependencies if at least one parameter retained stack-allocatable 1.343 + if (must_record_dependencies) { 1.344 + if (code == Bytecodes::_invokeinterface || code == Bytecodes::_invokevirtual && !target->is_final_method()) { 1.345 + _dependencies.append(actual_recv); 1.346 + _dependencies.append(inline_target); 1.347 + } 1.348 + _dependencies.appendAll(analyzer.dependencies()); 1.349 + } 1.350 + } else { 1.351 + TRACE_BCEA(1, tty->print_cr("[EA] virtual method %s is not monomorphic.", 1.352 + target->name()->as_utf8())); 1.353 + // conservatively mark all actual parameters as escaping globally 1.354 + for (i = 0; i < arg_size; i++) { 1.355 + ArgumentMap arg = state.raw_pop(); 1.356 + if (!is_argument(arg)) 1.357 + continue; 1.358 + set_modified(arg, OFFSET_ANY, type2size[T_INT]*HeapWordSize); 1.359 + set_global_escape(arg); 1.360 + } 1.361 + _unknown_modified = true; // assume the worst since we don't know the called method 1.362 + } 1.363 +} 1.364 + 1.365 +bool BCEscapeAnalyzer::contains(uint arg_set1, uint arg_set2) { 1.366 + return ((~arg_set1) | arg_set2) == 0; 1.367 +} 1.368 + 1.369 + 1.370 +void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, GrowableArray<ciBlock *> &successors) { 1.371 + 1.372 + blk->set_processed(); 1.373 + ciBytecodeStream s(method()); 1.374 + int limit_bci = blk->limit_bci(); 1.375 + bool fall_through = false; 1.376 + ArgumentMap allocated_obj; 1.377 + allocated_obj.add_allocated(); 1.378 + ArgumentMap unknown_obj; 1.379 + unknown_obj.add_unknown(); 1.380 + ArgumentMap empty_map; 1.381 + 1.382 + s.reset_to_bci(blk->start_bci()); 1.383 + while (s.next() != ciBytecodeStream::EOBC() && s.cur_bci() < limit_bci) { 1.384 + fall_through = true; 1.385 + switch (s.cur_bc()) { 1.386 + case Bytecodes::_nop: 1.387 + break; 1.388 + case Bytecodes::_aconst_null: 1.389 + state.apush(unknown_obj); 1.390 + break; 1.391 + case Bytecodes::_iconst_m1: 1.392 + case Bytecodes::_iconst_0: 1.393 + case Bytecodes::_iconst_1: 1.394 + case Bytecodes::_iconst_2: 1.395 + case Bytecodes::_iconst_3: 1.396 + case Bytecodes::_iconst_4: 1.397 + case Bytecodes::_iconst_5: 1.398 + case Bytecodes::_fconst_0: 1.399 + case Bytecodes::_fconst_1: 1.400 + case Bytecodes::_fconst_2: 1.401 + case Bytecodes::_bipush: 1.402 + case Bytecodes::_sipush: 1.403 + state.spush(); 1.404 + break; 1.405 + case Bytecodes::_lconst_0: 1.406 + case Bytecodes::_lconst_1: 1.407 + case Bytecodes::_dconst_0: 1.408 + case Bytecodes::_dconst_1: 1.409 + state.lpush(); 1.410 + break; 1.411 + case Bytecodes::_ldc: 1.412 + case Bytecodes::_ldc_w: 1.413 + case Bytecodes::_ldc2_w: 1.414 + { 1.415 + // Avoid calling get_constant() which will try to allocate 1.416 + // unloaded constant. We need only constant's type. 1.417 + int index = s.get_constant_pool_index(); 1.418 + constantTag tag = s.get_constant_pool_tag(index); 1.419 + if (tag.is_long() || tag.is_double()) { 1.420 + // Only longs and doubles use 2 stack slots. 1.421 + state.lpush(); 1.422 + } else if (tag.basic_type() == T_OBJECT) { 1.423 + state.apush(unknown_obj); 1.424 + } else { 1.425 + state.spush(); 1.426 + } 1.427 + break; 1.428 + } 1.429 + case Bytecodes::_aload: 1.430 + state.apush(state._vars[s.get_index()]); 1.431 + break; 1.432 + case Bytecodes::_iload: 1.433 + case Bytecodes::_fload: 1.434 + case Bytecodes::_iload_0: 1.435 + case Bytecodes::_iload_1: 1.436 + case Bytecodes::_iload_2: 1.437 + case Bytecodes::_iload_3: 1.438 + case Bytecodes::_fload_0: 1.439 + case Bytecodes::_fload_1: 1.440 + case Bytecodes::_fload_2: 1.441 + case Bytecodes::_fload_3: 1.442 + state.spush(); 1.443 + break; 1.444 + case Bytecodes::_lload: 1.445 + case Bytecodes::_dload: 1.446 + case Bytecodes::_lload_0: 1.447 + case Bytecodes::_lload_1: 1.448 + case Bytecodes::_lload_2: 1.449 + case Bytecodes::_lload_3: 1.450 + case Bytecodes::_dload_0: 1.451 + case Bytecodes::_dload_1: 1.452 + case Bytecodes::_dload_2: 1.453 + case Bytecodes::_dload_3: 1.454 + state.lpush(); 1.455 + break; 1.456 + case Bytecodes::_aload_0: 1.457 + state.apush(state._vars[0]); 1.458 + break; 1.459 + case Bytecodes::_aload_1: 1.460 + state.apush(state._vars[1]); 1.461 + break; 1.462 + case Bytecodes::_aload_2: 1.463 + state.apush(state._vars[2]); 1.464 + break; 1.465 + case Bytecodes::_aload_3: 1.466 + state.apush(state._vars[3]); 1.467 + break; 1.468 + case Bytecodes::_iaload: 1.469 + case Bytecodes::_faload: 1.470 + case Bytecodes::_baload: 1.471 + case Bytecodes::_caload: 1.472 + case Bytecodes::_saload: 1.473 + state.spop(); 1.474 + set_method_escape(state.apop()); 1.475 + state.spush(); 1.476 + break; 1.477 + case Bytecodes::_laload: 1.478 + case Bytecodes::_daload: 1.479 + state.spop(); 1.480 + set_method_escape(state.apop()); 1.481 + state.lpush(); 1.482 + break; 1.483 + case Bytecodes::_aaload: 1.484 + { state.spop(); 1.485 + ArgumentMap array = state.apop(); 1.486 + set_method_escape(array); 1.487 + state.apush(unknown_obj); 1.488 + set_dirty(array); 1.489 + } 1.490 + break; 1.491 + case Bytecodes::_istore: 1.492 + case Bytecodes::_fstore: 1.493 + case Bytecodes::_istore_0: 1.494 + case Bytecodes::_istore_1: 1.495 + case Bytecodes::_istore_2: 1.496 + case Bytecodes::_istore_3: 1.497 + case Bytecodes::_fstore_0: 1.498 + case Bytecodes::_fstore_1: 1.499 + case Bytecodes::_fstore_2: 1.500 + case Bytecodes::_fstore_3: 1.501 + state.spop(); 1.502 + break; 1.503 + case Bytecodes::_lstore: 1.504 + case Bytecodes::_dstore: 1.505 + case Bytecodes::_lstore_0: 1.506 + case Bytecodes::_lstore_1: 1.507 + case Bytecodes::_lstore_2: 1.508 + case Bytecodes::_lstore_3: 1.509 + case Bytecodes::_dstore_0: 1.510 + case Bytecodes::_dstore_1: 1.511 + case Bytecodes::_dstore_2: 1.512 + case Bytecodes::_dstore_3: 1.513 + state.lpop(); 1.514 + break; 1.515 + case Bytecodes::_astore: 1.516 + state._vars[s.get_index()] = state.apop(); 1.517 + break; 1.518 + case Bytecodes::_astore_0: 1.519 + state._vars[0] = state.apop(); 1.520 + break; 1.521 + case Bytecodes::_astore_1: 1.522 + state._vars[1] = state.apop(); 1.523 + break; 1.524 + case Bytecodes::_astore_2: 1.525 + state._vars[2] = state.apop(); 1.526 + break; 1.527 + case Bytecodes::_astore_3: 1.528 + state._vars[3] = state.apop(); 1.529 + break; 1.530 + case Bytecodes::_iastore: 1.531 + case Bytecodes::_fastore: 1.532 + case Bytecodes::_bastore: 1.533 + case Bytecodes::_castore: 1.534 + case Bytecodes::_sastore: 1.535 + { 1.536 + state.spop(); 1.537 + state.spop(); 1.538 + ArgumentMap arr = state.apop(); 1.539 + set_method_escape(arr); 1.540 + set_modified(arr, OFFSET_ANY, type2size[T_INT]*HeapWordSize); 1.541 + break; 1.542 + } 1.543 + case Bytecodes::_lastore: 1.544 + case Bytecodes::_dastore: 1.545 + { 1.546 + state.lpop(); 1.547 + state.spop(); 1.548 + ArgumentMap arr = state.apop(); 1.549 + set_method_escape(arr); 1.550 + set_modified(arr, OFFSET_ANY, type2size[T_LONG]*HeapWordSize); 1.551 + break; 1.552 + } 1.553 + case Bytecodes::_aastore: 1.554 + { 1.555 + set_global_escape(state.apop()); 1.556 + state.spop(); 1.557 + ArgumentMap arr = state.apop(); 1.558 + set_modified(arr, OFFSET_ANY, type2size[T_OBJECT]*HeapWordSize); 1.559 + break; 1.560 + } 1.561 + case Bytecodes::_pop: 1.562 + state.raw_pop(); 1.563 + break; 1.564 + case Bytecodes::_pop2: 1.565 + state.raw_pop(); 1.566 + state.raw_pop(); 1.567 + break; 1.568 + case Bytecodes::_dup: 1.569 + { ArgumentMap w1 = state.raw_pop(); 1.570 + state.raw_push(w1); 1.571 + state.raw_push(w1); 1.572 + } 1.573 + break; 1.574 + case Bytecodes::_dup_x1: 1.575 + { ArgumentMap w1 = state.raw_pop(); 1.576 + ArgumentMap w2 = state.raw_pop(); 1.577 + state.raw_push(w1); 1.578 + state.raw_push(w2); 1.579 + state.raw_push(w1); 1.580 + } 1.581 + break; 1.582 + case Bytecodes::_dup_x2: 1.583 + { ArgumentMap w1 = state.raw_pop(); 1.584 + ArgumentMap w2 = state.raw_pop(); 1.585 + ArgumentMap w3 = state.raw_pop(); 1.586 + state.raw_push(w1); 1.587 + state.raw_push(w3); 1.588 + state.raw_push(w2); 1.589 + state.raw_push(w1); 1.590 + } 1.591 + break; 1.592 + case Bytecodes::_dup2: 1.593 + { ArgumentMap w1 = state.raw_pop(); 1.594 + ArgumentMap w2 = state.raw_pop(); 1.595 + state.raw_push(w2); 1.596 + state.raw_push(w1); 1.597 + state.raw_push(w2); 1.598 + state.raw_push(w1); 1.599 + } 1.600 + break; 1.601 + case Bytecodes::_dup2_x1: 1.602 + { ArgumentMap w1 = state.raw_pop(); 1.603 + ArgumentMap w2 = state.raw_pop(); 1.604 + ArgumentMap w3 = state.raw_pop(); 1.605 + state.raw_push(w2); 1.606 + state.raw_push(w1); 1.607 + state.raw_push(w3); 1.608 + state.raw_push(w2); 1.609 + state.raw_push(w1); 1.610 + } 1.611 + break; 1.612 + case Bytecodes::_dup2_x2: 1.613 + { ArgumentMap w1 = state.raw_pop(); 1.614 + ArgumentMap w2 = state.raw_pop(); 1.615 + ArgumentMap w3 = state.raw_pop(); 1.616 + ArgumentMap w4 = state.raw_pop(); 1.617 + state.raw_push(w2); 1.618 + state.raw_push(w1); 1.619 + state.raw_push(w4); 1.620 + state.raw_push(w3); 1.621 + state.raw_push(w2); 1.622 + state.raw_push(w1); 1.623 + } 1.624 + break; 1.625 + case Bytecodes::_swap: 1.626 + { ArgumentMap w1 = state.raw_pop(); 1.627 + ArgumentMap w2 = state.raw_pop(); 1.628 + state.raw_push(w1); 1.629 + state.raw_push(w2); 1.630 + } 1.631 + break; 1.632 + case Bytecodes::_iadd: 1.633 + case Bytecodes::_fadd: 1.634 + case Bytecodes::_isub: 1.635 + case Bytecodes::_fsub: 1.636 + case Bytecodes::_imul: 1.637 + case Bytecodes::_fmul: 1.638 + case Bytecodes::_idiv: 1.639 + case Bytecodes::_fdiv: 1.640 + case Bytecodes::_irem: 1.641 + case Bytecodes::_frem: 1.642 + case Bytecodes::_iand: 1.643 + case Bytecodes::_ior: 1.644 + case Bytecodes::_ixor: 1.645 + state.spop(); 1.646 + state.spop(); 1.647 + state.spush(); 1.648 + break; 1.649 + case Bytecodes::_ladd: 1.650 + case Bytecodes::_dadd: 1.651 + case Bytecodes::_lsub: 1.652 + case Bytecodes::_dsub: 1.653 + case Bytecodes::_lmul: 1.654 + case Bytecodes::_dmul: 1.655 + case Bytecodes::_ldiv: 1.656 + case Bytecodes::_ddiv: 1.657 + case Bytecodes::_lrem: 1.658 + case Bytecodes::_drem: 1.659 + case Bytecodes::_land: 1.660 + case Bytecodes::_lor: 1.661 + case Bytecodes::_lxor: 1.662 + state.lpop(); 1.663 + state.lpop(); 1.664 + state.lpush(); 1.665 + break; 1.666 + case Bytecodes::_ishl: 1.667 + case Bytecodes::_ishr: 1.668 + case Bytecodes::_iushr: 1.669 + state.spop(); 1.670 + state.spop(); 1.671 + state.spush(); 1.672 + break; 1.673 + case Bytecodes::_lshl: 1.674 + case Bytecodes::_lshr: 1.675 + case Bytecodes::_lushr: 1.676 + state.spop(); 1.677 + state.lpop(); 1.678 + state.lpush(); 1.679 + break; 1.680 + case Bytecodes::_ineg: 1.681 + case Bytecodes::_fneg: 1.682 + state.spop(); 1.683 + state.spush(); 1.684 + break; 1.685 + case Bytecodes::_lneg: 1.686 + case Bytecodes::_dneg: 1.687 + state.lpop(); 1.688 + state.lpush(); 1.689 + break; 1.690 + case Bytecodes::_iinc: 1.691 + break; 1.692 + case Bytecodes::_i2l: 1.693 + case Bytecodes::_i2d: 1.694 + case Bytecodes::_f2l: 1.695 + case Bytecodes::_f2d: 1.696 + state.spop(); 1.697 + state.lpush(); 1.698 + break; 1.699 + case Bytecodes::_i2f: 1.700 + case Bytecodes::_f2i: 1.701 + state.spop(); 1.702 + state.spush(); 1.703 + break; 1.704 + case Bytecodes::_l2i: 1.705 + case Bytecodes::_l2f: 1.706 + case Bytecodes::_d2i: 1.707 + case Bytecodes::_d2f: 1.708 + state.lpop(); 1.709 + state.spush(); 1.710 + break; 1.711 + case Bytecodes::_l2d: 1.712 + case Bytecodes::_d2l: 1.713 + state.lpop(); 1.714 + state.lpush(); 1.715 + break; 1.716 + case Bytecodes::_i2b: 1.717 + case Bytecodes::_i2c: 1.718 + case Bytecodes::_i2s: 1.719 + state.spop(); 1.720 + state.spush(); 1.721 + break; 1.722 + case Bytecodes::_lcmp: 1.723 + case Bytecodes::_dcmpl: 1.724 + case Bytecodes::_dcmpg: 1.725 + state.lpop(); 1.726 + state.lpop(); 1.727 + state.spush(); 1.728 + break; 1.729 + case Bytecodes::_fcmpl: 1.730 + case Bytecodes::_fcmpg: 1.731 + state.spop(); 1.732 + state.spop(); 1.733 + state.spush(); 1.734 + break; 1.735 + case Bytecodes::_ifeq: 1.736 + case Bytecodes::_ifne: 1.737 + case Bytecodes::_iflt: 1.738 + case Bytecodes::_ifge: 1.739 + case Bytecodes::_ifgt: 1.740 + case Bytecodes::_ifle: 1.741 + { 1.742 + state.spop(); 1.743 + int dest_bci = s.get_dest(); 1.744 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.745 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.746 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.747 + break; 1.748 + } 1.749 + case Bytecodes::_if_icmpeq: 1.750 + case Bytecodes::_if_icmpne: 1.751 + case Bytecodes::_if_icmplt: 1.752 + case Bytecodes::_if_icmpge: 1.753 + case Bytecodes::_if_icmpgt: 1.754 + case Bytecodes::_if_icmple: 1.755 + { 1.756 + state.spop(); 1.757 + state.spop(); 1.758 + int dest_bci = s.get_dest(); 1.759 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.760 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.761 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.762 + break; 1.763 + } 1.764 + case Bytecodes::_if_acmpeq: 1.765 + case Bytecodes::_if_acmpne: 1.766 + { 1.767 + set_method_escape(state.apop()); 1.768 + set_method_escape(state.apop()); 1.769 + int dest_bci = s.get_dest(); 1.770 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.771 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.772 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.773 + break; 1.774 + } 1.775 + case Bytecodes::_goto: 1.776 + { 1.777 + int dest_bci = s.get_dest(); 1.778 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.779 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.780 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.781 + fall_through = false; 1.782 + break; 1.783 + } 1.784 + case Bytecodes::_jsr: 1.785 + { 1.786 + int dest_bci = s.get_dest(); 1.787 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.788 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.789 + state.apush(empty_map); 1.790 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.791 + fall_through = false; 1.792 + break; 1.793 + } 1.794 + case Bytecodes::_ret: 1.795 + // we don't track the destination of a "ret" instruction 1.796 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.797 + fall_through = false; 1.798 + break; 1.799 + case Bytecodes::_return: 1.800 + assert(s.next_bci() == limit_bci, "return must end block"); 1.801 + fall_through = false; 1.802 + break; 1.803 + case Bytecodes::_tableswitch: 1.804 + { 1.805 + state.spop(); 1.806 + Bytecode_tableswitch sw(&s); 1.807 + int len = sw.length(); 1.808 + int dest_bci; 1.809 + for (int i = 0; i < len; i++) { 1.810 + dest_bci = s.cur_bci() + sw.dest_offset_at(i); 1.811 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.812 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.813 + } 1.814 + dest_bci = s.cur_bci() + sw.default_offset(); 1.815 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.816 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.817 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.818 + fall_through = false; 1.819 + break; 1.820 + } 1.821 + case Bytecodes::_lookupswitch: 1.822 + { 1.823 + state.spop(); 1.824 + Bytecode_lookupswitch sw(&s); 1.825 + int len = sw.number_of_pairs(); 1.826 + int dest_bci; 1.827 + for (int i = 0; i < len; i++) { 1.828 + dest_bci = s.cur_bci() + sw.pair_at(i).offset(); 1.829 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.830 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.831 + } 1.832 + dest_bci = s.cur_bci() + sw.default_offset(); 1.833 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.834 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.835 + fall_through = false; 1.836 + break; 1.837 + } 1.838 + case Bytecodes::_ireturn: 1.839 + case Bytecodes::_freturn: 1.840 + state.spop(); 1.841 + fall_through = false; 1.842 + break; 1.843 + case Bytecodes::_lreturn: 1.844 + case Bytecodes::_dreturn: 1.845 + state.lpop(); 1.846 + fall_through = false; 1.847 + break; 1.848 + case Bytecodes::_areturn: 1.849 + set_returned(state.apop()); 1.850 + fall_through = false; 1.851 + break; 1.852 + case Bytecodes::_getstatic: 1.853 + case Bytecodes::_getfield: 1.854 + { bool ignored_will_link; 1.855 + ciField* field = s.get_field(ignored_will_link); 1.856 + BasicType field_type = field->type()->basic_type(); 1.857 + if (s.cur_bc() != Bytecodes::_getstatic) { 1.858 + set_method_escape(state.apop()); 1.859 + } 1.860 + if (field_type == T_OBJECT || field_type == T_ARRAY) { 1.861 + state.apush(unknown_obj); 1.862 + } else if (type2size[field_type] == 1) { 1.863 + state.spush(); 1.864 + } else { 1.865 + state.lpush(); 1.866 + } 1.867 + } 1.868 + break; 1.869 + case Bytecodes::_putstatic: 1.870 + case Bytecodes::_putfield: 1.871 + { bool will_link; 1.872 + ciField* field = s.get_field(will_link); 1.873 + BasicType field_type = field->type()->basic_type(); 1.874 + if (field_type == T_OBJECT || field_type == T_ARRAY) { 1.875 + set_global_escape(state.apop()); 1.876 + } else if (type2size[field_type] == 1) { 1.877 + state.spop(); 1.878 + } else { 1.879 + state.lpop(); 1.880 + } 1.881 + if (s.cur_bc() != Bytecodes::_putstatic) { 1.882 + ArgumentMap p = state.apop(); 1.883 + set_method_escape(p); 1.884 + set_modified(p, will_link ? field->offset() : OFFSET_ANY, type2size[field_type]*HeapWordSize); 1.885 + } 1.886 + } 1.887 + break; 1.888 + case Bytecodes::_invokevirtual: 1.889 + case Bytecodes::_invokespecial: 1.890 + case Bytecodes::_invokestatic: 1.891 + case Bytecodes::_invokedynamic: 1.892 + case Bytecodes::_invokeinterface: 1.893 + { bool ignored_will_link; 1.894 + ciSignature* declared_signature = NULL; 1.895 + ciMethod* target = s.get_method(ignored_will_link, &declared_signature); 1.896 + ciKlass* holder = s.get_declared_method_holder(); 1.897 + assert(declared_signature != NULL, "cannot be null"); 1.898 + // Push appendix argument, if one. 1.899 + if (s.has_appendix()) { 1.900 + state.apush(unknown_obj); 1.901 + } 1.902 + // Pass in raw bytecode because we need to see invokehandle instructions. 1.903 + invoke(state, s.cur_bc_raw(), target, holder); 1.904 + // We are using the return type of the declared signature here because 1.905 + // it might be a more concrete type than the one from the target (for 1.906 + // e.g. invokedynamic and invokehandle). 1.907 + ciType* return_type = declared_signature->return_type(); 1.908 + if (!return_type->is_primitive_type()) { 1.909 + state.apush(unknown_obj); 1.910 + } else if (return_type->is_one_word()) { 1.911 + state.spush(); 1.912 + } else if (return_type->is_two_word()) { 1.913 + state.lpush(); 1.914 + } 1.915 + } 1.916 + break; 1.917 + case Bytecodes::_new: 1.918 + state.apush(allocated_obj); 1.919 + break; 1.920 + case Bytecodes::_newarray: 1.921 + case Bytecodes::_anewarray: 1.922 + state.spop(); 1.923 + state.apush(allocated_obj); 1.924 + break; 1.925 + case Bytecodes::_multianewarray: 1.926 + { int i = s.cur_bcp()[3]; 1.927 + while (i-- > 0) state.spop(); 1.928 + state.apush(allocated_obj); 1.929 + } 1.930 + break; 1.931 + case Bytecodes::_arraylength: 1.932 + set_method_escape(state.apop()); 1.933 + state.spush(); 1.934 + break; 1.935 + case Bytecodes::_athrow: 1.936 + set_global_escape(state.apop()); 1.937 + fall_through = false; 1.938 + break; 1.939 + case Bytecodes::_checkcast: 1.940 + { ArgumentMap obj = state.apop(); 1.941 + set_method_escape(obj); 1.942 + state.apush(obj); 1.943 + } 1.944 + break; 1.945 + case Bytecodes::_instanceof: 1.946 + set_method_escape(state.apop()); 1.947 + state.spush(); 1.948 + break; 1.949 + case Bytecodes::_monitorenter: 1.950 + case Bytecodes::_monitorexit: 1.951 + state.apop(); 1.952 + break; 1.953 + case Bytecodes::_wide: 1.954 + ShouldNotReachHere(); 1.955 + break; 1.956 + case Bytecodes::_ifnull: 1.957 + case Bytecodes::_ifnonnull: 1.958 + { 1.959 + set_method_escape(state.apop()); 1.960 + int dest_bci = s.get_dest(); 1.961 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.962 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.963 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.964 + break; 1.965 + } 1.966 + case Bytecodes::_goto_w: 1.967 + { 1.968 + int dest_bci = s.get_far_dest(); 1.969 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.970 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.971 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.972 + fall_through = false; 1.973 + break; 1.974 + } 1.975 + case Bytecodes::_jsr_w: 1.976 + { 1.977 + int dest_bci = s.get_far_dest(); 1.978 + assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); 1.979 + assert(s.next_bci() == limit_bci, "branch must end block"); 1.980 + state.apush(empty_map); 1.981 + successors.push(_methodBlocks->block_containing(dest_bci)); 1.982 + fall_through = false; 1.983 + break; 1.984 + } 1.985 + case Bytecodes::_breakpoint: 1.986 + break; 1.987 + default: 1.988 + ShouldNotReachHere(); 1.989 + break; 1.990 + } 1.991 + 1.992 + } 1.993 + if (fall_through) { 1.994 + int fall_through_bci = s.cur_bci(); 1.995 + if (fall_through_bci < _method->code_size()) { 1.996 + assert(_methodBlocks->is_block_start(fall_through_bci), "must fall through to block start."); 1.997 + successors.push(_methodBlocks->block_containing(fall_through_bci)); 1.998 + } 1.999 + } 1.1000 +} 1.1001 + 1.1002 +void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) { 1.1003 + StateInfo *d_state = blockstates + dest->index(); 1.1004 + int nlocals = _method->max_locals(); 1.1005 + 1.1006 + // exceptions may cause transfer of control to handlers in the middle of a 1.1007 + // block, so we don't merge the incoming state of exception handlers 1.1008 + if (dest->is_handler()) 1.1009 + return; 1.1010 + if (!d_state->_initialized ) { 1.1011 + // destination not initialized, just copy 1.1012 + for (int i = 0; i < nlocals; i++) { 1.1013 + d_state->_vars[i] = s_state->_vars[i]; 1.1014 + } 1.1015 + for (int i = 0; i < s_state->_stack_height; i++) { 1.1016 + d_state->_stack[i] = s_state->_stack[i]; 1.1017 + } 1.1018 + d_state->_stack_height = s_state->_stack_height; 1.1019 + d_state->_max_stack = s_state->_max_stack; 1.1020 + d_state->_initialized = true; 1.1021 + } else if (!dest->processed()) { 1.1022 + // we have not yet walked the bytecodes of dest, we can merge 1.1023 + // the states 1.1024 + assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match"); 1.1025 + for (int i = 0; i < nlocals; i++) { 1.1026 + d_state->_vars[i].set_union(s_state->_vars[i]); 1.1027 + } 1.1028 + for (int i = 0; i < s_state->_stack_height; i++) { 1.1029 + d_state->_stack[i].set_union(s_state->_stack[i]); 1.1030 + } 1.1031 + } else { 1.1032 + // the bytecodes of dest have already been processed, mark any 1.1033 + // arguments in the source state which are not in the dest state 1.1034 + // as global escape. 1.1035 + // Future refinement: we only need to mark these variable to the 1.1036 + // maximum escape of any variables in dest state 1.1037 + assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match"); 1.1038 + ArgumentMap extra_vars; 1.1039 + for (int i = 0; i < nlocals; i++) { 1.1040 + ArgumentMap t; 1.1041 + t = s_state->_vars[i]; 1.1042 + t.set_difference(d_state->_vars[i]); 1.1043 + extra_vars.set_union(t); 1.1044 + } 1.1045 + for (int i = 0; i < s_state->_stack_height; i++) { 1.1046 + ArgumentMap t; 1.1047 + //extra_vars |= !d_state->_vars[i] & s_state->_vars[i]; 1.1048 + t.clear(); 1.1049 + t = s_state->_stack[i]; 1.1050 + t.set_difference(d_state->_stack[i]); 1.1051 + extra_vars.set_union(t); 1.1052 + } 1.1053 + set_global_escape(extra_vars, true); 1.1054 + } 1.1055 +} 1.1056 + 1.1057 +void BCEscapeAnalyzer::iterate_blocks(Arena *arena) { 1.1058 + int numblocks = _methodBlocks->num_blocks(); 1.1059 + int stkSize = _method->max_stack(); 1.1060 + int numLocals = _method->max_locals(); 1.1061 + StateInfo state; 1.1062 + 1.1063 + int datacount = (numblocks + 1) * (stkSize + numLocals); 1.1064 + int datasize = datacount * sizeof(ArgumentMap); 1.1065 + StateInfo *blockstates = (StateInfo *) arena->Amalloc(numblocks * sizeof(StateInfo)); 1.1066 + ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize); 1.1067 + for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap(); 1.1068 + ArgumentMap *dp = statedata; 1.1069 + state._vars = dp; 1.1070 + dp += numLocals; 1.1071 + state._stack = dp; 1.1072 + dp += stkSize; 1.1073 + state._initialized = false; 1.1074 + state._max_stack = stkSize; 1.1075 + for (int i = 0; i < numblocks; i++) { 1.1076 + blockstates[i]._vars = dp; 1.1077 + dp += numLocals; 1.1078 + blockstates[i]._stack = dp; 1.1079 + dp += stkSize; 1.1080 + blockstates[i]._initialized = false; 1.1081 + blockstates[i]._stack_height = 0; 1.1082 + blockstates[i]._max_stack = stkSize; 1.1083 + } 1.1084 + GrowableArray<ciBlock *> worklist(arena, numblocks / 4, 0, NULL); 1.1085 + GrowableArray<ciBlock *> successors(arena, 4, 0, NULL); 1.1086 + 1.1087 + _methodBlocks->clear_processed(); 1.1088 + 1.1089 + // initialize block 0 state from method signature 1.1090 + ArgumentMap allVars; // all oop arguments to method 1.1091 + ciSignature* sig = method()->signature(); 1.1092 + int j = 0; 1.1093 + ciBlock* first_blk = _methodBlocks->block_containing(0); 1.1094 + int fb_i = first_blk->index(); 1.1095 + if (!method()->is_static()) { 1.1096 + // record information for "this" 1.1097 + blockstates[fb_i]._vars[j].set(j); 1.1098 + allVars.add(j); 1.1099 + j++; 1.1100 + } 1.1101 + for (int i = 0; i < sig->count(); i++) { 1.1102 + ciType* t = sig->type_at(i); 1.1103 + if (!t->is_primitive_type()) { 1.1104 + blockstates[fb_i]._vars[j].set(j); 1.1105 + allVars.add(j); 1.1106 + } 1.1107 + j += t->size(); 1.1108 + } 1.1109 + blockstates[fb_i]._initialized = true; 1.1110 + assert(j == _arg_size, "just checking"); 1.1111 + 1.1112 + ArgumentMap unknown_map; 1.1113 + unknown_map.add_unknown(); 1.1114 + 1.1115 + worklist.push(first_blk); 1.1116 + while(worklist.length() > 0) { 1.1117 + ciBlock *blk = worklist.pop(); 1.1118 + StateInfo *blkState = blockstates + blk->index(); 1.1119 + if (blk->is_handler() || blk->is_ret_target()) { 1.1120 + // for an exception handler or a target of a ret instruction, we assume the worst case, 1.1121 + // that any variable could contain any argument 1.1122 + for (int i = 0; i < numLocals; i++) { 1.1123 + state._vars[i] = allVars; 1.1124 + } 1.1125 + if (blk->is_handler()) { 1.1126 + state._stack_height = 1; 1.1127 + } else { 1.1128 + state._stack_height = blkState->_stack_height; 1.1129 + } 1.1130 + for (int i = 0; i < state._stack_height; i++) { 1.1131 +// ??? should this be unknown_map ??? 1.1132 + state._stack[i] = allVars; 1.1133 + } 1.1134 + } else { 1.1135 + for (int i = 0; i < numLocals; i++) { 1.1136 + state._vars[i] = blkState->_vars[i]; 1.1137 + } 1.1138 + for (int i = 0; i < blkState->_stack_height; i++) { 1.1139 + state._stack[i] = blkState->_stack[i]; 1.1140 + } 1.1141 + state._stack_height = blkState->_stack_height; 1.1142 + } 1.1143 + iterate_one_block(blk, state, successors); 1.1144 + // if this block has any exception handlers, push them 1.1145 + // onto successor list 1.1146 + if (blk->has_handler()) { 1.1147 + DEBUG_ONLY(int handler_count = 0;) 1.1148 + int blk_start = blk->start_bci(); 1.1149 + int blk_end = blk->limit_bci(); 1.1150 + for (int i = 0; i < numblocks; i++) { 1.1151 + ciBlock *b = _methodBlocks->block(i); 1.1152 + if (b->is_handler()) { 1.1153 + int ex_start = b->ex_start_bci(); 1.1154 + int ex_end = b->ex_limit_bci(); 1.1155 + if ((ex_start >= blk_start && ex_start < blk_end) || 1.1156 + (ex_end > blk_start && ex_end <= blk_end)) { 1.1157 + successors.push(b); 1.1158 + } 1.1159 + DEBUG_ONLY(handler_count++;) 1.1160 + } 1.1161 + } 1.1162 + assert(handler_count > 0, "must find at least one handler"); 1.1163 + } 1.1164 + // merge computed variable state with successors 1.1165 + while(successors.length() > 0) { 1.1166 + ciBlock *succ = successors.pop(); 1.1167 + merge_block_states(blockstates, succ, &state); 1.1168 + if (!succ->processed()) 1.1169 + worklist.push(succ); 1.1170 + } 1.1171 + } 1.1172 +} 1.1173 + 1.1174 +bool BCEscapeAnalyzer::do_analysis() { 1.1175 + Arena* arena = CURRENT_ENV->arena(); 1.1176 + // identify basic blocks 1.1177 + _methodBlocks = _method->get_method_blocks(); 1.1178 + 1.1179 + iterate_blocks(arena); 1.1180 + // TEMPORARY 1.1181 + return true; 1.1182 +} 1.1183 + 1.1184 +vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() { 1.1185 + vmIntrinsics::ID iid = method()->intrinsic_id(); 1.1186 + 1.1187 + if (iid == vmIntrinsics::_getClass || 1.1188 + iid == vmIntrinsics::_fillInStackTrace || 1.1189 + iid == vmIntrinsics::_hashCode) 1.1190 + return iid; 1.1191 + else 1.1192 + return vmIntrinsics::_none; 1.1193 +} 1.1194 + 1.1195 +bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) { 1.1196 + ArgumentMap arg; 1.1197 + arg.clear(); 1.1198 + switch (iid) { 1.1199 + case vmIntrinsics::_getClass: 1.1200 + _return_local = false; 1.1201 + break; 1.1202 + case vmIntrinsics::_fillInStackTrace: 1.1203 + arg.set(0); // 'this' 1.1204 + set_returned(arg); 1.1205 + break; 1.1206 + case vmIntrinsics::_hashCode: 1.1207 + // initialized state is correct 1.1208 + break; 1.1209 + default: 1.1210 + assert(false, "unexpected intrinsic"); 1.1211 + } 1.1212 + return true; 1.1213 +} 1.1214 + 1.1215 +void BCEscapeAnalyzer::initialize() { 1.1216 + int i; 1.1217 + 1.1218 + // clear escape information (method may have been deoptimized) 1.1219 + methodData()->clear_escape_info(); 1.1220 + 1.1221 + // initialize escape state of object parameters 1.1222 + ciSignature* sig = method()->signature(); 1.1223 + int j = 0; 1.1224 + if (!method()->is_static()) { 1.1225 + _arg_local.set(0); 1.1226 + _arg_stack.set(0); 1.1227 + j++; 1.1228 + } 1.1229 + for (i = 0; i < sig->count(); i++) { 1.1230 + ciType* t = sig->type_at(i); 1.1231 + if (!t->is_primitive_type()) { 1.1232 + _arg_local.set(j); 1.1233 + _arg_stack.set(j); 1.1234 + } 1.1235 + j += t->size(); 1.1236 + } 1.1237 + assert(j == _arg_size, "just checking"); 1.1238 + 1.1239 + // start with optimistic assumption 1.1240 + ciType *rt = _method->return_type(); 1.1241 + if (rt->is_primitive_type()) { 1.1242 + _return_local = false; 1.1243 + _return_allocated = false; 1.1244 + } else { 1.1245 + _return_local = true; 1.1246 + _return_allocated = true; 1.1247 + } 1.1248 + _allocated_escapes = false; 1.1249 + _unknown_modified = false; 1.1250 +} 1.1251 + 1.1252 +void BCEscapeAnalyzer::clear_escape_info() { 1.1253 + ciSignature* sig = method()->signature(); 1.1254 + int arg_count = sig->count(); 1.1255 + ArgumentMap var; 1.1256 + if (!method()->is_static()) { 1.1257 + arg_count++; // allow for "this" 1.1258 + } 1.1259 + for (int i = 0; i < arg_count; i++) { 1.1260 + set_arg_modified(i, OFFSET_ANY, 4); 1.1261 + var.clear(); 1.1262 + var.set(i); 1.1263 + set_modified(var, OFFSET_ANY, 4); 1.1264 + set_global_escape(var); 1.1265 + } 1.1266 + _arg_local.Clear(); 1.1267 + _arg_stack.Clear(); 1.1268 + _arg_returned.Clear(); 1.1269 + _return_local = false; 1.1270 + _return_allocated = false; 1.1271 + _allocated_escapes = true; 1.1272 + _unknown_modified = true; 1.1273 +} 1.1274 + 1.1275 + 1.1276 +void BCEscapeAnalyzer::compute_escape_info() { 1.1277 + int i; 1.1278 + assert(!methodData()->has_escape_info(), "do not overwrite escape info"); 1.1279 + 1.1280 + vmIntrinsics::ID iid = known_intrinsic(); 1.1281 + 1.1282 + // check if method can be analyzed 1.1283 + if (iid == vmIntrinsics::_none && (method()->is_abstract() || method()->is_native() || !method()->holder()->is_initialized() 1.1284 + || _level > MaxBCEAEstimateLevel 1.1285 + || method()->code_size() > MaxBCEAEstimateSize)) { 1.1286 + if (BCEATraceLevel >= 1) { 1.1287 + tty->print("Skipping method because: "); 1.1288 + if (method()->is_abstract()) 1.1289 + tty->print_cr("method is abstract."); 1.1290 + else if (method()->is_native()) 1.1291 + tty->print_cr("method is native."); 1.1292 + else if (!method()->holder()->is_initialized()) 1.1293 + tty->print_cr("class of method is not initialized."); 1.1294 + else if (_level > MaxBCEAEstimateLevel) 1.1295 + tty->print_cr("level (%d) exceeds MaxBCEAEstimateLevel (%d).", 1.1296 + _level, (int) MaxBCEAEstimateLevel); 1.1297 + else if (method()->code_size() > MaxBCEAEstimateSize) 1.1298 + tty->print_cr("code size (%d) exceeds MaxBCEAEstimateSize (%d).", 1.1299 + method()->code_size(), (int) MaxBCEAEstimateSize); 1.1300 + else 1.1301 + ShouldNotReachHere(); 1.1302 + } 1.1303 + clear_escape_info(); 1.1304 + 1.1305 + return; 1.1306 + } 1.1307 + 1.1308 + if (BCEATraceLevel >= 1) { 1.1309 + tty->print("[EA] estimating escape information for"); 1.1310 + if (iid != vmIntrinsics::_none) 1.1311 + tty->print(" intrinsic"); 1.1312 + method()->print_short_name(); 1.1313 + tty->print_cr(" (%d bytes)", method()->code_size()); 1.1314 + } 1.1315 + 1.1316 + bool success; 1.1317 + 1.1318 + initialize(); 1.1319 + 1.1320 + // Do not scan method if it has no object parameters and 1.1321 + // does not returns an object (_return_allocated is set in initialize()). 1.1322 + if (_arg_local.Size() == 0 && !_return_allocated) { 1.1323 + // Clear all info since method's bytecode was not analysed and 1.1324 + // set pessimistic escape information. 1.1325 + clear_escape_info(); 1.1326 + methodData()->set_eflag(MethodData::allocated_escapes); 1.1327 + methodData()->set_eflag(MethodData::unknown_modified); 1.1328 + methodData()->set_eflag(MethodData::estimated); 1.1329 + return; 1.1330 + } 1.1331 + 1.1332 + if (iid != vmIntrinsics::_none) 1.1333 + success = compute_escape_for_intrinsic(iid); 1.1334 + else { 1.1335 + success = do_analysis(); 1.1336 + } 1.1337 + 1.1338 + // don't store interprocedural escape information if it introduces 1.1339 + // dependencies or if method data is empty 1.1340 + // 1.1341 + if (!has_dependencies() && !methodData()->is_empty()) { 1.1342 + for (i = 0; i < _arg_size; i++) { 1.1343 + if (_arg_local.test(i)) { 1.1344 + assert(_arg_stack.test(i), "inconsistent escape info"); 1.1345 + methodData()->set_arg_local(i); 1.1346 + methodData()->set_arg_stack(i); 1.1347 + } else if (_arg_stack.test(i)) { 1.1348 + methodData()->set_arg_stack(i); 1.1349 + } 1.1350 + if (_arg_returned.test(i)) { 1.1351 + methodData()->set_arg_returned(i); 1.1352 + } 1.1353 + methodData()->set_arg_modified(i, _arg_modified[i]); 1.1354 + } 1.1355 + if (_return_local) { 1.1356 + methodData()->set_eflag(MethodData::return_local); 1.1357 + } 1.1358 + if (_return_allocated) { 1.1359 + methodData()->set_eflag(MethodData::return_allocated); 1.1360 + } 1.1361 + if (_allocated_escapes) { 1.1362 + methodData()->set_eflag(MethodData::allocated_escapes); 1.1363 + } 1.1364 + if (_unknown_modified) { 1.1365 + methodData()->set_eflag(MethodData::unknown_modified); 1.1366 + } 1.1367 + methodData()->set_eflag(MethodData::estimated); 1.1368 + } 1.1369 +} 1.1370 + 1.1371 +void BCEscapeAnalyzer::read_escape_info() { 1.1372 + assert(methodData()->has_escape_info(), "no escape info available"); 1.1373 + 1.1374 + // read escape information from method descriptor 1.1375 + for (int i = 0; i < _arg_size; i++) { 1.1376 + if (methodData()->is_arg_local(i)) 1.1377 + _arg_local.set(i); 1.1378 + if (methodData()->is_arg_stack(i)) 1.1379 + _arg_stack.set(i); 1.1380 + if (methodData()->is_arg_returned(i)) 1.1381 + _arg_returned.set(i); 1.1382 + _arg_modified[i] = methodData()->arg_modified(i); 1.1383 + } 1.1384 + _return_local = methodData()->eflag_set(MethodData::return_local); 1.1385 + _return_allocated = methodData()->eflag_set(MethodData::return_allocated); 1.1386 + _allocated_escapes = methodData()->eflag_set(MethodData::allocated_escapes); 1.1387 + _unknown_modified = methodData()->eflag_set(MethodData::unknown_modified); 1.1388 + 1.1389 +} 1.1390 + 1.1391 +#ifndef PRODUCT 1.1392 +void BCEscapeAnalyzer::dump() { 1.1393 + tty->print("[EA] estimated escape information for"); 1.1394 + method()->print_short_name(); 1.1395 + tty->print_cr(has_dependencies() ? " (not stored)" : ""); 1.1396 + tty->print(" non-escaping args: "); 1.1397 + _arg_local.print_on(tty); 1.1398 + tty->print(" stack-allocatable args: "); 1.1399 + _arg_stack.print_on(tty); 1.1400 + if (_return_local) { 1.1401 + tty->print(" returned args: "); 1.1402 + _arg_returned.print_on(tty); 1.1403 + } else if (is_return_allocated()) { 1.1404 + tty->print_cr(" return allocated value"); 1.1405 + } else { 1.1406 + tty->print_cr(" return non-local value"); 1.1407 + } 1.1408 + tty->print(" modified args: "); 1.1409 + for (int i = 0; i < _arg_size; i++) { 1.1410 + if (_arg_modified[i] == 0) 1.1411 + tty->print(" 0"); 1.1412 + else 1.1413 + tty->print(" 0x%x", _arg_modified[i]); 1.1414 + } 1.1415 + tty->cr(); 1.1416 + tty->print(" flags: "); 1.1417 + if (_return_allocated) 1.1418 + tty->print(" return_allocated"); 1.1419 + if (_allocated_escapes) 1.1420 + tty->print(" allocated_escapes"); 1.1421 + if (_unknown_modified) 1.1422 + tty->print(" unknown_modified"); 1.1423 + tty->cr(); 1.1424 +} 1.1425 +#endif 1.1426 + 1.1427 +BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent) 1.1428 + : _conservative(method == NULL || !EstimateArgEscape) 1.1429 + , _arena(CURRENT_ENV->arena()) 1.1430 + , _method(method) 1.1431 + , _methodData(method ? method->method_data() : NULL) 1.1432 + , _arg_size(method ? method->arg_size() : 0) 1.1433 + , _arg_local(_arena) 1.1434 + , _arg_stack(_arena) 1.1435 + , _arg_returned(_arena) 1.1436 + , _dirty(_arena) 1.1437 + , _return_local(false) 1.1438 + , _return_allocated(false) 1.1439 + , _allocated_escapes(false) 1.1440 + , _unknown_modified(false) 1.1441 + , _dependencies(_arena, 4, 0, NULL) 1.1442 + , _parent(parent) 1.1443 + , _level(parent == NULL ? 0 : parent->level() + 1) { 1.1444 + if (!_conservative) { 1.1445 + _arg_local.Clear(); 1.1446 + _arg_stack.Clear(); 1.1447 + _arg_returned.Clear(); 1.1448 + _dirty.Clear(); 1.1449 + Arena* arena = CURRENT_ENV->arena(); 1.1450 + _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint)); 1.1451 + Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint)); 1.1452 + 1.1453 + if (methodData() == NULL) 1.1454 + return; 1.1455 + bool printit = _method->should_print_assembly(); 1.1456 + if (methodData()->has_escape_info()) { 1.1457 + TRACE_BCEA(2, tty->print_cr("[EA] Reading previous results for %s.%s", 1.1458 + method->holder()->name()->as_utf8(), 1.1459 + method->name()->as_utf8())); 1.1460 + read_escape_info(); 1.1461 + } else { 1.1462 + TRACE_BCEA(2, tty->print_cr("[EA] computing results for %s.%s", 1.1463 + method->holder()->name()->as_utf8(), 1.1464 + method->name()->as_utf8())); 1.1465 + 1.1466 + compute_escape_info(); 1.1467 + methodData()->update_escape_info(); 1.1468 + } 1.1469 +#ifndef PRODUCT 1.1470 + if (BCEATraceLevel >= 3) { 1.1471 + // dump escape information 1.1472 + dump(); 1.1473 + } 1.1474 +#endif 1.1475 + } 1.1476 +} 1.1477 + 1.1478 +void BCEscapeAnalyzer::copy_dependencies(Dependencies *deps) { 1.1479 + if (ciEnv::current()->jvmti_can_hotswap_or_post_breakpoint()) { 1.1480 + // Also record evol dependencies so redefinition of the 1.1481 + // callee will trigger recompilation. 1.1482 + deps->assert_evol_method(method()); 1.1483 + } 1.1484 + for (int i = 0; i < _dependencies.length(); i+=2) { 1.1485 + ciKlass *k = _dependencies.at(i)->as_klass(); 1.1486 + ciMethod *m = _dependencies.at(i+1)->as_method(); 1.1487 + deps->assert_unique_concrete_method(k, m); 1.1488 + } 1.1489 +}