changeset 1845:8099e71601df

6968368: SIGSEGV in the BCEscapeAnalyzer::copy_dependencies Summary: Use GrowableArray and VectorSet allocated in ciEnv arena. Reviewed-by: never, twisti
author kvn
date Wed, 14 Jul 2010 14:47:34 -0700
parents 079980c86f33
children a528509c992b
files src/share/vm/ci/bcEscapeAnalyzer.cpp src/share/vm/ci/bcEscapeAnalyzer.hpp src/share/vm/ci/ciMethod.cpp src/share/vm/ci/ciMethod.hpp src/share/vm/includeDB_compiler2 src/share/vm/includeDB_core
diffstat 6 files changed, 71 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp	Wed Jul 14 14:29:14 2010 -0700
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp	Wed Jul 14 14:47:34 2010 -0700
@@ -106,7 +106,7 @@
 void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
   for (int i = 0; i < _arg_size; i++) {
     if (vars.contains(i))
-      _arg_returned.set_bit(i);
+      _arg_returned.set(i);
   }
   _return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated());
   _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
@@ -126,16 +126,16 @@
   if (_conservative)
     return true;
   for (int i = 0; i < _arg_size; i++) {
-    if (vars.contains(i) && _arg_stack.at(i))
+    if (vars.contains(i) && _arg_stack.test(i))
       return true;
   }
   return false;
 }
 
-void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) {
+void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
   for (int i = 0; i < _arg_size; i++) {
     if (vars.contains(i)) {
-      bm.clear_bit(i);
+      bm >>= i;
     }
   }
 }
@@ -1157,15 +1157,15 @@
   ciSignature* sig = method()->signature();
   int j = 0;
   if (!method()->is_static()) {
-    _arg_local.set_bit(0);
-    _arg_stack.set_bit(0);
+    _arg_local.set(0);
+    _arg_stack.set(0);
     j++;
   }
   for (i = 0; i < sig->count(); i++) {
     ciType* t = sig->type_at(i);
     if (!t->is_primitive_type()) {
-      _arg_local.set_bit(j);
-      _arg_stack.set_bit(j);
+      _arg_local.set(j);
+      _arg_stack.set(j);
     }
     j += t->size();
   }
@@ -1198,9 +1198,9 @@
     set_modified(var, OFFSET_ANY, 4);
     set_global_escape(var);
   }
-  _arg_local.clear();
-  _arg_stack.clear();
-  _arg_returned.clear();
+  _arg_local.Clear();
+  _arg_stack.Clear();
+  _arg_returned.Clear();
   _return_local = false;
   _return_allocated = false;
   _allocated_escapes = true;
@@ -1254,7 +1254,7 @@
 
   // Do not scan method if it has no object parameters and
   // does not returns an object (_return_allocated is set in initialize()).
