# HG changeset patch # User Thomas Wuerthinger # Date 1309884922 -7200 # Node ID 5ca1332171c8e67aa458ca08ef3152106a9899c8 # Parent 3e89c4c5f37f9ea41fee2ae92a801fec88cac108 Fixed an issue in the HotSpot code for rethrowing an exception at deopt (wrong values on the expression stack caused a crash when GC and deopt happened at the same time). diff -r 3e89c4c5f37f -r 5ca1332171c8 src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Tue Jul 05 16:41:53 2011 +0200 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Tue Jul 05 18:55:22 2011 +0200 @@ -459,6 +459,7 @@ } while (should_repeat == true); if (h_method->method_data() != NULL) { + ResourceMark rm(thread); ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci); if (pdata != NULL) { int tstate0 = pdata->trap_state(); diff -r 3e89c4c5f37f -r 5ca1332171c8 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Tue Jul 05 16:41:53 2011 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Tue Jul 05 18:55:22 2011 +0200 @@ -1244,7 +1244,7 @@ if (trap_scope->rethrow_exception()) { if (TraceDeoptimization) { - tty->print_cr("Exception to be rethrown in the interpreter"); + tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", instanceKlass::cast(trap_method->method_holder())->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci); } GrowableArray* expressions = trap_scope->expressions(); ScopeValue* topOfStack = expressions->top(); diff -r 3e89c4c5f37f -r 5ca1332171c8 src/share/vm/runtime/vframeArray.cpp --- a/src/share/vm/runtime/vframeArray.cpp Tue Jul 05 16:41:53 2011 +0200 +++ b/src/share/vm/runtime/vframeArray.cpp Tue Jul 05 18:55:22 2011 +0200 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" +#include "code/scopeDesc.hpp" #include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -62,7 +63,7 @@ _method = vf->method(); _bci = vf->raw_bci(); _reexecute = vf->should_reexecute(); - + int index; // Get the monitors off-stack @@ -126,28 +127,37 @@ // Now the expressions off-stack // Same silliness as above - - StackValueCollection *exprs = vf->expressions(); - _expressions = new StackValueCollection(exprs->size()); - for(index = 0; index < exprs->size(); index++) { - StackValue* value = exprs->at(index); - switch(value->type()) { - case T_OBJECT: - assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); - // preserve object type - _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); - break; - case T_CONFLICT: - // A dead stack element. Will be initialized to null/zero. - // This can occur when the compiler emits a state in which stack - // elements are known to be dead (because of an imminent exception). - _expressions->add( new StackValue()); - break; - case T_INT: - _expressions->add( new StackValue(value->get_int())); - break; - default: - ShouldNotReachHere(); + bool rethrow_exception = vf->scope()->rethrow_exception(); + if (rethrow_exception) { + // (tw) Make sure there are only null pointers on the stack, because the stack values do not correspond to the GC map at the bytecode at which the exception is rethrown. + _expressions = new StackValueCollection(vf->method()->max_stack()); + assert(Thread::current()->has_pending_exception(), "just checking"); + for (int i=0; imethod()->max_stack(); ++i) { + _expressions->add( new StackValue()); + } + } else { + StackValueCollection *exprs = vf->expressions(); + _expressions = new StackValueCollection(exprs->size()); + for(index = 0; index < exprs->size(); index++) { + StackValue* value = exprs->at(index); + switch(value->type()) { + case T_OBJECT: + assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); + // preserve object type + _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); + break; + case T_CONFLICT: + // A dead stack element. Will be initialized to null/zero. + // This can occur when the compiler emits a state in which stack + // elements are known to be dead (because of an imminent exception). + _expressions->add( new StackValue()); + break; + case T_INT: + _expressions->add( new StackValue(value->get_int())); + break; + default: + ShouldNotReachHere(); + } } } } @@ -314,8 +324,7 @@ // only unpacks the part of the expression stack not used by callee // as parameters. The callee parameters are unpacked as part of the // callee locals. - int i; - for(i = 0; i < expressions()->size(); i++) { + for(int i = 0; i < expressions()->size(); i++) { StackValue *value = expressions()->at(i); intptr_t* addr = iframe()->interpreter_frame_expression_stack_at(i); switch(value->type()) { @@ -352,7 +361,7 @@ // Unpack the locals - for(i = 0; i < locals()->size(); i++) { + for(int i = 0; i < locals()->size(); i++) { StackValue *value = locals()->at(i); intptr_t* addr = iframe()->interpreter_frame_local_at(i); switch(value->type()) {