提交 23135ee9 编写于 作者: K kvn

6667615: (Escape Analysis) extend MDO to cache arguments escape state

Summary: Use MDO to cache arguments escape state determined by the byte code escape analyzer.
Reviewed-by: never
上级 a37e0865
...@@ -104,7 +104,7 @@ public: ...@@ -104,7 +104,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_bit(i);
} }
...@@ -112,10 +112,9 @@ void BCEscapeAnalyzer::set_returned(ArgumentMap vars) { ...@@ -112,10 +112,9 @@ void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
_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());
} }
// return true if any element of vars is an argument // return true if any element of vars is an argument
bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) { bool BCEscapeAnalyzer::is_argument(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))
return true; return true;
} }
...@@ -126,7 +125,7 @@ bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) { ...@@ -126,7 +125,7 @@ bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) {
bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ 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.at(i))
return true; return true;
} }
...@@ -134,12 +133,13 @@ bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ ...@@ -134,12 +133,13 @@ bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){
} }
void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) { void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &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.clear_bit(i);
} }
} }
} }
void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) { void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) {
clear_bits(vars, _arg_local); clear_bits(vars, _arg_local);
} }
...@@ -155,6 +155,17 @@ void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) { ...@@ -155,6 +155,17 @@ void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) {
clear_bits(vars, _dirty); clear_bits(vars, _dirty);
} }
void BCEscapeAnalyzer::set_modified(ArgumentMap vars, int offs, int size) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i)) {
set_arg_modified(i, offs, size);
}
}
if (vars.contains_unknown())
_unknown_modified = true;
}
bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) { bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) {
for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) { for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) {
if (scope->method() == callee) { if (scope->method() == callee) {
...@@ -164,6 +175,40 @@ bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) { ...@@ -164,6 +175,40 @@ bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) {
return false; return false;
} }
bool BCEscapeAnalyzer::is_arg_modified(int arg, int offset, int size_in_bytes) {
if (offset == OFFSET_ANY)
return _arg_modified[arg] != 0;
assert(arg >= 0 && arg < _arg_size, "must be an argument.");
bool modified = false;
int l = offset / HeapWordSize;
int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;
if (l > ARG_OFFSET_MAX)
l = ARG_OFFSET_MAX;
if (h > ARG_OFFSET_MAX+1)
h = ARG_OFFSET_MAX + 1;
for (int i = l; i < h; i++) {
modified = modified || (_arg_modified[arg] & (1 << i)) != 0;
}
return modified;
}
void BCEscapeAnalyzer::set_arg_modified(int arg, int offset, int size_in_bytes) {
if (offset == OFFSET_ANY) {
_arg_modified[arg] = (uint) -1;
return;
}
assert(arg >= 0 && arg < _arg_size, "must be an argument.");
int l = offset / HeapWordSize;
int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;
if (l > ARG_OFFSET_MAX)
l = ARG_OFFSET_MAX;
if (h > ARG_OFFSET_MAX+1)
h = ARG_OFFSET_MAX + 1;
for (int i = l; i < h; i++) {
_arg_modified[arg] |= (1 << i);
}
}
void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) { void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) {
int i; int i;
...@@ -197,6 +242,7 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* ...@@ -197,6 +242,7 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
for (i = 0; i < arg_size; i++) { for (i = 0; i < arg_size; i++) {
set_method_escape(state.raw_pop()); set_method_escape(state.raw_pop());
} }
_unknown_modified = true; // assume the worst since we don't analyze the called method
return; return;
} }
...@@ -224,6 +270,11 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* ...@@ -224,6 +270,11 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
ArgumentMap arg = state.raw_pop(); ArgumentMap arg = state.raw_pop();
if (!is_argument(arg)) if (!is_argument(arg))
continue; continue;
for (int j = 0; j < _arg_size; j++) {
if (arg.contains(j)) {
_arg_modified[j] |= analyzer._arg_modified[i];
}
}
if (!is_arg_stack(arg)) { if (!is_arg_stack(arg)) {
// arguments have already been recognized as escaping // arguments have already been recognized as escaping
} else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) { } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) {
...@@ -233,6 +284,7 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* ...@@ -233,6 +284,7 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
set_global_escape(arg); set_global_escape(arg);
} }
} }
_unknown_modified = _unknown_modified || analyzer.has_non_arg_side_affects();
// record dependencies if at least one parameter retained stack-allocatable // record dependencies if at least one parameter retained stack-allocatable
if (must_record_dependencies) { if (must_record_dependencies) {
...@@ -250,8 +302,10 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* ...@@ -250,8 +302,10 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
ArgumentMap arg = state.raw_pop(); ArgumentMap arg = state.raw_pop();
if (!is_argument(arg)) if (!is_argument(arg))
continue; continue;
set_modified(arg, OFFSET_ANY, type2size[T_INT]*HeapWordSize);
set_global_escape(arg); set_global_escape(arg);
} }
_unknown_modified = true; // assume the worst since we don't know the called method
} }
} }
...@@ -421,6 +475,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl ...@@ -421,6 +475,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
state.spop(); state.spop();
ArgumentMap arr = state.apop(); ArgumentMap arr = state.apop();
set_method_escape(arr); set_method_escape(arr);
set_modified(arr, OFFSET_ANY, type2size[T_INT]*HeapWordSize);
break; break;
} }
case Bytecodes::_lastore: case Bytecodes::_lastore:
...@@ -430,6 +485,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl ...@@ -430,6 +485,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
state.spop(); state.spop();
ArgumentMap arr = state.apop(); ArgumentMap arr = state.apop();
set_method_escape(arr); set_method_escape(arr);
set_modified(arr, OFFSET_ANY, type2size[T_LONG]*HeapWordSize);
break; break;
} }
case Bytecodes::_aastore: case Bytecodes::_aastore:
...@@ -437,6 +493,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl ...@@ -437,6 +493,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
set_global_escape(state.apop()); set_global_escape(state.apop());
state.spop(); state.spop();
ArgumentMap arr = state.apop(); ArgumentMap arr = state.apop();
set_modified(arr, OFFSET_ANY, type2size[T_OBJECT]*HeapWordSize);
break; break;
} }
case Bytecodes::_pop: case Bytecodes::_pop:
...@@ -762,6 +819,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl ...@@ -762,6 +819,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
if (s.cur_bc() != Bytecodes::_putstatic) { if (s.cur_bc() != Bytecodes::_putstatic) {
ArgumentMap p = state.apop(); ArgumentMap p = state.apop();
set_method_escape(p); set_method_escape(p);
set_modified(p, will_link ? field->offset() : OFFSET_ANY, type2size[field_type]*HeapWordSize);
} }
} }
break; break;
...@@ -872,7 +930,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl ...@@ -872,7 +930,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
} }
void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) { void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) {
StateInfo *d_state = blockstates+dest->index(); StateInfo *d_state = blockstates + dest->index();
int nlocals = _method->max_locals(); int nlocals = _method->max_locals();
// exceptions may cause transfer of control to handlers in the middle of a // exceptions may cause transfer of control to handlers in the middle of a
...@@ -916,6 +974,7 @@ void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, ...@@ -916,6 +974,7 @@ void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest,
} }
for (int i = 0; i < s_state->_stack_height; i++) { for (int i = 0; i < s_state->_stack_height; i++) {
ArgumentMap t; ArgumentMap t;
//extra_vars |= !d_state->_vars[i] & s_state->_vars[i];
t.clear(); t.clear();
t = s_state->_stack[i]; t = s_state->_stack[i];
t.set_difference(d_state->_stack[i]); t.set_difference(d_state->_stack[i]);
...@@ -933,7 +992,7 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) { ...@@ -933,7 +992,7 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) {
int datacount = (numblocks + 1) * (stkSize + numLocals); int datacount = (numblocks + 1) * (stkSize + numLocals);
int datasize = datacount * sizeof(ArgumentMap); int datasize = datacount * sizeof(ArgumentMap);
StateInfo *blockstates = (StateInfo *) arena->Amalloc(_methodBlocks->num_blocks() * sizeof(StateInfo)); StateInfo *blockstates = (StateInfo *) arena->Amalloc(numblocks * sizeof(StateInfo));
ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize); ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize);
for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap(); for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap();
ArgumentMap *dp = statedata; ArgumentMap *dp = statedata;
...@@ -961,33 +1020,35 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) { ...@@ -961,33 +1020,35 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) {
ArgumentMap allVars; // all oop arguments to method ArgumentMap allVars; // all oop arguments to method
ciSignature* sig = method()->signature(); ciSignature* sig = method()->signature();
int j = 0; int j = 0;
ciBlock* first_blk = _methodBlocks->block_containing(0);
int fb_i = first_blk->index();
if (!method()->is_static()) { if (!method()->is_static()) {
// record information for "this" // record information for "this"
blockstates[0]._vars[j].set(j); blockstates[fb_i]._vars[j].set(j);
allVars.add(j); allVars.add(j);
j++; j++;
} }
for (int i = 0; i < sig->count(); i++) { for (int 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()) {
blockstates[0]._vars[j].set(j); blockstates[fb_i]._vars[j].set(j);
allVars.add(j); allVars.add(j);
} }
j += t->size(); j += t->size();
} }
blockstates[0]._initialized = true; blockstates[fb_i]._initialized = true;
assert(j == _arg_size, "just checking"); assert(j == _arg_size, "just checking");
ArgumentMap unknown_map; ArgumentMap unknown_map;
unknown_map.add_unknown(); unknown_map.add_unknown();
worklist.push(_methodBlocks->block_containing(0)); worklist.push(first_blk);
while(worklist.length() > 0) { while(worklist.length() > 0) {
ciBlock *blk = worklist.pop(); ciBlock *blk = worklist.pop();
StateInfo *blkState = blockstates+blk->index(); StateInfo *blkState = blockstates + blk->index();
if (blk->is_handler() || blk->is_ret_target()) { if (blk->is_handler() || blk->is_ret_target()) {
// for an exception handler or a target of a ret instruction, we assume the worst case, // for an exception handler or a target of a ret instruction, we assume the worst case,
// that any variable or stack slot could contain any argument // that any variable could contain any argument
for (int i = 0; i < numLocals; i++) { for (int i = 0; i < numLocals; i++) {
state._vars[i] = allVars; state._vars[i] = allVars;
} }
...@@ -997,6 +1058,7 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) { ...@@ -997,6 +1058,7 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) {
state._stack_height = blkState->_stack_height; state._stack_height = blkState->_stack_height;
} }
for (int i = 0; i < state._stack_height; i++) { for (int i = 0; i < state._stack_height; i++) {
// ??? should this be unknown_map ???
state._stack[i] = allVars; state._stack[i] = allVars;
} }
} else { } else {
...@@ -1053,6 +1115,7 @@ vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() { ...@@ -1053,6 +1115,7 @@ vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {
vmIntrinsics::ID iid = method()->intrinsic_id(); vmIntrinsics::ID iid = method()->intrinsic_id();
if (iid == vmIntrinsics::_getClass || if (iid == vmIntrinsics::_getClass ||
iid == vmIntrinsics::_fillInStackTrace ||
iid == vmIntrinsics::_hashCode) iid == vmIntrinsics::_hashCode)
return iid; return iid;
else else
...@@ -1060,12 +1123,16 @@ vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() { ...@@ -1060,12 +1123,16 @@ vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {
} }
bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) { bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {
ArgumentMap empty; ArgumentMap arg;
empty.clear(); arg.clear();
switch (iid) { switch (iid) {
case vmIntrinsics::_getClass: case vmIntrinsics::_getClass:
_return_local = false; _return_local = false;
break; break;
case vmIntrinsics::_fillInStackTrace:
arg.set(0); // 'this'
set_returned(arg);
break;
case vmIntrinsics::_hashCode: case vmIntrinsics::_hashCode:
// initialized state is correct // initialized state is correct
break; break;
...@@ -1109,15 +1176,21 @@ void BCEscapeAnalyzer::initialize() { ...@@ -1109,15 +1176,21 @@ void BCEscapeAnalyzer::initialize() {
_return_allocated = true; _return_allocated = true;
} }
_allocated_escapes = false; _allocated_escapes = false;
_unknown_modified = false;
} }
void BCEscapeAnalyzer::clear_escape_info() { void BCEscapeAnalyzer::clear_escape_info() {
ciSignature* sig = method()->signature(); ciSignature* sig = method()->signature();
int arg_count = sig->count(); int arg_count = sig->count();
ArgumentMap var; ArgumentMap var;
if (!method()->is_static()) {
arg_count++; // allow for "this"
}
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
set_arg_modified(i, OFFSET_ANY, 4);
var.clear(); var.clear();
var.set(i); var.set(i);
set_modified(var, OFFSET_ANY, 4);
set_global_escape(var); set_global_escape(var);
} }
_arg_local.clear(); _arg_local.clear();
...@@ -1126,6 +1199,7 @@ void BCEscapeAnalyzer::clear_escape_info() { ...@@ -1126,6 +1199,7 @@ void BCEscapeAnalyzer::clear_escape_info() {
_return_local = false; _return_local = false;
_return_allocated = false; _return_allocated = false;
_allocated_escapes = true; _allocated_escapes = true;
_unknown_modified = true;
} }
...@@ -1205,8 +1279,17 @@ void BCEscapeAnalyzer::compute_escape_info() { ...@@ -1205,8 +1279,17 @@ void BCEscapeAnalyzer::compute_escape_info() {
} else { } else {
tty->print_cr(" non-local return values"); tty->print_cr(" non-local return values");
} }
tty->print(" modified args: ");
for (int i = 0; i < _arg_size; i++) {
if (_arg_modified[i] == 0)
tty->print(" 0");
else
tty->print(" 0x%x", _arg_modified[i]);
}
tty->cr(); tty->cr();
tty->print(" flags: "); tty->print(" flags: ");
if (_unknown_modified)
tty->print(" unknown_modified");
if (_return_allocated) if (_return_allocated)
tty->print(" return_allocated"); tty->print(" return_allocated");
tty->cr(); tty->cr();
...@@ -1228,6 +1311,7 @@ void BCEscapeAnalyzer::compute_escape_info() { ...@@ -1228,6 +1311,7 @@ void BCEscapeAnalyzer::compute_escape_info() {
if (_arg_returned.at(i)) { if (_arg_returned.at(i)) {
methodData()->set_arg_returned(i); methodData()->set_arg_returned(i);
} }
methodData()->set_arg_modified(i, _arg_modified[i]);
} }
if (_return_local) { if (_return_local) {
methodData()->set_eflag(methodDataOopDesc::return_local); methodData()->set_eflag(methodDataOopDesc::return_local);
...@@ -1244,6 +1328,7 @@ void BCEscapeAnalyzer::read_escape_info() { ...@@ -1244,6 +1328,7 @@ void BCEscapeAnalyzer::read_escape_info() {
_arg_local.at_put(i, methodData()->is_arg_local(i)); _arg_local.at_put(i, methodData()->is_arg_local(i));
_arg_stack.at_put(i, methodData()->is_arg_stack(i)); _arg_stack.at_put(i, methodData()->is_arg_stack(i));
_arg_returned.at_put(i, methodData()->is_arg_returned(i)); _arg_returned.at_put(i, methodData()->is_arg_returned(i));
_arg_modified[i] = methodData()->arg_modified(i);
} }
_return_local = methodData()->eflag_set(methodDataOopDesc::return_local); _return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
...@@ -1261,6 +1346,12 @@ void BCEscapeAnalyzer::read_escape_info() { ...@@ -1261,6 +1346,12 @@ void BCEscapeAnalyzer::read_escape_info() {
tty->print_cr(" non-local return values"); tty->print_cr(" non-local return values");
} }
tty->print(" modified args: "); tty->print(" modified args: ");
for (int i = 0; i < _arg_size; i++) {
if (_arg_modified[i] == 0)
tty->print(" 0");
else
tty->print(" 0x%x", _arg_modified[i]);
}
tty->cr(); tty->cr();
} }
#endif #endif
...@@ -1281,6 +1372,7 @@ BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent) ...@@ -1281,6 +1372,7 @@ BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
, _return_local(false) , _return_local(false)
, _return_allocated(false) , _return_allocated(false)
, _allocated_escapes(false) , _allocated_escapes(false)
, _unknown_modified(false)
, _dependencies() , _dependencies()
, _parent(parent) , _parent(parent)
, _level(parent == NULL ? 0 : parent->level() + 1) { , _level(parent == NULL ? 0 : parent->level() + 1) {
...@@ -1290,6 +1382,8 @@ BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent) ...@@ -1290,6 +1382,8 @@ BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
_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));
Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
if (methodData() == NULL) if (methodData() == NULL)
return; return;
......
...@@ -46,9 +46,12 @@ class BCEscapeAnalyzer : public ResourceObj { ...@@ -46,9 +46,12 @@ class BCEscapeAnalyzer : public ResourceObj {
BitMap _arg_stack; BitMap _arg_stack;
BitMap _arg_returned; BitMap _arg_returned;
BitMap _dirty; BitMap _dirty;
enum{ ARG_OFFSET_MAX = 31};
uint *_arg_modified;
bool _return_local; bool _return_local;
bool _allocated_escapes; bool _allocated_escapes;
bool _unknown_modified;
bool _return_allocated; bool _return_allocated;
ciObjectList _dependencies; ciObjectList _dependencies;
...@@ -80,6 +83,7 @@ class BCEscapeAnalyzer : public ResourceObj { ...@@ -80,6 +83,7 @@ class BCEscapeAnalyzer : public ResourceObj {
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);
void set_modified(ArgumentMap vars, int offs, int size);
bool is_recursive_call(ciMethod* callee); bool is_recursive_call(ciMethod* callee);
void add_dependence(ciKlass *klass, ciMethod *meth); void add_dependence(ciKlass *klass, ciMethod *meth);
...@@ -140,6 +144,13 @@ class BCEscapeAnalyzer : public ResourceObj { ...@@ -140,6 +144,13 @@ class BCEscapeAnalyzer : public ResourceObj {
return !_conservative && _return_allocated && !_allocated_escapes; return !_conservative && _return_allocated && !_allocated_escapes;
} }
// Tracking of argument modification
enum {OFFSET_ANY = -1};
bool is_arg_modified(int arg, int offset, int size_in_bytes);
void set_arg_modified(int arg, int offset, int size_in_bytes);
bool has_non_arg_side_affects() { return _unknown_modified; }
// Copy dependencies from this analysis into "deps" // Copy dependencies from this analysis into "deps"
void copy_dependencies(Dependencies *deps); void copy_dependencies(Dependencies *deps);
}; };
...@@ -42,6 +42,8 @@ ciMethodData::ciMethodData(methodDataHandle h_md) : ciObject(h_md) { ...@@ -42,6 +42,8 @@ ciMethodData::ciMethodData(methodDataHandle h_md) : ciObject(h_md) {
// Set an initial hint. Don't use set_hint_di() because // Set an initial hint. Don't use set_hint_di() because
// first_di() may be out of bounds if data_size is 0. // first_di() may be out of bounds if data_size is 0.
_hint_di = first_di(); _hint_di = first_di();
// Initialize the escape information (to "don't know.");
_eflags = _arg_local = _arg_stack = _arg_returned = 0;
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------
...@@ -59,6 +61,8 @@ ciMethodData::ciMethodData() : ciObject() { ...@@ -59,6 +61,8 @@ ciMethodData::ciMethodData() : ciObject() {
// Set an initial hint. Don't use set_hint_di() because // Set an initial hint. Don't use set_hint_di() because
// first_di() may be out of bounds if data_size is 0. // first_di() may be out of bounds if data_size is 0.
_hint_di = first_di(); _hint_di = first_di();
// Initialize the escape information (to "don't know.");
_eflags = _arg_local = _arg_stack = _arg_returned = 0;
} }
void ciMethodData::load_data() { void ciMethodData::load_data() {
...@@ -142,6 +146,8 @@ ciProfileData* ciMethodData::data_at(int data_index) { ...@@ -142,6 +146,8 @@ ciProfileData* ciMethodData::data_at(int data_index) {
return new ciBranchData(data_layout); return new ciBranchData(data_layout);
case DataLayout::multi_branch_data_tag: case DataLayout::multi_branch_data_tag:
return new ciMultiBranchData(data_layout); return new ciMultiBranchData(data_layout);
case DataLayout::arg_info_data_tag:
return new ciArgInfoData(data_layout);
}; };
} }
...@@ -172,6 +178,9 @@ ciProfileData* ciMethodData::bci_to_data(int bci) { ...@@ -172,6 +178,9 @@ ciProfileData* ciMethodData::bci_to_data(int bci) {
_saw_free_extra_data = true; // observed an empty slot (common case) _saw_free_extra_data = true; // observed an empty slot (common case)
return NULL; return NULL;
} }
if (dp->tag() == DataLayout::arg_info_data_tag) {
break; // ArgInfoData is at the end of extra data section.
}
if (dp->bci() == bci) { if (dp->bci() == bci) {
assert(dp->tag() == DataLayout::bit_data_tag, "sane"); assert(dp->tag() == DataLayout::bit_data_tag, "sane");
return new ciBitData(dp); return new ciBitData(dp);
...@@ -217,8 +226,14 @@ int ciMethodData::trap_recompiled_at(ciProfileData* data) { ...@@ -217,8 +226,14 @@ int ciMethodData::trap_recompiled_at(ciProfileData* data) {
void ciMethodData::clear_escape_info() { void ciMethodData::clear_escape_info() {
VM_ENTRY_MARK; VM_ENTRY_MARK;
methodDataOop mdo = get_methodDataOop(); methodDataOop mdo = get_methodDataOop();
if (mdo != NULL) if (mdo != NULL) {
mdo->clear_escape_info(); mdo->clear_escape_info();
ArgInfoData *aid = arg_info();
int arg_count = (aid == NULL) ? 0 : aid->number_of_args();
for (int i = 0; i < arg_count; i++) {
set_arg_modified(i, 0);
}
}
_eflags = _arg_local = _arg_stack = _arg_returned = 0; _eflags = _arg_local = _arg_stack = _arg_returned = 0;
} }
...@@ -231,6 +246,10 @@ void ciMethodData::update_escape_info() { ...@@ -231,6 +246,10 @@ void ciMethodData::update_escape_info() {
mdo->set_arg_local(_arg_local); mdo->set_arg_local(_arg_local);
mdo->set_arg_stack(_arg_stack); mdo->set_arg_stack(_arg_stack);
mdo->set_arg_returned(_arg_returned); mdo->set_arg_returned(_arg_returned);
int arg_count = mdo->method()->size_of_parameters();
for (int i = 0; i < arg_count; i++) {
mdo->set_arg_modified(i, arg_modified(i));
}
} }
} }
...@@ -262,6 +281,14 @@ void ciMethodData::set_arg_returned(int i) { ...@@ -262,6 +281,14 @@ void ciMethodData::set_arg_returned(int i) {
set_nth_bit(_arg_returned, i); set_nth_bit(_arg_returned, i);
} }
void ciMethodData::set_arg_modified(int arg, uint val) {
ArgInfoData *aid = arg_info();
if (aid == NULL)
return;
assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
aid->set_arg_modified(arg, val);
}
bool ciMethodData::is_arg_local(int i) const { bool ciMethodData::is_arg_local(int i) const {
return is_set_nth_bit(_arg_local, i); return is_set_nth_bit(_arg_local, i);
} }
...@@ -274,6 +301,14 @@ bool ciMethodData::is_arg_returned(int i) const { ...@@ -274,6 +301,14 @@ bool ciMethodData::is_arg_returned(int i) const {
return is_set_nth_bit(_arg_returned, i); return is_set_nth_bit(_arg_returned, i);
} }
uint ciMethodData::arg_modified(int arg) const {
ArgInfoData *aid = arg_info();
if (aid == NULL)
return 0;
assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
return aid->arg_modified(arg);
}
ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) { ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) {
// Get offset within methodDataOop of the data array // Get offset within methodDataOop of the data array
ByteSize data_offset = methodDataOopDesc::data_offset(); ByteSize data_offset = methodDataOopDesc::data_offset();
...@@ -287,6 +322,18 @@ ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_ ...@@ -287,6 +322,18 @@ ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_
return in_ByteSize(offset); return in_ByteSize(offset);
} }
ciArgInfoData *ciMethodData::arg_info() const {
// Should be last, have to skip all traps.
DataLayout* dp = data_layout_at(data_size());
DataLayout* end = data_layout_at(data_size() + extra_data_size());
for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) {
if (dp->tag() == DataLayout::arg_info_data_tag)
return new ciArgInfoData(dp);
}
return NULL;
}
// Implementation of the print method. // Implementation of the print method.
void ciMethodData::print_impl(outputStream* st) { void ciMethodData::print_impl(outputStream* st) {
ciObject::print_impl(st); ciObject::print_impl(st);
...@@ -305,6 +352,22 @@ void ciMethodData::print_data_on(outputStream* st) { ...@@ -305,6 +352,22 @@ void ciMethodData::print_data_on(outputStream* st) {
st->fill_to(6); st->fill_to(6);
data->print_data_on(st); data->print_data_on(st);
} }
st->print_cr("--- Extra data:");
DataLayout* dp = data_layout_at(data_size());
DataLayout* end = data_layout_at(data_size() + extra_data_size());
for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) {
if (dp->tag() == DataLayout::no_tag) continue;
if (dp->tag() == DataLayout::bit_data_tag) {
data = new BitData(dp);
} else {
assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo");
data = new ciArgInfoData(dp);
dp = end; // ArgInfoData is at the end of extra data section.
}
st->print("%d", dp_to_di(data->dp()));
st->fill_to(6);
data->print_data_on(st);
}
} }
void ciReceiverTypeData::print_receiver_data_on(outputStream* st) { void ciReceiverTypeData::print_receiver_data_on(outputStream* st) {
......
...@@ -30,6 +30,7 @@ class ciRetData; ...@@ -30,6 +30,7 @@ class ciRetData;
class ciBranchData; class ciBranchData;
class ciArrayData; class ciArrayData;
class ciMultiBranchData; class ciMultiBranchData;
class ciArgInfoData;
typedef ProfileData ciProfileData; typedef ProfileData ciProfileData;
...@@ -121,6 +122,11 @@ public: ...@@ -121,6 +122,11 @@ public:
ciMultiBranchData(DataLayout* layout) : MultiBranchData(layout) {}; ciMultiBranchData(DataLayout* layout) : MultiBranchData(layout) {};
}; };
class ciArgInfoData : public ArgInfoData {
public:
ciArgInfoData(DataLayout* layout) : ArgInfoData(layout) {};
};
// ciMethodData // ciMethodData
// //
// This class represents a methodDataOop in the HotSpot virtual // This class represents a methodDataOop in the HotSpot virtual
...@@ -163,9 +169,9 @@ private: ...@@ -163,9 +169,9 @@ private:
ciMethodData(); ciMethodData();
// Accessors // Accessors
int data_size() { return _data_size; } int data_size() const { return _data_size; }
int extra_data_size() { return _extra_data_size; } int extra_data_size() const { return _extra_data_size; }
intptr_t * data() { return _data; } intptr_t * data() const { return _data; }
methodDataOop get_methodDataOop() const { methodDataOop get_methodDataOop() const {
if (handle() == NULL) return NULL; if (handle() == NULL) return NULL;
...@@ -178,7 +184,7 @@ private: ...@@ -178,7 +184,7 @@ private:
void print_impl(outputStream* st); void print_impl(outputStream* st);
DataLayout* data_layout_at(int data_index) { DataLayout* data_layout_at(int data_index) const {
assert(data_index % sizeof(intptr_t) == 0, "unaligned"); assert(data_index % sizeof(intptr_t) == 0, "unaligned");
return (DataLayout*) (((address)_data) + data_index); return (DataLayout*) (((address)_data) + data_index);
} }
...@@ -207,6 +213,8 @@ private: ...@@ -207,6 +213,8 @@ private:
// What is the index of the first data entry? // What is the index of the first data entry?
int first_di() { return 0; } int first_di() { return 0; }
ciArgInfoData *arg_info() const;
public: public:
bool is_method_data() { return true; } bool is_method_data() { return true; }
bool is_empty() { return _state == empty_state; } bool is_empty() { return _state == empty_state; }
...@@ -270,10 +278,12 @@ public: ...@@ -270,10 +278,12 @@ public:
void set_arg_local(int i); void set_arg_local(int i);
void set_arg_stack(int i); void set_arg_stack(int i);
void set_arg_returned(int i); void set_arg_returned(int i);
void set_arg_modified(int arg, uint val);
bool is_arg_local(int i) const; bool is_arg_local(int i) const;
bool is_arg_stack(int i) const; bool is_arg_stack(int i) const;
bool is_arg_returned(int i) const; bool is_arg_returned(int i) const;
uint arg_modified(int arg) const;
// Code generation helper // Code generation helper
ByteSize offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data); ByteSize offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data);
......
...@@ -318,6 +318,11 @@ inline bool match_F_SN(jshort flags) { ...@@ -318,6 +318,11 @@ inline bool match_F_SN(jshort flags) {
const int neg = JVM_ACC_SYNCHRONIZED; const int neg = JVM_ACC_SYNCHRONIZED;
return (flags & (req | neg)) == req; return (flags & (req | neg)) == req;
} }
inline bool match_F_RNY(jshort flags) {
const int req = JVM_ACC_NATIVE | JVM_ACC_SYNCHRONIZED;
const int neg = JVM_ACC_STATIC;
return (flags & (req | neg)) == req;
}
// These are for forming case labels: // These are for forming case labels:
#define ID3(x, y, z) (( jint)(z) + \ #define ID3(x, y, z) (( jint)(z) + \
...@@ -359,6 +364,7 @@ const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf, ...@@ -359,6 +364,7 @@ const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf,
case F_RN: fname = "native "; break; case F_RN: fname = "native "; break;
case F_SN: fname = "native static "; break; case F_SN: fname = "native static "; break;
case F_S: fname = "static "; break; case F_S: fname = "static "; break;
case F_RNY:fname = "native synchronized "; break;
} }
const char* kptr = strrchr(kname, '/'); const char* kptr = strrchr(kname, '/');
if (kptr != NULL) kname = kptr + 1; if (kptr != NULL) kname = kptr + 1;
...@@ -485,7 +491,7 @@ void vmIntrinsics::verify_method(ID actual_id, methodOop m) { ...@@ -485,7 +491,7 @@ void vmIntrinsics::verify_method(ID actual_id, methodOop m) {
if (PrintMiscellaneous && (WizardMode || Verbose)) { if (PrintMiscellaneous && (WizardMode || Verbose)) {
tty->print_cr("*** misidentified method; %s(%d) should be %s(%d):", tty->print_cr("*** misidentified method; %s(%d) should be %s(%d):",
declared_name, declared_id, actual_name, actual_id); declared_name, declared_id, actual_name, actual_id);
m->print_short_name(tty); mh()->print_short_name(tty);
tty->cr(); tty->cr();
} }
} }
......
...@@ -584,6 +584,8 @@ ...@@ -584,6 +584,8 @@
do_name( attemptUpdate_name, "attemptUpdate") \ do_name( attemptUpdate_name, "attemptUpdate") \
do_signature(attemptUpdate_signature, "(JJ)Z") \ do_signature(attemptUpdate_signature, "(JJ)Z") \
\ \
do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \
\
/* support for sun.misc.Unsafe */ \ /* support for sun.misc.Unsafe */ \
do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \
\ \
...@@ -871,7 +873,8 @@ class vmIntrinsics: AllStatic { ...@@ -871,7 +873,8 @@ class vmIntrinsics: AllStatic {
F_R, // !static !synchronized (R="regular") F_R, // !static !synchronized (R="regular")
F_S, // static !synchronized F_S, // static !synchronized
F_RN, // !static native !synchronized F_RN, // !static native !synchronized
F_SN // static native !synchronized F_SN, // static native !synchronized
F_RNY // !static native synchronized
}; };
public: public:
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
// Some types of data layouts need a length field. // Some types of data layouts need a length field.
bool DataLayout::needs_array_len(u1 tag) { bool DataLayout::needs_array_len(u1 tag) {
return (tag == multi_branch_data_tag); return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag);
} }
// Perform generic initialization of the data. More specific // Perform generic initialization of the data. More specific
...@@ -404,6 +404,17 @@ void MultiBranchData::print_data_on(outputStream* st) { ...@@ -404,6 +404,17 @@ void MultiBranchData::print_data_on(outputStream* st) {
} }
#endif #endif
#ifndef PRODUCT
void ArgInfoData::print_data_on(outputStream* st) {
print_shared(st, "ArgInfoData");
int nargs = number_of_args();
for (int i = 0; i < nargs; i++) {
st->print(" 0x%x", arg_modified(i));
}
st->cr();
}
#endif
// ================================================================== // ==================================================================
// methodDataOop // methodDataOop
// //
...@@ -508,6 +519,9 @@ int methodDataOopDesc::compute_allocation_size_in_bytes(methodHandle method) { ...@@ -508,6 +519,9 @@ int methodDataOopDesc::compute_allocation_size_in_bytes(methodHandle method) {
int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); int extra_data_count = compute_extra_data_count(data_size, empty_bc_count);
object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); object_size += extra_data_count * DataLayout::compute_size_in_bytes(0);
// Add a cell to record information about modified arguments.
int arg_size = method->size_of_parameters();
object_size += DataLayout::compute_size_in_bytes(arg_size+1);
return object_size; return object_size;
} }
...@@ -626,6 +640,8 @@ ProfileData* methodDataOopDesc::data_at(int data_index) { ...@@ -626,6 +640,8 @@ ProfileData* methodDataOopDesc::data_at(int data_index) {
return new BranchData(data_layout); return new BranchData(data_layout);
case DataLayout::multi_branch_data_tag: case DataLayout::multi_branch_data_tag:
return new MultiBranchData(data_layout); return new MultiBranchData(data_layout);
case DataLayout::arg_info_data_tag:
return new ArgInfoData(data_layout);
}; };
} }
...@@ -681,7 +697,17 @@ void methodDataOopDesc::initialize(methodHandle method) { ...@@ -681,7 +697,17 @@ void methodDataOopDesc::initialize(methodHandle method) {
// Add some extra DataLayout cells (at least one) to track stray traps. // Add some extra DataLayout cells (at least one) to track stray traps.
int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); int extra_data_count = compute_extra_data_count(data_size, empty_bc_count);
object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); int extra_size = extra_data_count * DataLayout::compute_size_in_bytes(0);
// Add a cell to record information about modified arguments.
// Set up _args_modified array after traps cells so that
// the code for traps cells works.
DataLayout *dp = data_layout_at(data_size + extra_size);
int arg_size = method->size_of_parameters();
dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1);
// Set an initial hint. Don't use set_hint_di() because // Set an initial hint. Don't use set_hint_di() because
// first_di() may be out of bounds if data_size is 0. // first_di() may be out of bounds if data_size is 0.
...@@ -764,6 +790,10 @@ ProfileData* methodDataOopDesc::bci_to_extra_data(int bci, bool create_if_missin ...@@ -764,6 +790,10 @@ ProfileData* methodDataOopDesc::bci_to_extra_data(int bci, bool create_if_missin
// No need for "OrderAccess::load_acquire" ops, // No need for "OrderAccess::load_acquire" ops,
// since the data structure is monotonic. // since the data structure is monotonic.
if (dp->tag() == DataLayout::no_tag) break; if (dp->tag() == DataLayout::no_tag) break;
if (dp->tag() == DataLayout::arg_info_data_tag) {
dp = end; // ArgInfoData is at the end of extra data section.
break;
}
if (dp->bci() == bci) { if (dp->bci() == bci) {
assert(dp->tag() == DataLayout::bit_data_tag, "sane"); assert(dp->tag() == DataLayout::bit_data_tag, "sane");
return new BitData(dp); return new BitData(dp);
...@@ -785,6 +815,16 @@ ProfileData* methodDataOopDesc::bci_to_extra_data(int bci, bool create_if_missin ...@@ -785,6 +815,16 @@ ProfileData* methodDataOopDesc::bci_to_extra_data(int bci, bool create_if_missin
return NULL; return NULL;
} }
ArgInfoData *methodDataOopDesc::arg_info() {
DataLayout* dp = extra_data_base();
DataLayout* end = extra_data_limit();
for (; dp < end; dp = next_extra(dp)) {
if (dp->tag() == DataLayout::arg_info_data_tag)
return new ArgInfoData(dp);
}
return NULL;
}
#ifndef PRODUCT #ifndef PRODUCT
void methodDataOopDesc::print_data_on(outputStream* st) { void methodDataOopDesc::print_data_on(outputStream* st) {
ResourceMark rm; ResourceMark rm;
...@@ -794,15 +834,20 @@ void methodDataOopDesc::print_data_on(outputStream* st) { ...@@ -794,15 +834,20 @@ void methodDataOopDesc::print_data_on(outputStream* st) {
st->fill_to(6); st->fill_to(6);
data->print_data_on(st); data->print_data_on(st);
} }
st->print_cr("--- Extra data:");
DataLayout* dp = extra_data_base(); DataLayout* dp = extra_data_base();
DataLayout* end = extra_data_limit(); DataLayout* end = extra_data_limit();
for (; dp < end; dp = next_extra(dp)) { for (; dp < end; dp = next_extra(dp)) {
// No need for "OrderAccess::load_acquire" ops, // No need for "OrderAccess::load_acquire" ops,
// since the data structure is monotonic. // since the data structure is monotonic.
if (dp->tag() == DataLayout::no_tag) break; if (dp->tag() == DataLayout::no_tag) continue;
if (dp == extra_data_base()) if (dp->tag() == DataLayout::bit_data_tag) {
st->print_cr("--- Extra data:"); data = new BitData(dp);
data = new BitData(dp); } else {
assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo");
data = new ArgInfoData(dp);
dp = end; // ArgInfoData is at the end of extra data section.
}
st->print("%d", dp_to_di(data->dp())); st->print("%d", dp_to_di(data->dp()));
st->fill_to(6); st->fill_to(6);
data->print_data_on(st); data->print_data_on(st);
......
...@@ -101,7 +101,8 @@ public: ...@@ -101,7 +101,8 @@ public:
virtual_call_data_tag, virtual_call_data_tag,
ret_data_tag, ret_data_tag,
branch_data_tag, branch_data_tag,
multi_branch_data_tag multi_branch_data_tag,
arg_info_data_tag
}; };
enum { enum {
...@@ -245,6 +246,7 @@ class JumpData; ...@@ -245,6 +246,7 @@ class JumpData;
class BranchData; class BranchData;
class ArrayData; class ArrayData;
class MultiBranchData; class MultiBranchData;
class ArgInfoData;
// ProfileData // ProfileData
...@@ -376,6 +378,8 @@ public: ...@@ -376,6 +378,8 @@ public:
virtual bool is_BranchData() { return false; } virtual bool is_BranchData() { return false; }
virtual bool is_ArrayData() { return false; } virtual bool is_ArrayData() { return false; }
virtual bool is_MultiBranchData() { return false; } virtual bool is_MultiBranchData() { return false; }
virtual bool is_ArgInfoData() { return false; }
BitData* as_BitData() { BitData* as_BitData() {
assert(is_BitData(), "wrong type"); assert(is_BitData(), "wrong type");
...@@ -413,6 +417,10 @@ public: ...@@ -413,6 +417,10 @@ public:
assert(is_MultiBranchData(), "wrong type"); assert(is_MultiBranchData(), "wrong type");
return is_MultiBranchData() ? (MultiBranchData*)this : NULL; return is_MultiBranchData() ? (MultiBranchData*)this : NULL;
} }
ArgInfoData* as_ArgInfoData() {
assert(is_ArgInfoData(), "wrong type");
return is_ArgInfoData() ? (ArgInfoData*)this : NULL;
}
// Subclass specific initialization // Subclass specific initialization
...@@ -1047,6 +1055,33 @@ public: ...@@ -1047,6 +1055,33 @@ public:
#endif #endif
}; };
class ArgInfoData : public ArrayData {
public:
ArgInfoData(DataLayout* layout) : ArrayData(layout) {
assert(layout->tag() == DataLayout::arg_info_data_tag, "wrong type");
}
virtual bool is_ArgInfoData() { return true; }
int number_of_args() {
return array_len();
}
uint arg_modified(int arg) {
return array_uint_at(arg);
}
void set_arg_modified(int arg, uint val) {
array_set_int_at(arg, val);
}
#ifndef PRODUCT
void print_data_on(outputStream* st);
#endif
};
// methodDataOop // methodDataOop
// //
// A methodDataOop holds information which has been collected about // A methodDataOop holds information which has been collected about
...@@ -1183,6 +1218,9 @@ private: ...@@ -1183,6 +1218,9 @@ private:
// Find or create an extra ProfileData: // Find or create an extra ProfileData:
ProfileData* bci_to_extra_data(int bci, bool create_if_missing); ProfileData* bci_to_extra_data(int bci, bool create_if_missing);
// return the argument info cell
ArgInfoData *arg_info();
public: public:
static int header_size() { static int header_size() {
return sizeof(methodDataOopDesc)/wordSize; return sizeof(methodDataOopDesc)/wordSize;
...@@ -1222,11 +1260,18 @@ public: ...@@ -1222,11 +1260,18 @@ public:
intx arg_local() { return _arg_local; } intx arg_local() { return _arg_local; }
intx arg_stack() { return _arg_stack; } intx arg_stack() { return _arg_stack; }
intx arg_returned() { return _arg_returned; } intx arg_returned() { return _arg_returned; }
uint arg_modified(int a) { ArgInfoData *aid = arg_info();
assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
return aid->arg_modified(a); }
void set_eflags(intx v) { _eflags = v; } void set_eflags(intx v) { _eflags = v; }
void set_arg_local(intx v) { _arg_local = v; } void set_arg_local(intx v) { _arg_local = v; }
void set_arg_stack(intx v) { _arg_stack = v; } void set_arg_stack(intx v) { _arg_stack = v; }
void set_arg_returned(intx v) { _arg_returned = v; } void set_arg_returned(intx v) { _arg_returned = v; }
void set_arg_modified(int a, uint v) { ArgInfoData *aid = arg_info();
assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
aid->set_arg_modified(a, v); }
void clear_escape_info() { _eflags = _arg_local = _arg_stack = _arg_returned = 0; } void clear_escape_info() { _eflags = _arg_local = _arg_stack = _arg_returned = 0; }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册