-  if (_arg_local.is_empty() && !_return_allocated) {
+  if (_arg_local.Size() == 0 && !_return_allocated) {
     // Clear all info since method's bytecode was not analysed and
     // set pessimistic escape information.
     clear_escape_info();
@@ -1275,14 +1275,14 @@
   //
   if (!has_dependencies() && !methodData()->is_empty()) {
     for (i = 0; i < _arg_size; i++) {
-      if (_arg_local.at(i)) {
-        assert(_arg_stack.at(i), "inconsistent escape info");
+      if (_arg_local.test(i)) {
+        assert(_arg_stack.test(i), "inconsistent escape info");
         methodData()->set_arg_local(i);
         methodData()->set_arg_stack(i);
-      } else if (_arg_stack.at(i)) {
+      } else if (_arg_stack.test(i)) {
         methodData()->set_arg_stack(i);
       }
-      if (_arg_returned.at(i)) {
+      if (_arg_returned.test(i)) {
         methodData()->set_arg_returned(i);
       }
       methodData()->set_arg_modified(i, _arg_modified[i]);
@@ -1308,9 +1308,12 @@
 
   // read escape information from method descriptor
   for (int i = 0; i < _arg_size; i++) {
-    _arg_local.at_put(i, methodData()->is_arg_local(i));
-    _arg_stack.at_put(i, methodData()->is_arg_stack(i));
-    _arg_returned.at_put(i, methodData()->is_arg_returned(i));
+    if (methodData()->is_arg_local(i))
+      _arg_local.set(i);
+    if (methodData()->is_arg_stack(i))
+      _arg_stack.set(i);
+    if (methodData()->is_arg_returned(i))
+      _arg_returned.set(i);
     _arg_modified[i] = methodData()->arg_modified(i);
   }
   _return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
@@ -1358,26 +1361,26 @@
 
 BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
     : _conservative(method == NULL || !EstimateArgEscape)
+    , _arena(CURRENT_ENV->arena())
     , _method(method)
     , _methodData(method ? method->method_data() : NULL)
     , _arg_size(method ? method->arg_size() : 0)
-    , _stack()
-    , _arg_local(_arg_size)
-    , _arg_stack(_arg_size)
-    , _arg_returned(_arg_size)
-    , _dirty(_arg_size)
+    , _arg_local(_arena)
+    , _arg_stack(_arena)
+    , _arg_returned(_arena)
+    , _dirty(_arena)
     , _return_local(false)
     , _return_allocated(false)
     , _allocated_escapes(false)
     , _unknown_modified(false)
-    , _dependencies()
+    , _dependencies(_arena, 4, 0, NULL)
     , _parent(parent)
     , _level(parent == NULL ? 0 : parent->level() + 1) {
   if (!_conservative) {
-    _arg_local.clear();
-    _arg_stack.clear();
-    _arg_returned.clear();
-    _dirty.clear();
+    _arg_local.Clear();
+    _arg_stack.Clear();
+    _arg_returned.Clear();
+    _dirty.Clear();
     Arena* arena = CURRENT_ENV->arena();
     _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
     Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
@@ -1414,8 +1417,8 @@
     deps->assert_evol_method(method());
   }
   for (int i = 0; i < _dependencies.length(); i+=2) {
-    ciKlass *k = _dependencies[i]->as_klass();
-    ciMethod *m = _dependencies[i+1]->as_method();
+    ciKlass *k = _dependencies.at(i)->as_klass();
+    ciMethod *m = _dependencies.at(i+1)->as_method();
     deps->assert_unique_concrete_method(k, m);
   }
 }
--- a/src/share/vm/ci/bcEscapeAnalyzer.hpp	Wed Jul 14 14:29:14 2010 -0700
+++ b/src/share/vm/ci/bcEscapeAnalyzer.hpp	Wed Jul 14 14:47:34 2010 -0700
@@ -22,9 +22,6 @@
  *
  */
 
-define_array(ciObjectArray, ciObject*);
-define_stack(ciObjectList, ciObjectArray);
-
 // This class implements a fast, conservative analysis of effect of methods
 // on the escape state of their arguments.  The analysis is at the bytecode
 // level.
@@ -34,18 +31,17 @@
 
 class BCEscapeAnalyzer : public ResourceObj {
  private:
+  Arena*            _arena;        // ciEnv arena
+
   bool              _conservative; // If true, return maximally
                                    // conservative results.
   ciMethod*         _method;
   ciMethodData*     _methodData;
   int               _arg_size;
-
-  intStack          _stack;
-
-  BitMap            _arg_local;
-  BitMap            _arg_stack;
-  BitMap            _arg_returned;
-  BitMap            _dirty;
+  VectorSet         _arg_local;
+  VectorSet         _arg_stack;
+  VectorSet         _arg_returned;
+  VectorSet         _dirty;
   enum{ ARG_OFFSET_MAX = 31};
   uint              *_arg_modified;
 
@@ -54,7 +50,7 @@
   bool              _allocated_escapes;
   bool              _unknown_modified;
 
-  ciObjectList     _dependencies;
+  GrowableArray<ciObject *> _dependencies;
 
   ciMethodBlocks   *_methodBlocks;
 
@@ -68,20 +64,10 @@
  private:
   // helper functions
   bool is_argument(int i)    { return i >= 0 && i < _arg_size; }
-
-  void raw_push(int i)       { _stack.push(i); }
-  int  raw_pop()             { return _stack.is_empty() ? -1 : _stack.pop(); }
-  void apush(int i)          { raw_push(i); }
-  void spush()               { raw_push(-1); }
-  void lpush()               { spush(); spush(); }
-  int  apop()                { return raw_pop(); }
-  void spop()                { assert(_stack.is_empty() || _stack.top() == -1, ""); raw_pop(); }
-  void lpop()                { spop(); spop(); }
-
   void set_returned(ArgumentMap vars);
   bool is_argument(ArgumentMap vars);
   bool is_arg_stack(ArgumentMap vars);
-  void clear_bits(ArgumentMap vars, BitMap &bs);
+  void clear_bits(ArgumentMap vars, VectorSet &bs);
   void set_method_escape(ArgumentMap vars);
   void set_global_escape(ArgumentMap vars);
   void set_dirty(ArgumentMap vars);
@@ -116,25 +102,25 @@
   ciMethodData*     methodData() const           { return _methodData; }
   BCEscapeAnalyzer* parent() const               { return _parent; }
   int               level() const                { return _level; }
-  ciObjectList*     dependencies()               { return &_dependencies; }
+  GrowableArray<ciObject *>* dependencies()               { return &_dependencies; }
   bool              has_dependencies() const     { return !_dependencies.is_empty(); }
 
   // retrieval of interprocedural escape information
 
   // The given argument does not escape the callee.
   bool is_arg_local(int i) const {
-    return !_conservative && _arg_local.at(i);
+    return !_conservative && _arg_local.test(i);
   }
 
   // The given argument escapes the callee, but does not become globally
   // reachable.
   bool is_arg_stack(int i) const {
-    return !_conservative && _arg_stack.at(i);
+    return !_conservative && _arg_stack.test(i);
   }
 
   // The given argument does not escape globally, and may be returned.
   bool is_arg_returned(int i) const {
-    return !_conservative && _arg_returned.at(i); }
+    return !_conservative && _arg_returned.test(i); }
 
   // True iff only input arguments are returned.
   bool is_return_local() const {
--- a/src/share/vm/ci/ciMethod.cpp	Wed Jul 14 14:29:14 2010 -0700
+++ b/src/share/vm/ci/ciMethod.cpp	Wed Jul 14 14:47:34 2010 -0700
@@ -54,10 +54,10 @@
   _code               = NULL;
   _exception_handlers = NULL;
   _liveness           = NULL;
-  _bcea = NULL;
   _method_blocks = NULL;
 #ifdef COMPILER2
   _flow               = NULL;
+  _bcea               = NULL;
 #endif // COMPILER2
 
   ciEnv *env = CURRENT_ENV;
@@ -121,11 +121,11 @@
   _intrinsic_id = vmIntrinsics::_none;
   _liveness = NULL;
   _can_be_statically_bound = false;
-  _bcea = NULL;
   _method_blocks = NULL;
   _method_data = NULL;
 #ifdef COMPILER2
   _flow = NULL;
+  _bcea = NULL;
 #endif // COMPILER2
 }
 
@@ -1033,10 +1033,15 @@
 bool ciMethod::is_initializer () const {         FETCH_FLAG_FROM_VM(is_initializer); }
 
 BCEscapeAnalyzer  *ciMethod::get_bcea() {
+#ifdef COMPILER2
   if (_bcea == NULL) {
     _bcea = new (CURRENT_ENV->arena()) BCEscapeAnalyzer(this, NULL);
   }
   return _bcea;
+#else // COMPILER2
+  ShouldNotReachHere();
+  return NULL;
+#endif // COMPILER2
 }
 
 ciMethodBlocks  *ciMethod::get_method_blocks() {
--- a/src/share/vm/ci/ciMethod.hpp	Wed Jul 14 14:29:14 2010 -0700
+++ b/src/share/vm/ci/ciMethod.hpp	Wed Jul 14 14:47:34 2010 -0700
@@ -48,7 +48,6 @@
   ciInstanceKlass* _holder;
   ciSignature*     _signature;
   ciMethodData*    _method_data;
-  BCEscapeAnalyzer* _bcea;
   ciMethodBlocks*   _method_blocks;
 
   // Code attributes.
@@ -72,7 +71,8 @@
   // Optional liveness analyzer.
   MethodLiveness* _liveness;
 #ifdef COMPILER2
-  ciTypeFlow*     _flow;
+  ciTypeFlow*         _flow;
+  BCEscapeAnalyzer*   _bcea;
 #endif
 
   ciMethod(methodHandle h_m);
--- a/src/share/vm/includeDB_compiler2	Wed Jul 14 14:29:14 2010 -0700
+++ b/src/share/vm/includeDB_compiler2	Wed Jul 14 14:47:34 2010 -0700
@@ -89,6 +89,21 @@
 
 allocation.hpp                          c2_globals.hpp
 
+bcEscapeAnalyzer.cpp                    bcEscapeAnalyzer.hpp
+bcEscapeAnalyzer.cpp                    bitMap.inline.hpp
+bcEscapeAnalyzer.cpp                    bytecode.hpp
+bcEscapeAnalyzer.cpp                    ciConstant.hpp
+bcEscapeAnalyzer.cpp                    ciField.hpp
+bcEscapeAnalyzer.cpp                    ciMethodBlocks.hpp
+bcEscapeAnalyzer.cpp                    ciStreams.hpp
+
+bcEscapeAnalyzer.hpp                    allocation.hpp
+bcEscapeAnalyzer.hpp                    ciMethod.hpp
+bcEscapeAnalyzer.hpp                    ciMethodData.hpp
+bcEscapeAnalyzer.hpp                    dependencies.hpp
+bcEscapeAnalyzer.hpp                    growableArray.hpp
+bcEscapeAnalyzer.hpp                    vectset.hpp
+
 block.cpp                               allocation.inline.hpp
 block.cpp                               block.hpp
 block.cpp                               cfgnode.hpp
@@ -239,6 +254,7 @@
 ciEnv.cpp                               compileLog.hpp
 ciEnv.cpp                               runtime.hpp
 
+ciMethod.cpp                            bcEscapeAnalyzer.hpp
 ciMethod.cpp                            ciTypeFlow.hpp
 ciMethod.cpp                            methodOop.hpp
 
--- a/src/share/vm/includeDB_core	Wed Jul 14 14:29:14 2010 -0700
+++ b/src/share/vm/includeDB_core	Wed Jul 14 14:47:34 2010 -0700
@@ -301,20 +301,6 @@
 barrierSet.inline.hpp                   barrierSet.hpp
 barrierSet.inline.hpp                   cardTableModRefBS.hpp
 
-bcEscapeAnalyzer.cpp                    bcEscapeAnalyzer.hpp
-bcEscapeAnalyzer.cpp                    bitMap.inline.hpp
-bcEscapeAnalyzer.cpp                    bytecode.hpp
-bcEscapeAnalyzer.cpp                    ciConstant.hpp
-bcEscapeAnalyzer.cpp                    ciField.hpp
-bcEscapeAnalyzer.cpp                    ciMethodBlocks.hpp
-bcEscapeAnalyzer.cpp                    ciStreams.hpp
-
-bcEscapeAnalyzer.hpp                    allocation.hpp
-bcEscapeAnalyzer.hpp                    ciMethod.hpp
-bcEscapeAnalyzer.hpp                    ciMethodData.hpp
-bcEscapeAnalyzer.hpp                    dependencies.hpp
-bcEscapeAnalyzer.hpp                    growableArray.hpp
-
 biasedLocking.cpp                       biasedLocking.hpp
 biasedLocking.cpp                       klass.inline.hpp
 biasedLocking.cpp                       markOop.hpp
@@ -665,7 +651,6 @@
 
 ciMethod.cpp                            abstractCompiler.hpp
 ciMethod.cpp                            allocation.inline.hpp
-ciMethod.cpp                            bcEscapeAnalyzer.hpp
 ciMethod.cpp                            bitMap.inline.hpp
 ciMethod.cpp                            ciCallProfile.hpp
 ciMethod.cpp                            ciExceptionHandler.hpp