From c5224ef90a6c28a25e872179154ecbeffe46afc4 Mon Sep 17 00:00:00 2001 From: kvn Date: Wed, 14 Jul 2010 14:47:34 -0700 Subject: [PATCH] 6968368: SIGSEGV in the BCEscapeAnalyzer::copy_dependencies Summary: Use GrowableArray and VectorSet allocated in ciEnv arena. Reviewed-by: never, twisti --- src/share/vm/ci/bcEscapeAnalyzer.cpp | 65 +++++++++++++++------------- src/share/vm/ci/bcEscapeAnalyzer.hpp | 38 +++++----------- src/share/vm/ci/ciMethod.cpp | 9 +++- src/share/vm/ci/ciMethod.hpp | 4 +- src/share/vm/includeDB_compiler2 | 16 +++++++ src/share/vm/includeDB_core | 15 ------- 6 files changed, 71 insertions(+), 76 deletions(-) diff --git a/src/share/vm/ci/bcEscapeAnalyzer.cpp b/src/share/vm/ci/bcEscapeAnalyzer.cpp index 49f08d642..6642271cb 100644 --- a/src/share/vm/ci/bcEscapeAnalyzer.cpp +++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp @@ -106,7 +106,7 @@ public: 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 @@ bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ 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 @@ void BCEscapeAnalyzer::initialize() { 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 @@ void BCEscapeAnalyzer::clear_escape_info() { 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 @@ void BCEscapeAnalyzer::compute_escape_info() { // 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 @@ void BCEscapeAnalyzer::compute_escape_info() { // 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 @@ void BCEscapeAnalyzer::read_escape_info() { // 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 @@ void BCEscapeAnalyzer::dump() { 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 @@ void BCEscapeAnalyzer::copy_dependencies(Dependencies *deps) { 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); } } diff --git a/src/share/vm/ci/bcEscapeAnalyzer.hpp b/src/share/vm/ci/bcEscapeAnalyzer.hpp index fc6ce466e..5e61112c7 100644 --- a/src/share/vm/ci/bcEscapeAnalyzer.hpp +++ b/src/share/vm/ci/bcEscapeAnalyzer.hpp @@ -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 ciBlock; 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 @@ class BCEscapeAnalyzer : public ResourceObj { bool _allocated_escapes; bool _unknown_modified; - ciObjectList _dependencies; + GrowableArray _dependencies; ciMethodBlocks *_methodBlocks; @@ -68,20 +64,10 @@ class BCEscapeAnalyzer : public ResourceObj { 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 @@ class BCEscapeAnalyzer : public ResourceObj { ciMethodData* methodData() const { return _methodData; } BCEscapeAnalyzer* parent() const { return _parent; } int level() const { return _level; } - ciObjectList* dependencies() { return &_dependencies; } + GrowableArray* 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 { diff --git a/src/share/vm/ci/ciMethod.cpp b/src/share/vm/ci/ciMethod.cpp index 189b55104..22fc4f5fb 100644 --- a/src/share/vm/ci/ciMethod.cpp +++ b/src/share/vm/ci/ciMethod.cpp @@ -54,10 +54,10 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) { _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 @@ ciMethod::ciMethod(ciInstanceKlass* holder, _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_accessor () const { FETCH_FLAG_FROM_VM(is_accessor) 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() { diff --git a/src/share/vm/ci/ciMethod.hpp b/src/share/vm/ci/ciMethod.hpp index c8bbcc91d..7d94b46b7 100644 --- a/src/share/vm/ci/ciMethod.hpp +++ b/src/share/vm/ci/ciMethod.hpp @@ -48,7 +48,6 @@ class ciMethod : public ciObject { ciInstanceKlass* _holder; ciSignature* _signature; ciMethodData* _method_data; - BCEscapeAnalyzer* _bcea; ciMethodBlocks* _method_blocks; // Code attributes. @@ -72,7 +71,8 @@ class ciMethod : public ciObject { // Optional liveness analyzer. MethodLiveness* _liveness; #ifdef COMPILER2 - ciTypeFlow* _flow; + ciTypeFlow* _flow; + BCEscapeAnalyzer* _bcea; #endif ciMethod(methodHandle h_m); diff --git a/src/share/vm/includeDB_compiler2 b/src/share/vm/includeDB_compiler2 index 655c3169c..a7695d75c 100644 --- a/src/share/vm/includeDB_compiler2 +++ b/src/share/vm/includeDB_compiler2 @@ -89,6 +89,21 @@ adlcVMDeps.hpp allocation.hpp 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 @@ chaitin_.cpp machnode.hpp ciEnv.cpp compileLog.hpp ciEnv.cpp runtime.hpp +ciMethod.cpp bcEscapeAnalyzer.hpp ciMethod.cpp ciTypeFlow.hpp ciMethod.cpp methodOop.hpp diff --git a/src/share/vm/includeDB_core b/src/share/vm/includeDB_core index 06d1217fe..3e9089f24 100644 --- a/src/share/vm/includeDB_core +++ b/src/share/vm/includeDB_core @@ -301,20 +301,6 @@ barrierSet.hpp oopsHierarchy.hpp 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 @@ ciKlassKlass.hpp ciSymbol.hpp 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 -- GitLab