6968368: SIGSEGV in the BCEscapeAnalyzer::copy_dependencies
Summary: Use GrowableArray and VectorSet allocated in ciEnv arena.
Reviewed-by: never, twisti
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Wed Jul 14 14:29:14 2010 -0700
+++ b/hotspot/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/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp Wed Jul 14 14:29:14 2010 -0700
+++ b/hotspot/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/hotspot/src/share/vm/ci/ciMethod.cpp Wed Jul 14 14:29:14 2010 -0700
+++ b/hotspot/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/hotspot/src/share/vm/ci/ciMethod.hpp Wed Jul 14 14:29:14 2010 -0700
+++ b/hotspot/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/hotspot/src/share/vm/includeDB_compiler2 Wed Jul 14 14:29:14 2010 -0700
+++ b/hotspot/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/hotspot/src/share/vm/includeDB_core Wed Jul 14 14:29:14 2010 -0700
+++ b/hotspot/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