提交 c5224ef9 编写于 作者: K kvn

6968368: SIGSEGV in the BCEscapeAnalyzer::copy_dependencies

Summary: Use GrowableArray and VectorSet allocated in ciEnv arena.
Reviewed-by: never, twisti
上级 8dfee536
...@@ -106,7 +106,7 @@ public: ...@@ -106,7 +106,7 @@ public:
void BCEscapeAnalyzer::set_returned(ArgumentMap vars) { void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
for (int i = 0; i < _arg_size; i++) { for (int i = 0; i < _arg_size; i++) {
if (vars.contains(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_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated());
_return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars()); _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
...@@ -126,16 +126,16 @@ bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ ...@@ -126,16 +126,16 @@ bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){
if (_conservative) if (_conservative)
return true; return true;
for (int i = 0; i < _arg_size; i++) { 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 true;
} }
return false; 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++) { for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i)) { if (vars.contains(i)) {
bm.clear_bit(i); bm >>= i;
} }
} }
} }
...@@ -1157,15 +1157,15 @@ void BCEscapeAnalyzer::initialize() { ...@@ -1157,15 +1157,15 @@ void BCEscapeAnalyzer::initialize() {
ciSignature* sig = method()->signature(); ciSignature* sig = method()->signature();
int j = 0; int j = 0;
if (!method()->is_static()) { if (!method()->is_static()) {
_arg_local.set_bit(0); _arg_local.set(0);
_arg_stack.set_bit(0); _arg_stack.set(0);
j++; j++;
} }
for (i = 0; i < sig->count(); i++) { for (i = 0; i < sig->count(); i++) {
ciType* t = sig->type_at(i); ciType* t = sig->type_at(i);
if (!t->is_primitive_type()) { if (!t->is_primitive_type()) {
_arg_local.set_bit(j); _arg_local.set(j);
_arg_stack.set_bit(j); _arg_stack.set(j);
} }
j += t->size(); j += t->size();
} }
...@@ -1198,9 +1198,9 @@ void BCEscapeAnalyzer::clear_escape_info() { ...@@ -1198,9 +1198,9 @@ void BCEscapeAnalyzer::clear_escape_info() {
set_modified(var, OFFSET_ANY, 4); set_modified(var, OFFSET_ANY, 4);
set_global_escape(var); set_global_escape(var);
} }
_arg_local.clear(); _arg_local.Clear();
_arg_stack.clear(); _arg_stack.Clear();
_arg_returned.clear(); _arg_returned.Clear();
_return_local = false; _return_local = false;
_return_allocated = false; _return_allocated = false;
_allocated_escapes = true; _allocated_escapes = true;
...@@ -1254,7 +1254,7 @@ void BCEscapeAnalyzer::compute_escape_info() { ...@@ -1254,7 +1254,7 @@ void BCEscapeAnalyzer::compute_escape_info() {
// Do not scan method if it has no object parameters and // Do not scan method if it has no object parameters and
// does not returns an object (_return_allocated is set in initialize()). // 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 // Clear all info since method's bytecode was not analysed and
// set pessimistic escape information. // set pessimistic escape information.
clear_escape_info(); clear_escape_info();
...@@ -1275,14 +1275,14 @@ void BCEscapeAnalyzer::compute_escape_info() { ...@@ -1275,14 +1275,14 @@ void BCEscapeAnalyzer::compute_escape_info() {
// //
if (!has_dependencies() && !methodData()->is_empty()) { if (!has_dependencies() && !methodData()->is_empty()) {
for (i = 0; i < _arg_size; i++) { for (i = 0; i < _arg_size; i++) {
if (_arg_local.at(i)) { if (_arg_local.test(i)) {
assert(_arg_stack.at(i), "inconsistent escape info"); assert(_arg_stack.test(i), "inconsistent escape info");
methodData()->set_arg_local(i); methodData()->set_arg_local(i);
methodData()->set_arg_stack(i); methodData()->set_arg_stack(i);
} else if (_arg_stack.at(i)) { } else if (_arg_stack.test(i)) {
methodData()->set_arg_stack(i); methodData()->set_arg_stack(i);
} }
if (_arg_returned.at(i)) { if (_arg_returned.test(i)) {
methodData()->set_arg_returned(i); methodData()->set_arg_returned(i);
} }
methodData()->set_arg_modified(i, _arg_modified[i]); methodData()->set_arg_modified(i, _arg_modified[i]);
...@@ -1308,9 +1308,12 @@ void BCEscapeAnalyzer::read_escape_info() { ...@@ -1308,9 +1308,12 @@ void BCEscapeAnalyzer::read_escape_info() {
// read escape information from method descriptor // read escape information from method descriptor
for (int i = 0; i < _arg_size; i++) { for (int i = 0; i < _arg_size; i++) {
_arg_local.at_put(i, methodData()->is_arg_local(i)); if (methodData()->is_arg_local(i))
_arg_stack.at_put(i, methodData()->is_arg_stack(i)); _arg_local.set(i);
_arg_returned.at_put(i, methodData()->is_arg_returned(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); _arg_modified[i] = methodData()->arg_modified(i);
} }
_return_local = methodData()->eflag_set(methodDataOopDesc::return_local); _return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
...@@ -1358,26 +1361,26 @@ void BCEscapeAnalyzer::dump() { ...@@ -1358,26 +1361,26 @@ void BCEscapeAnalyzer::dump() {
BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent) BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
: _conservative(method == NULL || !EstimateArgEscape) : _conservative(method == NULL || !EstimateArgEscape)
, _arena(CURRENT_ENV->arena())
, _method(method) , _method(method)
, _methodData(method ? method->method_data() : NULL) , _methodData(method ? method->method_data() : NULL)
, _arg_size(method ? method->arg_size() : 0) , _arg_size(method ? method->arg_size() : 0)
, _stack() , _arg_local(_arena)
, _arg_local(_arg_size) , _arg_stack(_arena)
, _arg_stack(_arg_size) , _arg_returned(_arena)
, _arg_returned(_arg_size) , _dirty(_arena)
, _dirty(_arg_size)
, _return_local(false) , _return_local(false)
, _return_allocated(false) , _return_allocated(false)
, _allocated_escapes(false) , _allocated_escapes(false)
, _unknown_modified(false) , _unknown_modified(false)
, _dependencies() , _dependencies(_arena, 4, 0, NULL)
, _parent(parent) , _parent(parent)
, _level(parent == NULL ? 0 : parent->level() + 1) { , _level(parent == NULL ? 0 : parent->level() + 1) {
if (!_conservative) { if (!_conservative) {
_arg_local.clear(); _arg_local.Clear();
_arg_stack.clear(); _arg_stack.Clear();
_arg_returned.clear(); _arg_returned.Clear();
_dirty.clear(); _dirty.Clear();
Arena* arena = CURRENT_ENV->arena(); Arena* arena = CURRENT_ENV->arena();
_arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint)); _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint)); Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
...@@ -1414,8 +1417,8 @@ void BCEscapeAnalyzer::copy_dependencies(Dependencies *deps) { ...@@ -1414,8 +1417,8 @@ void BCEscapeAnalyzer::copy_dependencies(Dependencies *deps) {
deps->assert_evol_method(method()); deps->assert_evol_method(method());
} }
for (int i = 0; i < _dependencies.length(); i+=2) { for (int i = 0; i < _dependencies.length(); i+=2) {
ciKlass *k = _dependencies[i]->as_klass(); ciKlass *k = _dependencies.at(i)->as_klass();
ciMethod *m = _dependencies[i+1]->as_method(); ciMethod *m = _dependencies.at(i+1)->as_method();
deps->assert_unique_concrete_method(k, m); deps->assert_unique_concrete_method(k, m);
} }
} }
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
* *
*/ */
define_array(ciObjectArray, ciObject*);
define_stack(ciObjectList, ciObjectArray);
// This class implements a fast, conservative analysis of effect of methods // This class implements a fast, conservative analysis of effect of methods
// on the escape state of their arguments. The analysis is at the bytecode // on the escape state of their arguments. The analysis is at the bytecode
// level. // level.
...@@ -34,18 +31,17 @@ class ciBlock; ...@@ -34,18 +31,17 @@ class ciBlock;
class BCEscapeAnalyzer : public ResourceObj { class BCEscapeAnalyzer : public ResourceObj {
private: private:
Arena* _arena; // ciEnv arena
bool _conservative; // If true, return maximally bool _conservative; // If true, return maximally
// conservative results. // conservative results.
ciMethod* _method; ciMethod* _method;
ciMethodData* _methodData; ciMethodData* _methodData;
int _arg_size; int _arg_size;
VectorSet _arg_local;
intStack _stack; VectorSet _arg_stack;
VectorSet _arg_returned;
BitMap _arg_local; VectorSet _dirty;
BitMap _arg_stack;
BitMap _arg_returned;
BitMap _dirty;
enum{ ARG_OFFSET_MAX = 31}; enum{ ARG_OFFSET_MAX = 31};
uint *_arg_modified; uint *_arg_modified;
...@@ -54,7 +50,7 @@ class BCEscapeAnalyzer : public ResourceObj { ...@@ -54,7 +50,7 @@ class BCEscapeAnalyzer : public ResourceObj {
bool _allocated_escapes; bool _allocated_escapes;
bool _unknown_modified; bool _unknown_modified;
ciObjectList _dependencies; GrowableArray<ciObject *> _dependencies;
ciMethodBlocks *_methodBlocks; ciMethodBlocks *_methodBlocks;
...@@ -68,20 +64,10 @@ class BCEscapeAnalyzer : public ResourceObj { ...@@ -68,20 +64,10 @@ class BCEscapeAnalyzer : public ResourceObj {
private: private:
// helper functions // helper functions
bool is_argument(int i) { return i >= 0 && i < _arg_size; } 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); void set_returned(ArgumentMap vars);
bool is_argument(ArgumentMap vars); bool is_argument(ArgumentMap vars);
bool is_arg_stack(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_method_escape(ArgumentMap vars);
void set_global_escape(ArgumentMap vars); void set_global_escape(ArgumentMap vars);
void set_dirty(ArgumentMap vars); void set_dirty(ArgumentMap vars);
...@@ -116,25 +102,25 @@ class BCEscapeAnalyzer : public ResourceObj { ...@@ -116,25 +102,25 @@ class BCEscapeAnalyzer : public ResourceObj {
ciMethodData* methodData() const { return _methodData; } ciMethodData* methodData() const { return _methodData; }
BCEscapeAnalyzer* parent() const { return _parent; } BCEscapeAnalyzer* parent() const { return _parent; }
int level() const { return _level; } int level() const { return _level; }
ciObjectList* dependencies() { return &_dependencies; } GrowableArray<ciObject *>* dependencies() { return &_dependencies; }
bool has_dependencies() const { return !_dependencies.is_empty(); } bool has_dependencies() const { return !_dependencies.is_empty(); }
// retrieval of interprocedural escape information // retrieval of interprocedural escape information
// The given argument does not escape the callee. // The given argument does not escape the callee.
bool is_arg_local(int i) const { 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 // The given argument escapes the callee, but does not become globally
// reachable. // reachable.
bool is_arg_stack(int i) const { 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. // The given argument does not escape globally, and may be returned.
bool is_arg_returned(int i) const { 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. // True iff only input arguments are returned.
bool is_return_local() const { bool is_return_local() const {
......
...@@ -54,10 +54,10 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) { ...@@ -54,10 +54,10 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
_code = NULL; _code = NULL;
_exception_handlers = NULL; _exception_handlers = NULL;
_liveness = NULL; _liveness = NULL;
_bcea = NULL;
_method_blocks = NULL; _method_blocks = NULL;
#ifdef COMPILER2 #ifdef COMPILER2
_flow = NULL; _flow = NULL;
_bcea = NULL;
#endif // COMPILER2 #endif // COMPILER2
ciEnv *env = CURRENT_ENV; ciEnv *env = CURRENT_ENV;
...@@ -121,11 +121,11 @@ ciMethod::ciMethod(ciInstanceKlass* holder, ...@@ -121,11 +121,11 @@ ciMethod::ciMethod(ciInstanceKlass* holder,
_intrinsic_id = vmIntrinsics::_none; _intrinsic_id = vmIntrinsics::_none;
_liveness = NULL; _liveness = NULL;
_can_be_statically_bound = false; _can_be_statically_bound = false;
_bcea = NULL;
_method_blocks = NULL; _method_blocks = NULL;
_method_data = NULL; _method_data = NULL;
#ifdef COMPILER2 #ifdef COMPILER2
_flow = NULL; _flow = NULL;
_bcea = NULL;
#endif // COMPILER2 #endif // COMPILER2
} }
...@@ -1033,10 +1033,15 @@ bool ciMethod::is_accessor () const { FETCH_FLAG_FROM_VM(is_accessor) ...@@ -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); } bool ciMethod::is_initializer () const { FETCH_FLAG_FROM_VM(is_initializer); }
BCEscapeAnalyzer *ciMethod::get_bcea() { BCEscapeAnalyzer *ciMethod::get_bcea() {
#ifdef COMPILER2
if (_bcea == NULL) { if (_bcea == NULL) {
_bcea = new (CURRENT_ENV->arena()) BCEscapeAnalyzer(this, NULL); _bcea = new (CURRENT_ENV->arena()) BCEscapeAnalyzer(this, NULL);
} }
return _bcea; return _bcea;
#else // COMPILER2
ShouldNotReachHere();
return NULL;
#endif // COMPILER2
} }
ciMethodBlocks *ciMethod::get_method_blocks() { ciMethodBlocks *ciMethod::get_method_blocks() {
......
...@@ -48,7 +48,6 @@ class ciMethod : public ciObject { ...@@ -48,7 +48,6 @@ class ciMethod : public ciObject {
ciInstanceKlass* _holder; ciInstanceKlass* _holder;
ciSignature* _signature; ciSignature* _signature;
ciMethodData* _method_data; ciMethodData* _method_data;
BCEscapeAnalyzer* _bcea;
ciMethodBlocks* _method_blocks; ciMethodBlocks* _method_blocks;
// Code attributes. // Code attributes.
...@@ -72,7 +71,8 @@ class ciMethod : public ciObject { ...@@ -72,7 +71,8 @@ class ciMethod : public ciObject {
// Optional liveness analyzer. // Optional liveness analyzer.
MethodLiveness* _liveness; MethodLiveness* _liveness;
#ifdef COMPILER2 #ifdef COMPILER2
ciTypeFlow* _flow; ciTypeFlow* _flow;
BCEscapeAnalyzer* _bcea;
#endif #endif
ciMethod(methodHandle h_m); ciMethod(methodHandle h_m);
......
...@@ -89,6 +89,21 @@ adlcVMDeps.hpp allocation.hpp ...@@ -89,6 +89,21 @@ adlcVMDeps.hpp allocation.hpp
allocation.hpp c2_globals.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 allocation.inline.hpp
block.cpp block.hpp block.cpp block.hpp
block.cpp cfgnode.hpp block.cpp cfgnode.hpp
...@@ -239,6 +254,7 @@ chaitin_<os_family>.cpp machnode.hpp ...@@ -239,6 +254,7 @@ chaitin_<os_family>.cpp machnode.hpp
ciEnv.cpp compileLog.hpp ciEnv.cpp compileLog.hpp
ciEnv.cpp runtime.hpp ciEnv.cpp runtime.hpp
ciMethod.cpp bcEscapeAnalyzer.hpp
ciMethod.cpp ciTypeFlow.hpp ciMethod.cpp ciTypeFlow.hpp
ciMethod.cpp methodOop.hpp ciMethod.cpp methodOop.hpp
......
...@@ -301,20 +301,6 @@ barrierSet.hpp oopsHierarchy.hpp ...@@ -301,20 +301,6 @@ barrierSet.hpp oopsHierarchy.hpp
barrierSet.inline.hpp barrierSet.hpp barrierSet.inline.hpp barrierSet.hpp
barrierSet.inline.hpp cardTableModRefBS.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 biasedLocking.hpp
biasedLocking.cpp klass.inline.hpp biasedLocking.cpp klass.inline.hpp
biasedLocking.cpp markOop.hpp biasedLocking.cpp markOop.hpp
...@@ -665,7 +651,6 @@ ciKlassKlass.hpp ciSymbol.hpp ...@@ -665,7 +651,6 @@ ciKlassKlass.hpp ciSymbol.hpp
ciMethod.cpp abstractCompiler.hpp ciMethod.cpp abstractCompiler.hpp
ciMethod.cpp allocation.inline.hpp ciMethod.cpp allocation.inline.hpp
ciMethod.cpp bcEscapeAnalyzer.hpp
ciMethod.cpp bitMap.inline.hpp ciMethod.cpp bitMap.inline.hpp
ciMethod.cpp ciCallProfile.hpp ciMethod.cpp ciCallProfile.hpp
ciMethod.cpp ciExceptionHandler.hpp ciMethod.cpp ciExceptionHandler.hpp
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册