src/share/vm/ci/bcEscapeAnalyzer.cpp

changeset 480
48a3fa21394b
parent 435
a61af66fc99e
child 513
e1e86702e43e
     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;

mercurial