fix crash when encountering invokespecial call to abstract method

We must throw an AbstractMethodError when such a call is executed (not
when the call is compiled), so we compile this case as a call to a
thunk which throws such an error.
This commit is contained in:
Joel Dice
2011-07-17 19:54:55 -06:00
parent 08d4fddbb4
commit c3824c6844
5 changed files with 93 additions and 1 deletions

View File

@ -2344,6 +2344,26 @@ findVirtualMethodFromReference(MyThread* t, object pair, object instance)
return prepareMethodForCall(t, target);
}
bool
methodAbstract(Thread* t, object method)
{
return methodCode(t, method) == 0
and (methodFlags(t, method) & ACC_NATIVE) == 0;
}
int64_t
getMethodAddress(MyThread* t, object target)
{
if (methodAbstract(t, target)) {
throwNew(t, Machine::AbstractMethodErrorType, "%s.%s%s",
&byteArrayBody(t, className(t, methodClass(t, target)), 0),
&byteArrayBody(t, methodName(t, target), 0),
&byteArrayBody(t, methodSpec(t, target), 0));
} else {
return prepareMethodForCall(t, target);
}
}
int64_t
getJClassFromReference(MyThread* t, object pair)
{
@ -3440,6 +3460,48 @@ compileDirectReferenceInvoke(MyThread* t, Frame* frame, Thunk thunk,
reference, isStatic, tailCall);
}
void
compileAbstractInvoke(MyThread* t, Frame* frame, Compiler::Operand* method,
object target, bool tailCall)
{
unsigned parameterFootprint = methodParameterFootprint(t, target);
int returnCode = methodReturnCode(t, target);
unsigned rSize = resultSize(t, returnCode);
Compiler::Operand* result = frame->c->stackCall
(method,
tailCall ? Compiler::TailJump : 0,
frame->trace(0, 0),
rSize,
operandTypeForFieldCode(t, returnCode),
parameterFootprint);
frame->pop(parameterFootprint);
if (rSize) {
pushReturnValue(t, frame, returnCode, result);
}
}
void
compileDirectAbstractInvoke(MyThread* t, Frame* frame, Thunk thunk,
object target, bool tailCall)
{
Compiler* c = frame->c;
compileAbstractInvoke
(t, frame, c->call
(c->constant(getThunk(t, thunk), Compiler::AddressType),
0,
frame->trace(0, 0),
BytesPerWord,
Compiler::AddressType,
2, c->register_(t->arch->thread()), frame->append(target)),
target, tailCall);
}
void
handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function)
{
@ -4844,7 +4906,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
bool tailCall = isTailCall(t, code, ip, context->method, target);
compileDirectInvoke(t, frame, target, tailCall);
if (UNLIKELY(methodAbstract(t, target))) {
compileDirectAbstractInvoke
(t, frame, getMethodAddressThunk, target, tailCall);
} else {
compileDirectInvoke(t, frame, target, tailCall);
}
} else {
compileDirectReferenceInvoke
(t, frame, findSpecialMethodFromReferenceThunk, reference, false,

View File

@ -4,6 +4,7 @@ THUNK(findInterfaceMethodFromInstanceAndReference)
THUNK(findSpecialMethodFromReference)
THUNK(findStaticMethodFromReference)
THUNK(findVirtualMethodFromReference)
THUNK(getMethodAddress)
THUNK(compareDoublesG)
THUNK(compareDoublesL)
THUNK(compareFloatsG)

View File

@ -249,6 +249,8 @@
(type incompatibleClassChangeError java/lang/IncompatibleClassChangeError)
(type abstractMethodError java/lang/AbstractMethodError)
(type noSuchFieldError java/lang/NoSuchFieldError)
(type noSuchMethodError java/lang/NoSuchMethodError)