mirror of
https://github.com/corda/corda.git
synced 2025-01-01 02:36:44 +00:00
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:
parent
08d4fddbb4
commit
c3824c6844
21
classpath/java/lang/AbstractMethodError.java
Normal file
21
classpath/java/lang/AbstractMethodError.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -4,6 +4,7 @@ THUNK(findInterfaceMethodFromInstanceAndReference)
|
||||
THUNK(findSpecialMethodFromReference)
|
||||
THUNK(findStaticMethodFromReference)
|
||||
THUNK(findVirtualMethodFromReference)
|
||||
THUNK(getMethodAddress)
|
||||
THUNK(compareDoublesG)
|
||||
THUNK(compareDoublesL)
|
||||
THUNK(compareFloatsG)
|
||||
|
@ -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
1
vm.pro
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user