6898462: The escape analysis with G1 cause crash assertion src/share/vm/runtime/vframeArray.cpp:94

OOM during reallocation of scalar replaced objects in deoptimization causes crashes

Reviewed-by: kvn, jrose
This commit is contained in:
Roland Westrelin 2014-11-25 17:33:59 +01:00
parent 53f42d325b
commit 15dcd41e87
12 changed files with 602 additions and 64 deletions

View file

@ -57,7 +57,7 @@ void vframeArrayElement::free_monitors(JavaThread* jt) {
}
}
void vframeArrayElement::fill_in(compiledVFrame* vf) {
void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) {
// Copy the information from the compiled vframe to the
// interpreter frame we will be creating to replace vf
@ -65,6 +65,9 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
_method = vf->method();
_bci = vf->raw_bci();
_reexecute = vf->should_reexecute();
#ifdef ASSERT
_removed_monitors = false;
#endif
int index;
@ -82,11 +85,15 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
// Migrate the BasicLocks from the stack to the monitor chunk
for (index = 0; index < list->length(); index++) {
MonitorInfo* monitor = list->at(index);
assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already");
assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
assert(!monitor->owner_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
BasicObjectLock* dest = _monitors->at(index);
dest->set_obj(monitor->owner());
monitor->lock()->move_to(monitor->owner(), dest->lock());
if (monitor->owner_is_scalar_replaced()) {
dest->set_obj(NULL);
} else {
assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
dest->set_obj(monitor->owner());
monitor->lock()->move_to(monitor->owner(), dest->lock());
}
}
}
@ -111,7 +118,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
StackValue* value = locs->at(index);
switch(value->type()) {
case T_OBJECT:
assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
// preserve object type
_locals->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
break;
@ -136,7 +143,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
StackValue* value = exprs->at(index);
switch(value->type()) {
case T_OBJECT:
assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
// preserve object type
_expressions->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
break;
@ -287,7 +294,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters,
_frame.patch_pc(thread, pc);
assert (!method()->is_synchronized() || locks > 0, "synchronized methods must have monitors");
assert (!method()->is_synchronized() || locks > 0 || _removed_monitors, "synchronized methods must have monitors");
BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin();
for (int index = 0; index < locks; index++) {
@ -439,7 +446,8 @@ int vframeArrayElement::on_stack_size(int callee_parameters,
vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk,
RegisterMap *reg_map, frame sender, frame caller, frame self) {
RegisterMap *reg_map, frame sender, frame caller, frame self,
bool realloc_failures) {
// Allocate the vframeArray
vframeArray * result = (vframeArray*) AllocateHeap(sizeof(vframeArray) + // fixed part
@ -451,19 +459,20 @@ vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableA
result->_caller = caller;
result->_original = self;
result->set_unroll_block(NULL); // initialize it
result->fill_in(thread, frame_size, chunk, reg_map);
result->fill_in(thread, frame_size, chunk, reg_map, realloc_failures);
return result;
}
void vframeArray::fill_in(JavaThread* thread,
int frame_size,
GrowableArray<compiledVFrame*>* chunk,
const RegisterMap *reg_map) {
const RegisterMap *reg_map,
bool realloc_failures) {
// Set owner first, it is used when adding monitor chunks
_frame_size = frame_size;
for(int i = 0; i < chunk->length(); i++) {
element(i)->fill_in(chunk->at(i));
element(i)->fill_in(chunk->at(i), realloc_failures);
}
// Copy registers for callee-saved registers