mirror of
https://github.com/corda/corda.git
synced 2025-01-05 20:54:13 +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);
|
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
|
int64_t
|
||||||
getJClassFromReference(MyThread* t, object pair)
|
getJClassFromReference(MyThread* t, object pair)
|
||||||
{
|
{
|
||||||
@ -3440,6 +3460,48 @@ compileDirectReferenceInvoke(MyThread* t, Frame* frame, Thunk thunk,
|
|||||||
reference, isStatic, tailCall);
|
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
|
void
|
||||||
handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function)
|
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);
|
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 {
|
} else {
|
||||||
compileDirectReferenceInvoke
|
compileDirectReferenceInvoke
|
||||||
(t, frame, findSpecialMethodFromReferenceThunk, reference, false,
|
(t, frame, findSpecialMethodFromReferenceThunk, reference, false,
|
||||||
|
@ -4,6 +4,7 @@ THUNK(findInterfaceMethodFromInstanceAndReference)
|
|||||||
THUNK(findSpecialMethodFromReference)
|
THUNK(findSpecialMethodFromReference)
|
||||||
THUNK(findStaticMethodFromReference)
|
THUNK(findStaticMethodFromReference)
|
||||||
THUNK(findVirtualMethodFromReference)
|
THUNK(findVirtualMethodFromReference)
|
||||||
|
THUNK(getMethodAddress)
|
||||||
THUNK(compareDoublesG)
|
THUNK(compareDoublesG)
|
||||||
THUNK(compareDoublesL)
|
THUNK(compareDoublesL)
|
||||||
THUNK(compareFloatsG)
|
THUNK(compareFloatsG)
|
||||||
|
@ -249,6 +249,8 @@
|
|||||||
|
|
||||||
(type incompatibleClassChangeError java/lang/IncompatibleClassChangeError)
|
(type incompatibleClassChangeError java/lang/IncompatibleClassChangeError)
|
||||||
|
|
||||||
|
(type abstractMethodError java/lang/AbstractMethodError)
|
||||||
|
|
||||||
(type noSuchFieldError java/lang/NoSuchFieldError)
|
(type noSuchFieldError java/lang/NoSuchFieldError)
|
||||||
|
|
||||||
(type noSuchMethodError java/lang/NoSuchMethodError)
|
(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.StackOverflowError
|
||||||
-keep public class java.lang.NoSuchFieldError
|
-keep public class java.lang.NoSuchFieldError
|
||||||
-keep public class java.lang.NoSuchMethodError
|
-keep public class java.lang.NoSuchMethodError
|
||||||
|
-keep public class java.lang.AbstractMethodError
|
||||||
-keep public class java.lang.UnsatisfiedLinkError
|
-keep public class java.lang.UnsatisfiedLinkError
|
||||||
-keep public class java.lang.ExceptionInInitializerError
|
-keep public class java.lang.ExceptionInInitializerError
|
||||||
-keep public class java.lang.OutOfMemoryError
|
-keep public class java.lang.OutOfMemoryError
|
||||||
|
Loading…
Reference in New Issue
Block a user