mirror of
https://github.com/corda/corda.git
synced 2025-02-01 08:48:09 +00:00
Merge pull request #327 from dicej/tryNative
add avian.Machine.tryNative
This commit is contained in:
commit
e1074c026c
@ -35,4 +35,33 @@ public abstract class Machine {
|
|||||||
return unsafe;
|
return unsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Short version: Don't use this function -- it's evil.
|
||||||
|
*
|
||||||
|
* Long version: This is kind of a poor man's, cross-platform
|
||||||
|
* version of Microsoft's Structured Exception Handling. The idea
|
||||||
|
* is that you can call a native function with the specified
|
||||||
|
* argument such that any OS signals raised (e.g. SIGSEGV, SIGBUS,
|
||||||
|
* SIGFPE, EXC_ACCESS_VIOLATION, etc.) prior to the function
|
||||||
|
* returning are converted into the appropriate Java exception
|
||||||
|
* (e.g. NullPointerException, ArithmeticException, etc.) and thrown
|
||||||
|
* from this method. This may be useful in very specific
|
||||||
|
* circumstances, e.g. to work around a bug in a library that would
|
||||||
|
* otherwise crash your app. On the other hand, you'd be much
|
||||||
|
* better off just fixing the library if possible.
|
||||||
|
*
|
||||||
|
* Caveats: The specified function should return quickly without
|
||||||
|
* blocking, since it will block critical VM features such as
|
||||||
|
* garbage collection. The implementation is equivalent to using
|
||||||
|
* setjmp/longjmp to achieve a non-local return from the signal
|
||||||
|
* handler, meaning C++ destructors and other cleanup code might not
|
||||||
|
* be run if a signal is raised. It might melt your keyboard and
|
||||||
|
* burn your fingertips. Caveat lector.
|
||||||
|
*
|
||||||
|
* @param function a function pointer of type int64_t (*)(int64_t)
|
||||||
|
* @param argument the argument to pass to the function
|
||||||
|
* @return the return value of the function
|
||||||
|
*/
|
||||||
|
public static native long tryNative(long function, long argument);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1119,6 +1119,7 @@ class Thread {
|
|||||||
static const unsigned ActiveFlag = 1 << 5;
|
static const unsigned ActiveFlag = 1 << 5;
|
||||||
static const unsigned SystemFlag = 1 << 6;
|
static const unsigned SystemFlag = 1 << 6;
|
||||||
static const unsigned JoinFlag = 1 << 7;
|
static const unsigned JoinFlag = 1 << 7;
|
||||||
|
static const unsigned TryNativeFlag = 1 << 8;
|
||||||
|
|
||||||
class Protector {
|
class Protector {
|
||||||
public:
|
public:
|
||||||
|
@ -309,6 +309,20 @@ extern "C" AVIAN_EXPORT void JNICALL
|
|||||||
|
|
||||||
#endif // AVIAN_HEAPDUMP
|
#endif // AVIAN_HEAPDUMP
|
||||||
|
|
||||||
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
|
Avian_avian_Machine_tryNative(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t function;
|
||||||
|
memcpy(&function, arguments, 8);
|
||||||
|
int64_t argument;
|
||||||
|
memcpy(&argument, arguments + 2, 8);
|
||||||
|
|
||||||
|
t->flags |= Thread::TryNativeFlag;
|
||||||
|
THREAD_RESOURCE0(t, t->flags &= ~Thread::TryNativeFlag);
|
||||||
|
|
||||||
|
return reinterpret_cast<int64_t (*)(int64_t)>(function)(argument);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_Runtime_exit(Thread* t, object, uintptr_t* arguments)
|
Avian_java_lang_Runtime_exit(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
|
@ -8164,6 +8164,18 @@ class SignalHandler : public SignalRegistrar::Handler {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setException(MyThread* t) {
|
||||||
|
if (ensure(t, pad(fixedSize) + traceSize(t))) {
|
||||||
|
atomicOr(&(t->flags), Thread::TracingFlag);
|
||||||
|
t->exception = makeThrowable(t, type);
|
||||||
|
atomicAnd(&(t->flags), ~Thread::TracingFlag);
|
||||||
|
} else {
|
||||||
|
// not enough memory available for a new exception and stack
|
||||||
|
// trace -- use a preallocated instance instead
|
||||||
|
t->exception = (vm::roots(t)->*exc)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool handleSignal(void** ip,
|
virtual bool handleSignal(void** ip,
|
||||||
void** frame,
|
void** frame,
|
||||||
void** stack,
|
void** stack,
|
||||||
@ -8171,8 +8183,23 @@ class SignalHandler : public SignalRegistrar::Handler {
|
|||||||
{
|
{
|
||||||
MyThread* t = static_cast<MyThread*>(m->localThread->get());
|
MyThread* t = static_cast<MyThread*>(m->localThread->get());
|
||||||
if (t and t->state == Thread::ActiveState) {
|
if (t and t->state == Thread::ActiveState) {
|
||||||
GcMethod* node = methodForIp(t, *ip);
|
if (t->flags & Thread::TryNativeFlag) {
|
||||||
if (node) {
|
setException(t);
|
||||||
|
|
||||||
|
popResources(t);
|
||||||
|
|
||||||
|
GcContinuation* continuation;
|
||||||
|
findUnwindTarget(t, ip, frame, stack, &continuation);
|
||||||
|
|
||||||
|
t->trace->targetMethod = 0;
|
||||||
|
t->trace->nativeMethod = 0;
|
||||||
|
|
||||||
|
transition(t, *ip, *stack, continuation, t->trace);
|
||||||
|
|
||||||
|
*thread = t;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (methodForIp(t, *ip)) {
|
||||||
// add one to the IP since findLineNumber will subtract one
|
// add one to the IP since findLineNumber will subtract one
|
||||||
// when we make the trace:
|
// when we make the trace:
|
||||||
MyThread::TraceContext context(
|
MyThread::TraceContext context(
|
||||||
@ -8182,22 +8209,14 @@ class SignalHandler : public SignalRegistrar::Handler {
|
|||||||
t->continuation,
|
t->continuation,
|
||||||
t->trace);
|
t->trace);
|
||||||
|
|
||||||
if (ensure(t, pad(fixedSize) + traceSize(t))) {
|
setException(t);
|
||||||
atomicOr(&(t->flags), Thread::TracingFlag);
|
|
||||||
t->exception = makeThrowable(t, type);
|
|
||||||
atomicAnd(&(t->flags), ~Thread::TracingFlag);
|
|
||||||
} else {
|
|
||||||
// not enough memory available for a new exception and stack
|
|
||||||
// trace -- use a preallocated instance instead
|
|
||||||
t->exception = (vm::roots(t)->*exc)();
|
|
||||||
}
|
|
||||||
|
|
||||||
// printTrace(t, t->exception);
|
// printTrace(t, t->exception);
|
||||||
|
|
||||||
GcContinuation* continuation;
|
GcContinuation* continuation;
|
||||||
findUnwindTarget(t, ip, frame, stack, &continuation);
|
findUnwindTarget(t, ip, frame, stack, &continuation);
|
||||||
|
|
||||||
transition(t, ip, stack, continuation, t->trace);
|
transition(t, *ip, *stack, continuation, t->trace);
|
||||||
|
|
||||||
*thread = t;
|
*thread = t;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user