1.1 --- a/src/share/vm/ci/bcEscapeAnalyzer.cpp Tue Mar 11 11:25:13 2008 -0700 1.2 +++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp Tue Mar 11 19:00:38 2008 -0700 1.3 @@ -104,7 +104,7 @@ 1.4 }; 1.5 1.6 void BCEscapeAnalyzer::set_returned(ArgumentMap vars) { 1.7 - for (int i = 0; i <= _arg_size; i++) { 1.8 + for (int i = 0; i < _arg_size; i++) { 1.9 if (vars.contains(i)) 1.10 _arg_returned.set_bit(i); 1.11 } 1.12 @@ -112,10 +112,9 @@ 1.13 _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars()); 1.14 } 1.15 1.16 - 1.17 // return true if any element of vars is an argument 1.18 bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) { 1.19 - for (int i = 0; i <= _arg_size; i++) { 1.20 + for (int i = 0; i < _arg_size; i++) { 1.21 if (vars.contains(i)) 1.22 return true; 1.23 } 1.24 @@ -126,7 +125,7 @@ 1.25 bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ 1.26 if (_conservative) 1.27 return true; 1.28 - for (int i = 0; i <= _arg_size; i++) { 1.29 + for (int i = 0; i < _arg_size; i++) { 1.30 if (vars.contains(i) && _arg_stack.at(i)) 1.31 return true; 1.32 } 1.33 @@ -134,12 +133,13 @@ 1.34 } 1.35 1.36 void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) { 1.37 - for (int i = 0; i <= _arg_size; i++) { 1.38 + for (int i = 0; i < _arg_size; i++) { 1.39 if (vars.contains(i)) { 1.40 bm.clear_bit(i); 1.41 } 1.42 } 1.43 } 1.44 + 1.45 void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) { 1.46 clear_bits(vars, _arg_local); 1.47 } 1.48 @@ -155,6 +155,17 @@ 1.49 clear_bits(vars, _dirty); 1.50 } 1.51 1.52 +void BCEscapeAnalyzer::set_modified(ArgumentMap vars, int offs, int size) { 1.53 + 1.54 + for (int i = 0; i < _arg_size; i++) { 1.55 + if (vars.contains(i)) { 1.56 + set_arg_modified(i, offs, size); 1.57 + } 1.58 + } 1.59 + if (vars.contains_unknown()) 1.60 + _unknown_modified = true; 1.61 +} 1.62 + 1.63 bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) { 1.64 for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) { 1.65 if (scope->method() == callee) { 1.66 @@ -164,6 +175,40 @@ 1.67 return false; 1.68 } 1.69 1.70 +bool BCEscapeAnalyzer::is_arg_modified(int arg, int offset, int size_in_bytes) { 1.71 + if (offset == OFFSET_ANY) 1.72 + return _arg_modified[arg] != 0; 1.73 + assert(arg >= 0 && arg < _arg_size, "must be an argument."); 1.74 + bool modified = false; 1.75 + int l = offset / HeapWordSize; 1.76 + int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize; 1.77 + if (l > ARG_OFFSET_MAX) 1.78 + l = ARG_OFFSET_MAX; 1.79 + if (h > ARG_OFFSET_MAX+1) 1.80 + h = ARG_OFFSET_MAX + 1; 1.81 + for (int i = l; i < h; i++) { 1.82 + modified = modified || (_arg_modified[arg] & (1 << i)) != 0; 1.83 + } 1.84 + return modified; 1.85 +} 1.86 + 1.87 +void BCEscapeAnalyzer::set_arg_modified(int arg, int offset, int size_in_bytes) { 1.88 + if (offset == OFFSET_ANY) { 1.89 + _arg_modified[arg] = (uint) -1; 1.90 + return; 1.91 + } 1.92 + assert(arg >= 0 && arg < _arg_size, "must be an argument."); 1.93 + int l = offset / HeapWordSize; 1.94 + int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize; 1.95 + if (l > ARG_OFFSET_MAX) 1.96 + l = ARG_OFFSET_MAX; 1.97 + if (h > ARG_OFFSET_MAX+1) 1.98 + h = ARG_OFFSET_MAX + 1; 1.99 + for (int i = l; i < h; i++) { 1.100 + _arg_modified[arg] |= (1 << i); 1.101 + } 1.102 +} 1.103 + 1.104 void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) { 1.105 int i; 1.106 1.107 @@ -197,6 +242,7 @@ 1.108 for (i = 0; i < arg_size; i++) { 1.109 set_method_escape(state.raw_pop()); 1.110 } 1.111 + _unknown_modified = true; // assume the worst since we don't analyze the called method 1.112 return; 1.113 } 1.114 1.115 @@ -224,6 +270,11 @@ 1.116 ArgumentMap arg = state.raw_pop(); 1.117 if (!is_argument(arg)) 1.118 continue; 1.119 + for (int j = 0; j < _arg_size; j++) { 1.120 + if (arg.contains(j)) { 1.121 + _arg_modified[j] |= analyzer._arg_modified[i]; 1.122 + } 1.123 + } 1.124 if (!is_arg_stack(arg)) { 1.125 // arguments have already been recognized as escaping 1.126 } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) { 1.127 @@ -233,6 +284,7 @@ 1.128 set_global_escape(arg); 1.129 } 1.130 } 1.131 + _unknown_modified = _unknown_modified || analyzer.has_non_arg_side_affects(); 1.132 1.133 // record dependencies if at least one parameter retained stack-allocatable 1.134 if (must_record_dependencies) { 1.135 @@ -250,8 +302,10 @@ 1.136 ArgumentMap arg = state.raw_pop(); 1.137 if (!is_argument(arg)) 1.138 continue; 1.139 + set_modified(arg, OFFSET_ANY, type2size[T_INT]*HeapWordSize); 1.140 set_global_escape(arg); 1.141 } 1.142 + _unknown_modified = true; // assume the worst since we don't know the called method 1.143 } 1.144 } 1.145 1.146 @@ -421,6 +475,7 @@ 1.147 state.spop(); 1.148 ArgumentMap arr = state.apop(); 1.149 set_method_escape(arr); 1.150 + set_modified(arr, OFFSET_ANY, type2size[T_INT]*HeapWordSize); 1.151 break; 1.152 } 1.153 case Bytecodes::_lastore: 1.154 @@ -430,6 +485,7 @@ 1.155 state.spop(); 1.156 ArgumentMap arr = state.apop(); 1.157 set_method_escape(arr); 1.158 + set_modified(arr, OFFSET_ANY, type2size[T_LONG]*HeapWordSize); 1.159 break; 1.160 } 1.161 case Bytecodes::_aastore: 1.162 @@ -437,6 +493,7 @@ 1.163 set_global_escape(state.apop()); 1.164 state.spop(); 1.165 ArgumentMap arr = state.apop(); 1.166 + set_modified(arr, OFFSET_ANY, type2size[T_OBJECT]*HeapWordSize); 1.167 break; 1.168 } 1.169 case Bytecodes::_pop: 1.170 @@ -762,6 +819,7 @@ 1.171 if (s.cur_bc() != Bytecodes::_putstatic) { 1.172 ArgumentMap p = state.apop(); 1.173 set_method_escape(p); 1.174 + set_modified(p, will_link ? field->offset() : OFFSET_ANY, type2size[field_type]*HeapWordSize); 1.175 } 1.176 } 1.177 break; 1.178 @@ -872,7 +930,7 @@ 1.179 } 1.180 1.181 void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) { 1.182 - StateInfo *d_state = blockstates+dest->index(); 1.183 + StateInfo *d_state = blockstates + dest->index(); 1.184 int nlocals = _method->max_locals(); 1.185 1.186 // exceptions may cause transfer of control to handlers in the middle of a 1.187 @@ -916,6 +974,7 @@ 1.188 } 1.189 for (int i = 0; i < s_state->_stack_height; i++) { 1.190 ArgumentMap t; 1.191 + //extra_vars |= !d_state->_vars[i] & s_state->_vars[i]; 1.192 t.clear(); 1.193 t = s_state->_stack[i]; 1.194 t.set_difference(d_state->_stack[i]); 1.195 @@ -933,7 +992,7 @@ 1.196 1.197 int datacount = (numblocks + 1) * (stkSize + numLocals); 1.198 int datasize = datacount * sizeof(ArgumentMap); 1.199 - StateInfo *blockstates = (StateInfo *) arena->Amalloc(_methodBlocks->num_blocks() * sizeof(StateInfo)); 1.200 + StateInfo *blockstates = (StateInfo *) arena->Amalloc(numblocks * sizeof(StateInfo)); 1.201 ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize); 1.202 for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap(); 1.203 ArgumentMap *dp = statedata; 1.204 @@ -961,33 +1020,35 @@ 1.205 ArgumentMap allVars; // all oop arguments to method 1.206 ciSignature* sig = method()->signature(); 1.207 int j = 0; 1.208 + ciBlock* first_blk = _methodBlocks->block_containing(0); 1.209 + int fb_i = first_blk->index(); 1.210 if (!method()->is_static()) { 1.211 // record information for "this" 1.212 - blockstates[0]._vars[j].set(j); 1.213 + blockstates[fb_i]._vars[j].set(j); 1.214 allVars.add(j); 1.215 j++; 1.216 } 1.217 for (int i = 0; i < sig->count(); i++) { 1.218 ciType* t = sig->type_at(i); 1.219 if (!t->is_primitive_type()) { 1.220 - blockstates[0]._vars[j].set(j); 1.221 + blockstates[fb_i]._vars[j].set(j); 1.222 allVars.add(j); 1.223 } 1.224 j += t->size(); 1.225 } 1.226 - blockstates[0]._initialized = true; 1.227 + blockstates[fb_i]._initialized = true; 1.228 assert(j == _arg_size, "just checking"); 1.229 1.230 ArgumentMap unknown_map; 1.231 unknown_map.add_unknown(); 1.232 1.233 - worklist.push(_methodBlocks->block_containing(0)); 1.234 + worklist.push(first_blk); 1.235 while(worklist.length() > 0) { 1.236 ciBlock *blk = worklist.pop(); 1.237 - StateInfo *blkState = blockstates+blk->index(); 1.238 + StateInfo *blkState = blockstates + blk->index(); 1.239 if (blk->is_handler() || blk->is_ret_target()) { 1.240 // for an exception handler or a target of a ret instruction, we assume the worst case, 1.241 - // that any variable or stack slot could contain any argument 1.242 + // that any variable could contain any argument 1.243 for (int i = 0; i < numLocals; i++) { 1.244 state._vars[i] = allVars; 1.245 } 1.246 @@ -997,6 +1058,7 @@ 1.247 state._stack_height = blkState->_stack_height; 1.248 } 1.249 for (int i = 0; i < state._stack_height; i++) { 1.250 +// ??? should this be unknown_map ??? 1.251 state._stack[i] = allVars; 1.252 } 1.253 } else { 1.254 @@ -1053,6 +1115,7 @@ 1.255 vmIntrinsics::ID iid = method()->intrinsic_id(); 1.256 1.257 if (iid == vmIntrinsics::_getClass || 1.258 + iid == vmIntrinsics::_fillInStackTrace || 1.259 iid == vmIntrinsics::_hashCode) 1.260 return iid; 1.261 else 1.262 @@ -1060,12 +1123,16 @@ 1.263 } 1.264 1.265 bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) { 1.266 - ArgumentMap empty; 1.267 - empty.clear(); 1.268 + ArgumentMap arg; 1.269 + arg.clear(); 1.270 switch (iid) { 1.271 case vmIntrinsics::_getClass: 1.272 _return_local = false; 1.273 break; 1.274 + case vmIntrinsics::_fillInStackTrace: 1.275 + arg.set(0); // 'this' 1.276 + set_returned(arg); 1.277 + break; 1.278 case vmIntrinsics::_hashCode: 1.279 // initialized state is correct 1.280 break; 1.281 @@ -1109,15 +1176,21 @@ 1.282 _return_allocated = true; 1.283 } 1.284 _allocated_escapes = false; 1.285 + _unknown_modified = false; 1.286 } 1.287 1.288 void BCEscapeAnalyzer::clear_escape_info() { 1.289 ciSignature* sig = method()->signature(); 1.290 int arg_count = sig->count(); 1.291 ArgumentMap var; 1.292 + if (!method()->is_static()) { 1.293 + arg_count++; // allow for "this" 1.294 + } 1.295 for (int i = 0; i < arg_count; i++) { 1.296 + set_arg_modified(i, OFFSET_ANY, 4); 1.297 var.clear(); 1.298 var.set(i); 1.299 + set_modified(var, OFFSET_ANY, 4); 1.300 set_global_escape(var); 1.301 } 1.302 _arg_local.clear(); 1.303 @@ -1126,6 +1199,7 @@ 1.304 _return_local = false; 1.305 _return_allocated = false; 1.306 _allocated_escapes = true; 1.307 + _unknown_modified = true; 1.308 } 1.309 1.310 1.311 @@ -1205,8 +1279,17 @@ 1.312 } else { 1.313 tty->print_cr(" non-local return values"); 1.314 } 1.315 + tty->print(" modified args: "); 1.316 + for (int i = 0; i < _arg_size; i++) { 1.317 + if (_arg_modified[i] == 0) 1.318 + tty->print(" 0"); 1.319 + else 1.320 + tty->print(" 0x%x", _arg_modified[i]); 1.321 + } 1.322 tty->cr(); 1.323 tty->print(" flags: "); 1.324 + if (_unknown_modified) 1.325 + tty->print(" unknown_modified"); 1.326 if (_return_allocated) 1.327 tty->print(" return_allocated"); 1.328 tty->cr(); 1.329 @@ -1228,6 +1311,7 @@ 1.330 if (_arg_returned.at(i)) { 1.331 methodData()->set_arg_returned(i); 1.332 } 1.333 + methodData()->set_arg_modified(i, _arg_modified[i]); 1.334 } 1.335 if (_return_local) { 1.336 methodData()->set_eflag(methodDataOopDesc::return_local); 1.337 @@ -1244,6 +1328,7 @@ 1.338 _arg_local.at_put(i, methodData()->is_arg_local(i)); 1.339 _arg_stack.at_put(i, methodData()->is_arg_stack(i)); 1.340 _arg_returned.at_put(i, methodData()->is_arg_returned(i)); 1.341 + _arg_modified[i] = methodData()->arg_modified(i); 1.342 } 1.343 _return_local = methodData()->eflag_set(methodDataOopDesc::return_local); 1.344 1.345 @@ -1261,6 +1346,12 @@ 1.346 tty->print_cr(" non-local return values"); 1.347 } 1.348 tty->print(" modified args: "); 1.349 + for (int i = 0; i < _arg_size; i++) { 1.350 + if (_arg_modified[i] == 0) 1.351 + tty->print(" 0"); 1.352 + else 1.353 + tty->print(" 0x%x", _arg_modified[i]); 1.354 + } 1.355 tty->cr(); 1.356 } 1.357 #endif 1.358 @@ -1281,6 +1372,7 @@ 1.359 , _return_local(false) 1.360 , _return_allocated(false) 1.361 , _allocated_escapes(false) 1.362 + , _unknown_modified(false) 1.363 , _dependencies() 1.364 , _parent(parent) 1.365 , _level(parent == NULL ? 0 : parent->level() + 1) { 1.366 @@ -1290,6 +1382,8 @@ 1.367 _arg_returned.clear(); 1.368 _dirty.clear(); 1.369 Arena* arena = CURRENT_ENV->arena(); 1.370 + _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint)); 1.371 + Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint)); 1.372 1.373 if (methodData() == NULL) 1.374 return;