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

@ -0,0 +1,21 @@
/* Copyright (c) 2011, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.lang;
public class AbstractMethodError extends IncompatibleClassChangeError {
public AbstractMethodError() {
super();
}
public AbstractMethodError(String message) {
super(message);
}
}

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)

1
vm.pro
View File

@ -62,6 +62,7 @@
-keep public class java.lang.StackOverflowError
-keep public class java.lang.NoSuchFieldError
-keep public class java.lang.NoSuchMethodError
-keep public class java.lang.AbstractMethodError
-keep public class java.lang.UnsatisfiedLinkError
-keep public class java.lang.ExceptionInInitializerError
-keep public class java.lang.OutOfMemoryError