corda/src/jnienv.cpp

3787 lines
101 KiB
C++
Raw Normal View History

2014-04-21 02:14:48 +00:00
/* Copyright (c) 2008-2014, 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. */
#include "avian/jnienv.h"
#include "avian/machine.h"
#include "avian/util.h"
#include "avian/processor.h"
#include "avian/constants.h"
2013-02-20 05:56:05 +00:00
#include <avian/util/runtime-array.h>
using namespace vm;
namespace {
2010-04-15 17:11:10 +00:00
namespace local {
2014-07-11 15:50:18 +00:00
jint JNICALL AttachCurrentThread(Machine* m, Thread** t, void*)
{
*t = static_cast<Thread*>(m->localThread->get());
if (*t == 0) {
*t = attachThread(m, false);
}
return 0;
}
2014-07-11 15:50:18 +00:00
jint JNICALL AttachCurrentThreadAsDaemon(Machine* m, Thread** t, void*)
{
*t = static_cast<Thread*>(m->localThread->get());
if (*t == 0) {
*t = attachThread(m, true);
}
return 0;
}
2014-07-11 15:50:18 +00:00
jint JNICALL DetachCurrentThread(Machine* m)
{
Thread* t = static_cast<Thread*>(m->localThread->get());
if (t) {
// todo: detaching the root thread seems to cause stability
// problems which I haven't yet had a chance to investigate
// thoroughly. Meanwhile, we just ignore requests to detach it,
// which leaks a bit of memory but should be harmless otherwise.
if (m->rootThread != t) {
m->localThread->set(0);
ACQUIRE_RAW(t, t->m->stateLock);
enter(t, Thread::ActiveState);
2014-06-28 23:24:24 +00:00
t->javaThread->peer() = 0;
enter(t, Thread::ZombieState);
t->state = Thread::JoinedState;
}
return 0;
} else {
return -1;
}
}
2014-07-11 15:50:18 +00:00
uint64_t destroyJavaVM(Thread* t, uintptr_t*)
{
// wait for other non-daemon threads to exit
2014-07-11 15:50:18 +00:00
{
ACQUIRE(t, t->m->stateLock);
while (t->m->liveCount - t->m->daemonCount > 1) {
t->m->stateLock->wait(t->systemThread, 0);
}
}
2014-07-11 15:50:18 +00:00
{
ENTER(t, Thread::ActiveState);
t->m->classpath->shutDown(t);
}
// wait again in case the Classpath::shutDown process started new
// threads:
2014-07-11 15:50:18 +00:00
{
ACQUIRE(t, t->m->stateLock);
while (t->m->liveCount - t->m->daemonCount > 1) {
t->m->stateLock->wait(t->systemThread, 0);
}
enter(t, Thread::ExclusiveState);
}
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
shutDown(t);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return 1;
}
2014-07-11 15:50:18 +00:00
jint JNICALL DestroyJavaVM(Machine* m)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
2014-07-11 15:50:18 +00:00
Thread* t;
AttachCurrentThread(m, &t, 0);
if (runRaw(t, destroyJavaVM, 0)) {
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
t->exit();
return 0;
} else {
return -1;
}
}
2014-07-11 15:50:18 +00:00
jint JNICALL GetEnv(Machine* m, Thread** t, jint version)
{
*t = static_cast<Thread*>(m->localThread->get());
if (*t) {
if (version <= JNI_VERSION_1_6) {
return AVIAN_JNI_OK;
} else {
return AVIAN_JNI_EVERSION;
}
} else {
return AVIAN_JNI_EDETACHED;
}
}
2014-07-11 15:50:18 +00:00
jint JNICALL GetVersion(Thread* t)
2009-06-22 22:25:13 +00:00
{
ENTER(t, Thread::ActiveState);
return JNI_VERSION_1_6;
}
2014-07-11 15:50:18 +00:00
jsize JNICALL GetStringLength(Thread* t, jstring s)
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
return (*s)->length(t);
}
2014-07-11 15:50:18 +00:00
const jchar* JNICALL GetStringChars(Thread* t, jstring s, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
2014-07-11 15:47:57 +00:00
jchar* chars = static_cast<jchar*>(
t->m->heap->allocate(((*s)->length(t) + 1) * sizeof(jchar)));
2014-06-29 02:44:36 +00:00
stringChars(t, *s, chars);
2014-07-11 15:50:18 +00:00
if (isCopy)
*isCopy = true;
return chars;
}
2014-07-11 15:50:18 +00:00
void JNICALL ReleaseStringChars(Thread* t, jstring s, const jchar* chars)
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
t->m->heap->free(chars, ((*s)->length(t) + 1) * sizeof(jchar));
}
void JNICALL
2014-07-11 15:50:18 +00:00
GetStringRegion(Thread* t, jstring s, jsize start, jsize length, jchar* dst)
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
stringChars(t, *s, start, length, dst);
}
2014-07-11 15:50:18 +00:00
const jchar* JNICALL GetStringCritical(Thread* t, jstring s, jboolean* isCopy)
{
if (t->criticalLevel == 0) {
enter(t, Thread::ActiveState);
}
2014-07-11 15:50:18 +00:00
++t->criticalLevel;
if (isCopy) {
*isCopy = true;
}
2014-05-29 04:17:25 +00:00
object data = (*s)->data();
2014-05-29 04:17:25 +00:00
if (objectClass(t, data) == type(t, GcByteArray::Type)) {
return GetStringChars(t, s, isCopy);
} else {
2014-06-29 02:44:36 +00:00
return &cast<GcCharArray>(t, data)->body()[(*s)->offset(t)];
}
}
2014-07-11 15:50:18 +00:00
void JNICALL ReleaseStringCritical(Thread* t, jstring s, const jchar* chars)
{
2014-06-29 02:44:36 +00:00
if (objectClass(t, (*s)->data()) == type(t, GcByteArray::Type)) {
ReleaseStringChars(t, s, chars);
}
2014-07-11 15:50:18 +00:00
if ((--t->criticalLevel) == 0) {
enter(t, Thread::IdleState);
}
}
2014-07-11 15:50:18 +00:00
jsize JNICALL GetStringUTFLength(Thread* t, jstring s)
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
return stringUTFLength(t, *s);
}
2014-07-11 15:50:18 +00:00
const char* JNICALL GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
int length = stringUTFLength(t, *s);
2014-07-11 15:50:18 +00:00
char* chars = static_cast<char*>(t->m->heap->allocate(length + 1));
2014-06-29 02:44:36 +00:00
stringUTFChars(t, *s, chars, length);
2014-07-11 15:50:18 +00:00
if (isCopy)
*isCopy = true;
return chars;
}
2014-07-11 15:50:18 +00:00
void JNICALL ReleaseStringUTFChars(Thread* t, jstring s, const char* chars)
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
t->m->heap->free(chars, stringUTFLength(t, *s) + 1);
}
2014-07-11 15:50:18 +00:00
void JNICALL GetStringUTFRegion(Thread* t,
jstring s,
jsize start,
jsize length,
char* dst)
{
ENTER(t, Thread::ActiveState);
2014-07-11 15:50:18 +00:00
stringUTFChars(
t, *s, start, length, dst, stringUTFLength(t, *s, start, length));
}
2014-07-11 15:50:18 +00:00
jsize JNICALL GetArrayLength(Thread* t, jarray array)
{
ENTER(t, Thread::ActiveState);
2013-02-11 00:38:51 +00:00
return fieldAtOffset<uintptr_t>(*array, BytesPerWord);
}
2014-07-11 15:50:18 +00:00
uint64_t newString(Thread* t, uintptr_t* arguments)
2007-10-26 21:23:54 +00:00
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
const jchar* chars = reinterpret_cast<const jchar*>(arguments[0]);
jsize size = arguments[1];
2007-10-26 21:23:54 +00:00
2014-06-29 02:44:36 +00:00
GcCharArray* a = makeCharArray(t, size);
2007-10-26 21:23:54 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy(a->body().begin(), chars, size * sizeof(jchar));
2007-10-26 21:23:54 +00:00
}
2014-06-29 02:44:36 +00:00
return reinterpret_cast<uint64_t>(
2014-07-11 15:47:57 +00:00
makeLocalReference(t, t->m->classpath->makeString(t, a, 0, size)));
2007-10-26 21:23:54 +00:00
}
2014-07-11 15:50:18 +00:00
jstring JNICALL NewString(Thread* t, const jchar* chars, jsize size)
2007-07-07 23:47:35 +00:00
{
2014-07-11 15:50:18 +00:00
if (chars == 0)
return 0;
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(chars), static_cast<uintptr_t>(size)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jstring>(run(t, newString, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t newStringUTF(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
const char* chars = reinterpret_cast<const char*>(arguments[0]);
2007-07-07 23:47:35 +00:00
object array = parseUtf8(t, chars, strlen(chars));
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uint64_t>(makeLocalReference(
t,
t->m->classpath->makeString(
t, array, 0, fieldAtOffset<uintptr_t>(array, BytesPerWord) - 1)));
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2014-07-11 15:50:18 +00:00
jstring JNICALL NewStringUTF(Thread* t, const char* chars)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
2014-07-11 15:50:18 +00:00
if (chars == 0)
return 0;
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(chars)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jstring>(run(t, newStringUTF, arguments));
2007-07-07 23:47:35 +00:00
}
2014-07-11 15:50:18 +00:00
void replace(int a, int b, const char* in, int8_t* out)
{
while (*in) {
*out = (*in == a ? b : *in);
2014-07-11 15:50:18 +00:00
++in;
++out;
}
*out = 0;
}
2014-07-11 15:50:18 +00:00
uint64_t defineClass(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jobject loader = reinterpret_cast<jobject>(arguments[0]);
const uint8_t* buffer = reinterpret_cast<const uint8_t*>(arguments[1]);
jsize length = arguments[2];
2014-05-29 04:17:25 +00:00
return reinterpret_cast<uint64_t>(makeLocalReference(
t,
2014-07-11 15:47:57 +00:00
getJClass(
t,
cast<GcClass>(t,
defineClass(t,
loader ? cast<GcClassLoader>(t, *loader)
: roots(t)->bootLoader(),
buffer,
length)))));
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2014-07-11 15:50:18 +00:00
jclass JNICALL DefineClass(Thread* t,
const char*,
jobject loader,
const jbyte* buffer,
jsize length)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(loader),
reinterpret_cast<uintptr_t>(buffer),
static_cast<uintptr_t>(length)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jclass>(run(t, defineClass, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t findClass(Thread* t, uintptr_t* arguments)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
const char* name = reinterpret_cast<const char*>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcByteArray* n = makeByteArray(t, strlen(name) + 1);
replace('.', '/', name, n->body().begin());
2014-05-29 04:17:25 +00:00
GcMethod* caller = getCaller(t, 0);
2014-06-30 01:44:41 +00:00
GcClass* c
= resolveClass(t,
caller ? t->m->classpath->libraryClassLoader(t, caller)
: roots(t)->appLoader(),
n);
if (t->m->classpath->mayInitClasses()) {
PROTECT(t, c);
initClass(t, c);
}
return reinterpret_cast<uint64_t>(makeLocalReference(t, getJClass(t, c)));
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2014-07-11 15:50:18 +00:00
jclass JNICALL FindClass(Thread* t, const char* name)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(name)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jclass>(run(t, findClass, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t throwNew(Thread* t, uintptr_t* arguments)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jclass c = reinterpret_cast<jclass>(arguments[0]);
const char* message = reinterpret_cast<const char*>(arguments[1]);
2014-06-29 02:44:36 +00:00
GcString* m = 0;
PROTECT(t, m);
if (message) {
2014-06-29 02:44:36 +00:00
m = makeString(t, "%s", message);
}
object trace = makeTrace(t);
PROTECT(t, trace);
2014-06-29 02:44:36 +00:00
t->exception = cast<GcThrowable>(t, make(t, (*c)->vmClass()));
2014-06-26 02:17:27 +00:00
t->exception->setMessage(t, m);
t->exception->setTrace(t, trace);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return 1;
}
2014-07-11 15:50:18 +00:00
jint JNICALL ThrowNew(Thread* t, jclass c, const char* message)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
if (t->exception) {
return -1;
}
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(c), reinterpret_cast<uintptr_t>(message)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, throwNew, arguments) ? 0 : -1;
}
2014-07-11 15:50:18 +00:00
jint JNICALL Throw(Thread* t, jthrowable throwable)
{
if (t->exception) {
return -1;
}
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
t->exception = *throwable;
return 0;
}
2014-07-11 15:50:18 +00:00
jobject JNICALL NewLocalRef(Thread* t, jobject o)
2014-05-29 04:17:25 +00:00
{
2012-12-20 16:05:30 +00:00
ENTER(t, Thread::ActiveState);
return makeLocalReference(t, *o);
}
2014-07-11 15:50:18 +00:00
void JNICALL DeleteLocalRef(Thread* t, jobject r)
2007-08-14 13:27:10 +00:00
{
2007-11-29 15:04:07 +00:00
ENTER(t, Thread::ActiveState);
disposeLocalReference(t, r);
2007-08-14 13:27:10 +00:00
}
2014-07-11 15:50:18 +00:00
jboolean JNICALL ExceptionCheck(Thread* t)
{
return t->exception != 0;
}
2014-07-11 15:50:18 +00:00
uint64_t getObjectClass(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-07-11 15:47:57 +00:00
return reinterpret_cast<uint64_t>(
makeLocalReference(t, getJClass(t, objectClass(t, *o))));
}
2014-07-11 15:50:18 +00:00
jclass JNICALL GetObjectClass(Thread* t, jobject o)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o)};
return reinterpret_cast<jclass>(run(t, getObjectClass, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t getSuperclass(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcClass* class_ = (*reinterpret_cast<jclass>(arguments[0]))->vmClass();
if (class_->flags() & ACC_INTERFACE) {
return 0;
} else {
2014-06-29 02:44:36 +00:00
GcClass* super = class_->super();
2014-07-11 15:50:18 +00:00
return super ? reinterpret_cast<uint64_t>(
makeLocalReference(t, getJClass(t, super)))
: 0;
}
}
2014-07-11 15:50:18 +00:00
jclass JNICALL GetSuperclass(Thread* t, jclass c)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c)};
2007-09-07 23:20:21 +00:00
return reinterpret_cast<jclass>(run(t, getSuperclass, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t isInstanceOf(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
jclass c = reinterpret_cast<jclass>(arguments[1]);
2014-06-29 02:44:36 +00:00
return instanceOf(t, (*c)->vmClass(), *o);
}
2014-07-11 15:50:18 +00:00
jboolean JNICALL IsInstanceOf(Thread* t, jobject o, jclass c)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), reinterpret_cast<uintptr_t>(c)};
2007-09-07 23:20:21 +00:00
return run(t, isInstanceOf, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t isAssignableFrom(Thread* t, uintptr_t* arguments)
{
jclass b = reinterpret_cast<jclass>(arguments[0]);
jclass a = reinterpret_cast<jclass>(arguments[1]);
2014-06-29 02:44:36 +00:00
return isAssignableFrom(t, (*a)->vmClass(), (*b)->vmClass());
}
2014-07-11 15:50:18 +00:00
jboolean JNICALL IsAssignableFrom(Thread* t, jclass b, jclass a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(b), reinterpret_cast<uintptr_t>(a)};
return run(t, isAssignableFrom, arguments);
}
2014-07-11 15:47:57 +00:00
GcMethod* findMethod(Thread* t, jclass c, const char* name, const char* spec)
{
2014-06-28 23:24:24 +00:00
GcByteArray* n = makeByteArray(t, "%s", name);
PROTECT(t, n);
2014-06-28 23:24:24 +00:00
GcByteArray* s = makeByteArray(t, "%s", spec);
2014-06-29 02:44:36 +00:00
return vm::findMethod(t, (*c)->vmClass(), n, s);
}
2014-07-11 15:47:57 +00:00
jint methodID(Thread* t, GcMethod* method)
{
2014-05-29 04:17:25 +00:00
int id = method->nativeID();
loadMemoryBarrier();
if (id == 0) {
PROTECT(t, method);
ACQUIRE(t, t->m->referenceLock);
2014-05-29 04:17:25 +00:00
if (method->nativeID() == 0) {
2014-07-11 15:47:57 +00:00
GcVector* v = vectorAppend(t, roots(t)->jNIMethodTable(), method);
2014-06-30 01:44:41 +00:00
// sequence point, for gc (don't recombine statements)
2014-06-26 02:17:27 +00:00
roots(t)->setJNIMethodTable(t, v);
storeStoreMemoryBarrier();
2014-06-30 01:44:41 +00:00
method->nativeID() = roots(t)->jNIMethodTable()->size();
}
}
2014-05-29 04:17:25 +00:00
return method->nativeID();
}
2014-07-11 15:50:18 +00:00
uint64_t getMethodID(Thread* t, uintptr_t* arguments)
2007-09-07 23:20:21 +00:00
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jclass c = reinterpret_cast<jclass>(arguments[0]);
const char* name = reinterpret_cast<const char*>(arguments[1]);
const char* spec = reinterpret_cast<const char*>(arguments[2]);
2007-09-07 23:20:21 +00:00
2014-05-29 04:17:25 +00:00
GcMethod* method = findMethod(t, c, name, spec);
assertT(t, (method->flags() & ACC_STATIC) == 0);
2014-05-29 04:17:25 +00:00
return methodID(t, method);
2007-09-07 23:20:21 +00:00
}
2007-09-07 23:20:21 +00:00
jmethodID JNICALL
2014-07-11 15:50:18 +00:00
GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c),
reinterpret_cast<uintptr_t>(name),
reinterpret_cast<uintptr_t>(spec)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, getMethodID, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticMethodID(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jclass c = reinterpret_cast<jclass>(arguments[0]);
const char* name = reinterpret_cast<const char*>(arguments[1]);
const char* spec = reinterpret_cast<const char*>(arguments[2]);
2014-05-29 04:17:25 +00:00
GcMethod* method = findMethod(t, c, name, spec);
2007-09-07 23:20:21 +00:00
assertT(t, method->flags() & ACC_STATIC);
return methodID(t, method);
}
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jmethodID JNICALL
2014-07-11 15:50:18 +00:00
GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c),
reinterpret_cast<uintptr_t>(name),
reinterpret_cast<uintptr_t>(spec)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, getStaticMethodID, arguments);
}
2014-07-11 15:47:57 +00:00
GcMethod* getMethod(Thread* t, jmethodID m)
{
assertT(t, m);
2014-07-11 15:47:57 +00:00
GcMethod* method
= cast<GcMethod>(t, roots(t)->jNIMethodTable()->body()[m - 1]);
2008-04-01 17:37:59 +00:00
assertT(t, (method->flags() & ACC_STATIC) == 0);
2008-04-01 17:37:59 +00:00
return method;
}
2014-07-11 15:50:18 +00:00
uint64_t newObjectV(Thread* t, uintptr_t* arguments)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jclass c = reinterpret_cast<jclass>(arguments[0]);
jmethodID m = arguments[1];
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
2014-06-29 02:44:36 +00:00
object o = make(t, (*c)->vmClass());
PROTECT(t, o);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
t->m->processor->invokeList(t, getMethod(t, m), o, true, *a);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<uint64_t>(makeLocalReference(t, o));
}
2014-07-11 15:50:18 +00:00
jobject JNICALL NewObjectV(Thread* t, jclass c, jmethodID m, va_list a)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jobject>(run(t, newObjectV, arguments));
}
2014-07-11 15:50:18 +00:00
jobject JNICALL NewObject(Thread* t, jclass c, jmethodID m, ...)
{
va_list a;
va_start(a, m);
2007-11-29 15:04:07 +00:00
jobject r = NewObjectV(t, c, m, a);
va_end(a);
return r;
}
2014-07-11 15:50:18 +00:00
uint64_t newObjectA(Thread* t, uintptr_t* arguments)
{
jclass c = reinterpret_cast<jclass>(arguments[0]);
jmethodID m = arguments[1];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
2014-06-29 02:44:36 +00:00
object o = make(t, (*c)->vmClass());
PROTECT(t, o);
t->m->processor->invokeArray(t, getMethod(t, m), o, a);
return reinterpret_cast<uint64_t>(makeLocalReference(t, o));
}
2014-07-11 15:47:57 +00:00
jobject JNICALL NewObjectA(Thread* t, jclass c, jmethodID m, const jvalue* a)
{
2014-07-11 15:47:57 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(c), m, reinterpret_cast<uintptr_t>(a)};
return reinterpret_cast<jobject>(run(t, newObjectA, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t callObjectMethodV(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jmethodID m = arguments[1];
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uint64_t>(makeLocalReference(
t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a)));
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2014-07-11 15:50:18 +00:00
jobject JNICALL CallObjectMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jobject>(run(t, callObjectMethodV, arguments));
}
2014-07-11 15:50:18 +00:00
jobject JNICALL CallObjectMethod(Thread* t, jobject o, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jobject r = CallObjectMethodV(t, o, m, a);
va_end(a);
return r;
}
2014-07-11 15:50:18 +00:00
uint64_t callObjectMethodA(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
jmethodID m = arguments[1];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uint64_t>(makeLocalReference(
t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a)));
}
jobject JNICALL
2014-07-11 15:50:18 +00:00
CallObjectMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
return reinterpret_cast<jobject>(run(t, callObjectMethodA, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t callIntMethodV(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jmethodID m = arguments[1];
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
2014-07-11 15:47:57 +00:00
return cast<GcInt>(
t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a))
->value();
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
jboolean JNICALL
2014-07-11 15:50:18 +00:00
CallBooleanMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callIntMethodV, arguments) != 0;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jboolean JNICALL CallBooleanMethod(Thread* t, jobject o, jmethodID m, ...)
2007-09-07 23:20:21 +00:00
{
va_list a;
va_start(a, m);
jboolean r = CallBooleanMethodV(t, o, m, a);
va_end(a);
return r;
}
2014-07-11 15:50:18 +00:00
uint64_t callIntMethodA(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
jmethodID m = arguments[1];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
2014-07-11 15:47:57 +00:00
return cast<GcInt>(t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a))
->value();
}
jboolean JNICALL
2014-07-11 15:50:18 +00:00
CallBooleanMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
return run(t, callIntMethodA, arguments) != 0;
}
2014-07-11 15:50:18 +00:00
jbyte JNICALL CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callIntMethodV, arguments);
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jbyte JNICALL CallByteMethod(Thread* t, jobject o, jmethodID m, ...)
2007-09-07 23:20:21 +00:00
{
va_list a;
va_start(a, m);
jbyte r = CallByteMethodV(t, o, m, a);
va_end(a);
return r;
}
jbyte JNICALL
2014-07-11 15:50:18 +00:00
CallByteMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
return run(t, callIntMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
jchar JNICALL CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callIntMethodV, arguments);
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jchar JNICALL CallCharMethod(Thread* t, jobject o, jmethodID m, ...)
2007-09-07 23:20:21 +00:00
{
va_list a;
va_start(a, m);
jchar r = CallCharMethodV(t, o, m, a);
va_end(a);
return r;
}
jchar JNICALL
2014-07-11 15:50:18 +00:00
CallCharMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
return run(t, callIntMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
jshort JNICALL CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callIntMethodV, arguments);
}
2014-07-11 15:50:18 +00:00
jshort JNICALL CallShortMethod(Thread* t, jobject o, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jshort r = CallShortMethodV(t, o, m, a);
va_end(a);
return r;
}
jshort JNICALL
2014-07-11 15:50:18 +00:00
CallShortMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
return run(t, callIntMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
jint JNICALL CallIntMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callIntMethodV, arguments);
}
2014-07-11 15:50:18 +00:00
jint JNICALL CallIntMethod(Thread* t, jobject o, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jint r = CallIntMethodV(t, o, m, a);
va_end(a);
return r;
}
2014-07-11 15:50:18 +00:00
jint JNICALL CallIntMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
return run(t, callIntMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t callLongMethodV(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jmethodID m = arguments[1];
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
2014-07-11 15:47:57 +00:00
return cast<GcLong>(
t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a))
->value();
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2014-07-11 15:50:18 +00:00
jlong JNICALL CallLongMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callLongMethodV, arguments);
}
2014-07-11 15:50:18 +00:00
jlong JNICALL CallLongMethod(Thread* t, jobject o, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jlong r = CallLongMethodV(t, o, m, a);
va_end(a);
return r;
}
2014-07-11 15:50:18 +00:00
uint64_t callLongMethodA(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
jmethodID m = arguments[1];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
2014-07-11 15:47:57 +00:00
return cast<GcLong>(t,
t->m->processor->invokeArray(t, getMethod(t, m), *o, a))
->value();
}
jlong JNICALL
2014-07-11 15:50:18 +00:00
CallLongMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
return run(t, callLongMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
jfloat JNICALL CallFloatMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return bitsToFloat(run(t, callIntMethodV, arguments));
}
2014-07-11 15:50:18 +00:00
jfloat JNICALL CallFloatMethod(Thread* t, jobject o, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jfloat r = CallFloatMethodV(t, o, m, a);
va_end(a);
return r;
}
jfloat JNICALL
2014-07-11 15:50:18 +00:00
CallFloatMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
return bitsToFloat(run(t, callIntMethodA, arguments));
}
2014-07-11 15:50:18 +00:00
jdouble JNICALL CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return bitsToDouble(run(t, callLongMethodV, arguments));
}
2014-07-11 15:50:18 +00:00
jdouble JNICALL CallDoubleMethod(Thread* t, jobject o, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jdouble r = CallDoubleMethodV(t, o, m, a);
va_end(a);
return r;
}
jdouble JNICALL
2014-07-11 15:50:18 +00:00
CallDoubleMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
return bitsToDouble(run(t, callLongMethodA, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t callVoidMethodV(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jmethodID m = arguments[1];
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return 0;
}
2014-07-11 15:50:18 +00:00
void JNICALL CallVoidMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
run(t, callVoidMethodV, arguments);
}
2014-07-11 15:50:18 +00:00
void JNICALL CallVoidMethod(Thread* t, jobject o, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
CallVoidMethodV(t, o, m, a);
va_end(a);
}
2014-07-11 15:50:18 +00:00
uint64_t callVoidMethodA(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
jmethodID m = arguments[1];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
t->m->processor->invokeArray(t, getMethod(t, m), *o, a);
return 0;
}
2014-07-11 15:50:18 +00:00
void JNICALL CallVoidMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), m, reinterpret_cast<uintptr_t>(a)};
run(t, callVoidMethodA, arguments);
}
2014-07-11 15:47:57 +00:00
GcMethod* getStaticMethod(Thread* t, jmethodID m)
{
assertT(t, m);
2014-07-11 15:47:57 +00:00
GcMethod* method
= cast<GcMethod>(t, roots(t)->jNIMethodTable()->body()[m - 1]);
2008-04-01 17:37:59 +00:00
assertT(t, method->flags() & ACC_STATIC);
2008-04-01 17:37:59 +00:00
return method;
}
2014-07-11 15:50:18 +00:00
uint64_t callStaticObjectMethodV(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jmethodID m = arguments[0];
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uint64_t>(makeLocalReference(
t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a)));
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2007-09-07 23:20:21 +00:00
jobject JNICALL
2014-07-11 15:50:18 +00:00
CallStaticObjectMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jobject>(run(t, callStaticObjectMethodV, arguments));
}
2014-07-11 15:50:18 +00:00
jobject JNICALL CallStaticObjectMethod(Thread* t, jclass c, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jobject r = CallStaticObjectMethodV(t, c, m, a);
va_end(a);
return r;
}
2014-07-11 15:50:18 +00:00
uint64_t callStaticObjectMethodA(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uint64_t>(makeLocalReference(
t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a)));
}
jobject JNICALL
2014-07-11 15:50:18 +00:00
CallStaticObjectMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
return reinterpret_cast<jobject>(run(t, callStaticObjectMethodA, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t callStaticIntMethodV(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jmethodID m = arguments[0];
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
2014-07-11 15:47:57 +00:00
return cast<GcInt>(t,
t->m->processor->invokeList(
t, getStaticMethod(t, m), 0, true, *a))->value();
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
jboolean JNICALL
2014-07-11 15:50:18 +00:00
CallStaticBooleanMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callStaticIntMethodV, arguments) != 0;
}
2014-07-11 15:50:18 +00:00
jboolean JNICALL CallStaticBooleanMethod(Thread* t, jclass c, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jboolean r = CallStaticBooleanMethodV(t, c, m, a);
va_end(a);
return r;
}
2014-07-11 15:50:18 +00:00
uint64_t callStaticIntMethodA(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
2014-07-11 15:47:57 +00:00
return cast<GcInt>(
t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a))
->value();
}
jboolean JNICALL
2014-07-11 15:50:18 +00:00
CallStaticBooleanMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
return run(t, callStaticIntMethodA, arguments) != 0;
}
2014-07-11 15:50:18 +00:00
jbyte JNICALL CallStaticByteMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callStaticIntMethodV, arguments);
}
2014-07-11 15:50:18 +00:00
jbyte JNICALL CallStaticByteMethod(Thread* t, jclass c, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jbyte r = CallStaticByteMethodV(t, c, m, a);
va_end(a);
return r;
}
jbyte JNICALL
2014-07-11 15:50:18 +00:00
CallStaticByteMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
return run(t, callStaticIntMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
jchar JNICALL CallStaticCharMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callStaticIntMethodV, arguments);
}
2014-07-11 15:50:18 +00:00
jchar JNICALL CallStaticCharMethod(Thread* t, jclass c, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jchar r = CallStaticCharMethodV(t, c, m, a);
va_end(a);
return r;
}
jchar JNICALL
2014-07-11 15:50:18 +00:00
CallStaticCharMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
return run(t, callStaticIntMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
jshort JNICALL CallStaticShortMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callStaticIntMethodV, arguments);
}
2014-07-11 15:50:18 +00:00
jshort JNICALL CallStaticShortMethod(Thread* t, jclass c, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jshort r = CallStaticShortMethodV(t, c, m, a);
va_end(a);
return r;
}
jshort JNICALL
2014-07-11 15:50:18 +00:00
CallStaticShortMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
return run(t, callStaticIntMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
jint JNICALL CallStaticIntMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callStaticIntMethodV, arguments);
}
2014-07-11 15:50:18 +00:00
jint JNICALL CallStaticIntMethod(Thread* t, jclass c, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jint r = CallStaticIntMethodV(t, c, m, a);
va_end(a);
return r;
}
jint JNICALL
2014-07-11 15:50:18 +00:00
CallStaticIntMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
return run(t, callStaticIntMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t callStaticLongMethodV(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jmethodID m = arguments[0];
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
2014-07-11 15:47:57 +00:00
return cast<GcLong>(t,
t->m->processor->invokeList(
t, getStaticMethod(t, m), 0, true, *a))->value();
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2014-07-11 15:50:18 +00:00
jlong JNICALL CallStaticLongMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, callStaticLongMethodV, arguments);
}
2014-07-11 15:50:18 +00:00
jlong JNICALL CallStaticLongMethod(Thread* t, jclass c, jmethodID m, ...)
{
2007-09-07 23:20:21 +00:00
va_list a;
va_start(a, m);
jlong r = CallStaticLongMethodV(t, c, m, a);
va_end(a);
return r;
}
2014-07-11 15:50:18 +00:00
uint64_t callStaticLongMethodA(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
2014-07-11 15:47:57 +00:00
return cast<GcLong>(
t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a))
->value();
}
jlong JNICALL
2014-07-11 15:50:18 +00:00
CallStaticLongMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
return run(t, callStaticLongMethodA, arguments);
}
2014-07-11 15:50:18 +00:00
jfloat JNICALL CallStaticFloatMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return bitsToFloat(run(t, callStaticIntMethodV, arguments));
}
2014-07-11 15:50:18 +00:00
jfloat JNICALL CallStaticFloatMethod(Thread* t, jclass c, jmethodID m, ...)
2007-09-07 23:20:21 +00:00
{
va_list a;
va_start(a, m);
jfloat r = CallStaticFloatMethodV(t, c, m, a);
va_end(a);
return r;
}
jfloat JNICALL
2014-07-11 15:50:18 +00:00
CallStaticFloatMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
return bitsToFloat(run(t, callStaticIntMethodA, arguments));
}
2007-09-07 23:20:21 +00:00
jdouble JNICALL
2014-07-11 15:50:18 +00:00
CallStaticDoubleMethodV(Thread* t, jclass, jmethodID m, va_list a)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return bitsToDouble(run(t, callStaticLongMethodV, arguments));
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jdouble JNICALL CallStaticDoubleMethod(Thread* t, jclass c, jmethodID m, ...)
2007-09-07 23:20:21 +00:00
{
va_list a;
va_start(a, m);
jdouble r = CallStaticDoubleMethodV(t, c, m, a);
va_end(a);
return r;
}
jdouble JNICALL
2014-07-11 15:50:18 +00:00
CallStaticDoubleMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
return bitsToDouble(run(t, callStaticLongMethodA, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t callStaticVoidMethodV(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jmethodID m = arguments[0];
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a);
return 0;
}
2014-07-11 15:50:18 +00:00
void JNICALL CallStaticVoidMethodV(Thread* t, jclass, jmethodID m, va_list a)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(VA_LIST(a))};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
run(t, callStaticVoidMethodV, arguments);
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...)
2007-09-07 23:20:21 +00:00
{
va_list a;
va_start(a, m);
CallStaticVoidMethodV(t, c, m, a);
va_end(a);
}
2014-07-11 15:50:18 +00:00
uint64_t callStaticVoidMethodA(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a);
return 0;
}
void JNICALL
2014-07-11 15:50:18 +00:00
CallStaticVoidMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {m, reinterpret_cast<uintptr_t>(a)};
run(t, callStaticVoidMethodA, arguments);
}
2014-07-11 15:47:57 +00:00
jint fieldID(Thread* t, GcField* field)
{
2014-06-28 23:24:24 +00:00
int id = field->nativeID();
loadMemoryBarrier();
if (id == 0) {
PROTECT(t, field);
ACQUIRE(t, t->m->referenceLock);
2014-05-29 04:17:25 +00:00
2014-06-28 23:24:24 +00:00
if (field->nativeID() == 0) {
2014-07-11 15:47:57 +00:00
GcVector* v = vectorAppend(t, roots(t)->jNIFieldTable(), field);
2014-06-30 01:44:41 +00:00
// sequence point, for gc (don't recombine statements)
2014-06-26 02:17:27 +00:00
roots(t)->setJNIFieldTable(t, v);
storeStoreMemoryBarrier();
2014-06-30 01:44:41 +00:00
field->nativeID() = roots(t)->jNIFieldTable()->size();
}
}
2014-06-28 23:24:24 +00:00
return field->nativeID();
}
2014-07-11 15:50:18 +00:00
uint64_t getFieldID(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
jclass c = reinterpret_cast<jclass>(arguments[0]);
const char* name = reinterpret_cast<const char*>(arguments[1]);
const char* spec = reinterpret_cast<const char*>(arguments[2]);
2014-06-29 02:44:36 +00:00
return fieldID(t, resolveField(t, (*c)->vmClass(), name, spec));
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2007-09-07 23:20:21 +00:00
jfieldID JNICALL
2014-07-11 15:50:18 +00:00
GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c),
reinterpret_cast<uintptr_t>(name),
reinterpret_cast<uintptr_t>(spec)};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, getFieldID, arguments);
2007-09-07 23:20:21 +00:00
}
jfieldID JNICALL
2014-07-11 15:50:18 +00:00
GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c),
reinterpret_cast<uintptr_t>(name),
reinterpret_cast<uintptr_t>(spec)};
2007-09-07 23:20:21 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, getFieldID, arguments);
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
GcField* getField(Thread* t, jfieldID f)
{
assertT(t, f);
2014-06-30 01:44:41 +00:00
GcField* field = cast<GcField>(t, roots(t)->jNIFieldTable()->body()[f - 1]);
2014-06-29 02:44:36 +00:00
assertT(t, (field->flags() & ACC_STATIC) == 0);
return field;
}
2014-07-11 15:50:18 +00:00
uint64_t getObjectField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-07-11 15:47:57 +00:00
return reinterpret_cast<uintptr_t>(
makeLocalReference(t, fieldAtOffset<object>(*o, field->offset())));
}
2014-07-11 15:50:18 +00:00
jobject JNICALL GetObjectField(Thread* t, jobject o, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field};
return reinterpret_cast<jobject>(run(t, getObjectField, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t getBooleanField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2014-06-29 02:44:36 +00:00
return fieldAtOffset<jboolean>(*o, field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jboolean JNICALL GetBooleanField(Thread* t, jobject o, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field};
return run(t, getBooleanField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getByteField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2014-06-29 02:44:36 +00:00
return fieldAtOffset<jbyte>(*o, field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jbyte JNICALL GetByteField(Thread* t, jobject o, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field};
2007-09-07 23:20:21 +00:00
return run(t, getByteField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getCharField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-06-29 02:44:36 +00:00
return fieldAtOffset<jchar>(*o, field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jchar JNICALL GetCharField(Thread* t, jobject o, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field};
return run(t, getCharField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getShortField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2014-06-29 02:44:36 +00:00
return fieldAtOffset<jshort>(*o, field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jshort JNICALL GetShortField(Thread* t, jobject o, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field};
return run(t, getShortField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getIntField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2014-06-29 02:44:36 +00:00
return fieldAtOffset<jint>(*o, field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jint JNICALL GetIntField(Thread* t, jobject o, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field};
2007-09-07 23:20:21 +00:00
return run(t, getIntField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getLongField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-06-29 02:44:36 +00:00
return fieldAtOffset<jlong>(*o, field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jlong JNICALL GetLongField(Thread* t, jobject o, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field};
2007-09-07 23:20:21 +00:00
return run(t, getLongField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getFloatField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-06-29 02:44:36 +00:00
return floatToBits(fieldAtOffset<jfloat>(*o, field->offset()));
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jfloat JNICALL GetFloatField(Thread* t, jobject o, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field};
2007-09-07 23:20:21 +00:00
return bitsToFloat(run(t, getFloatField, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t getDoubleField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-06-29 02:44:36 +00:00
return doubleToBits(fieldAtOffset<jdouble>(*o, field->offset()));
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jdouble JNICALL GetDoubleField(Thread* t, jobject o, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field};
return bitsToDouble(run(t, getDoubleField, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t setObjectField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
jobject v = reinterpret_cast<jobject>(arguments[2]);
2014-05-29 04:17:25 +00:00
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2007-09-07 23:20:21 +00:00
2014-06-26 02:17:27 +00:00
setField(t, *o, field->offset(), (v ? *v : 0));
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetObjectField(Thread* t, jobject o, jfieldID field, jobject v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), field, reinterpret_cast<uintptr_t>(v)};
run(t, setObjectField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setBooleanField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
jboolean v = arguments[2];
2014-05-29 04:17:25 +00:00
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2007-09-07 23:20:21 +00:00
2014-06-29 02:44:36 +00:00
fieldAtOffset<jboolean>(*o, field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetBooleanField(Thread* t, jobject o, jfieldID field, jboolean v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field, v};
run(t, setBooleanField, arguments);
}
2007-09-07 23:20:21 +00:00
2014-07-11 15:50:18 +00:00
uint64_t setByteField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
jbyte v = arguments[2];
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
fieldAtOffset<jbyte>(*o, field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetByteField(Thread* t, jobject o, jfieldID field, jbyte v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), field, static_cast<uintptr_t>(v)};
2007-09-07 23:20:21 +00:00
run(t, setByteField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setCharField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
jchar v = arguments[2];
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
fieldAtOffset<jchar>(*o, field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetCharField(Thread* t, jobject o, jfieldID field, jchar v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(o), field, v};
2007-09-07 23:20:21 +00:00
run(t, setCharField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setShortField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
jshort v = arguments[2];
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
fieldAtOffset<jshort>(*o, field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetShortField(Thread* t, jobject o, jfieldID field, jshort v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), field, static_cast<uintptr_t>(v)};
2007-09-07 23:20:21 +00:00
run(t, setShortField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setIntField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
jint v = arguments[2];
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
fieldAtOffset<jint>(*o, field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetIntField(Thread* t, jobject o, jfieldID field, jint v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), field, static_cast<uintptr_t>(v)};
2007-09-07 23:20:21 +00:00
run(t, setIntField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setLongField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
2014-07-11 15:50:18 +00:00
jlong v;
memcpy(&v, arguments + 2, sizeof(jlong));
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
fieldAtOffset<jlong>(*o, field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetLongField(Thread* t, jobject o, jfieldID field, jlong v)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[2 + (sizeof(jlong) / BytesPerWord)];
arguments[0] = reinterpret_cast<uintptr_t>(o);
arguments[1] = field;
memcpy(arguments + 2, &v, sizeof(jlong));
run(t, setLongField, arguments);
}
2007-09-07 23:20:21 +00:00
2014-07-11 15:50:18 +00:00
uint64_t setFloatField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
jfloat v = bitsToFloat(arguments[2]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
fieldAtOffset<jfloat>(*o, field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetFloatField(Thread* t, jobject o, jfieldID field, jfloat v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(o), field, floatToBits(v)};
run(t, setFloatField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setDoubleField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
2014-06-29 02:44:36 +00:00
GcField* field = getField(t, arguments[1]);
2014-07-11 15:50:18 +00:00
jdouble v;
memcpy(&v, arguments + 2, sizeof(jdouble));
2007-09-07 23:20:21 +00:00
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
fieldAtOffset<jdouble>(*o, field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetDoubleField(Thread* t, jobject o, jfieldID field, jdouble v)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[2 + (sizeof(jdouble) / BytesPerWord)];
arguments[0] = reinterpret_cast<uintptr_t>(o);
arguments[1] = field;
memcpy(arguments + 2, &v, sizeof(jdouble));
2007-09-07 23:20:21 +00:00
run(t, setDoubleField, arguments);
}
2014-07-11 15:47:57 +00:00
GcField* getStaticField(Thread* t, jfieldID f)
{
assertT(t, f);
2014-06-30 01:44:41 +00:00
GcField* field = cast<GcField>(t, roots(t)->jNIFieldTable()->body()[f - 1]);
2014-06-29 02:44:36 +00:00
assertT(t, field->flags() & ACC_STATIC);
return field;
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticObjectField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-07-11 15:47:57 +00:00
return reinterpret_cast<uintptr_t>(makeLocalReference(
t, fieldAtOffset<object>(c->vmClass()->staticTable(), field->offset())));
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
jobject JNICALL GetStaticObjectField(Thread* t, jclass c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field};
2007-09-07 23:20:21 +00:00
return reinterpret_cast<jobject>(run(t, getStaticObjectField, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticBooleanField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-07-11 15:47:57 +00:00
return fieldAtOffset<jboolean>(c->vmClass()->staticTable(), field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
jboolean JNICALL GetStaticBooleanField(Thread* t, jclass c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field};
return run(t, getStaticBooleanField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticByteField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2014-07-11 15:47:57 +00:00
return fieldAtOffset<jbyte>(c->vmClass()->staticTable(), field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
jbyte JNICALL GetStaticByteField(Thread* t, jclass c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field};
return run(t, getStaticByteField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticCharField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2014-07-11 15:47:57 +00:00
return fieldAtOffset<jchar>(c->vmClass()->staticTable(), field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
jchar JNICALL GetStaticCharField(Thread* t, jclass c, jfieldID field)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field};
2007-09-07 23:20:21 +00:00
return run(t, getStaticCharField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticShortField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-07-11 15:47:57 +00:00
return fieldAtOffset<jshort>(c->vmClass()->staticTable(), field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
jshort JNICALL GetStaticShortField(Thread* t, jclass c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field};
return run(t, getStaticShortField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticIntField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2014-07-11 15:47:57 +00:00
return fieldAtOffset<jint>(c->vmClass()->staticTable(), field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
jint JNICALL GetStaticIntField(Thread* t, jclass c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field};
return run(t, getStaticIntField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticLongField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2014-07-11 15:47:57 +00:00
return fieldAtOffset<jlong>(c->vmClass()->staticTable(), field->offset());
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
jlong JNICALL GetStaticLongField(Thread* t, jclass c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field};
return run(t, getStaticLongField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticFloatField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-07-11 15:47:57 +00:00
return floatToBits(
fieldAtOffset<jfloat>(c->vmClass()->staticTable(), field->offset()));
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
jfloat JNICALL GetStaticFloatField(Thread* t, jclass c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field};
2007-09-07 23:20:21 +00:00
return bitsToFloat(run(t, getStaticFloatField, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t getStaticDoubleField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_READ(t, field);
2014-07-11 15:47:57 +00:00
return doubleToBits(
fieldAtOffset<jdouble>(c->vmClass()->staticTable(), field->offset()));
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
jdouble JNICALL GetStaticDoubleField(Thread* t, jclass c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field};
2007-09-07 23:20:21 +00:00
return bitsToDouble(run(t, getStaticDoubleField, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t setStaticObjectField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
jobject v = reinterpret_cast<jobject>(arguments[2]);
2014-05-29 04:17:25 +00:00
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-07-11 15:47:57 +00:00
setField(t, c->vmClass()->staticTable(), field->offset(), (v ? *v : 0));
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
2014-07-11 15:47:57 +00:00
SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(c), field, reinterpret_cast<uintptr_t>(v)};
run(t, setStaticObjectField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setStaticBooleanField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
jboolean v = arguments[2];
2014-05-29 04:17:25 +00:00
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2007-09-07 23:20:21 +00:00
2014-07-11 15:47:57 +00:00
fieldAtOffset<jboolean>(c->vmClass()->staticTable(), field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
2014-07-11 15:47:57 +00:00
SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field, v};
run(t, setStaticBooleanField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setStaticByteField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
jbyte v = arguments[2];
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-07-11 15:47:57 +00:00
fieldAtOffset<jbyte>(c->vmClass()->staticTable(), field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
void JNICALL SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(c), field, static_cast<uintptr_t>(v)};
run(t, setStaticByteField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setStaticCharField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
jchar v = arguments[2];
2007-09-07 23:20:21 +00:00
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-07-11 15:47:57 +00:00
fieldAtOffset<jchar>(c->vmClass()->staticTable(), field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
void JNICALL SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c), field, v};
2007-09-07 23:20:21 +00:00
run(t, setStaticCharField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setStaticShortField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
jshort v = arguments[2];
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-07-11 15:47:57 +00:00
fieldAtOffset<jshort>(c->vmClass()->staticTable(), field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
void JNICALL SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(c), field, static_cast<uintptr_t>(v)};
run(t, setStaticShortField, arguments);
}
2007-09-07 23:20:21 +00:00
2014-07-11 15:50:18 +00:00
uint64_t setStaticIntField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
jint v = arguments[2];
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-07-11 15:47:57 +00:00
fieldAtOffset<jint>(c->vmClass()->staticTable(), field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:47:57 +00:00
void JNICALL SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(c), field, static_cast<uintptr_t>(v)};
2007-09-07 23:20:21 +00:00
run(t, setStaticIntField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setStaticLongField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
2014-07-11 15:50:18 +00:00
jlong v;
memcpy(&v, arguments + 2, sizeof(jlong));
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-07-11 15:47:57 +00:00
fieldAtOffset<jlong>(c->vmClass()->staticTable(), field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
}
2014-07-11 15:47:57 +00:00
void JNICALL SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v)
{
uintptr_t arguments[2 + (sizeof(jlong) / BytesPerWord)];
arguments[0] = reinterpret_cast<uintptr_t>(c);
arguments[1] = field;
memcpy(arguments + 2, &v, sizeof(jlong));
2007-09-07 23:20:21 +00:00
run(t, setStaticLongField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setStaticFloatField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
jfloat v = bitsToFloat(arguments[2]);
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-07-11 15:47:57 +00:00
fieldAtOffset<jfloat>(c->vmClass()->staticTable(), field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
}
2014-07-11 15:47:57 +00:00
void JNICALL SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[]
= {reinterpret_cast<uintptr_t>(c), field, floatToBits(v)};
2007-09-07 23:20:21 +00:00
run(t, setStaticFloatField, arguments);
}
2014-07-11 15:50:18 +00:00
uint64_t setStaticDoubleField(Thread* t, uintptr_t* arguments)
{
2014-06-29 02:44:36 +00:00
GcJclass* c = cast<GcJclass>(t, *reinterpret_cast<jobject>(arguments[0]));
2014-06-29 02:44:36 +00:00
initClass(t, c->vmClass());
2014-06-29 02:44:36 +00:00
GcField* field = getStaticField(t, arguments[1]);
2014-07-11 15:50:18 +00:00
jdouble v;
memcpy(&v, arguments + 2, sizeof(jdouble));
PROTECT(t, field);
2014-06-29 02:44:36 +00:00
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2014-07-11 15:47:57 +00:00
fieldAtOffset<jdouble>(c->vmClass()->staticTable(), field->offset()) = v;
2014-05-29 04:17:25 +00:00
return 1;
}
void JNICALL
2014-07-11 15:47:57 +00:00
SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v)
{
uintptr_t arguments[2 + (sizeof(jdouble) / BytesPerWord)];
arguments[0] = reinterpret_cast<uintptr_t>(c);
arguments[1] = field;
memcpy(arguments + 2, &v, sizeof(jdouble));
2007-09-07 23:20:21 +00:00
run(t, setStaticDoubleField, arguments);
}
2014-07-11 15:50:18 +00:00
jobject JNICALL newGlobalRef(Thread* t, jobject o, bool weak)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
ACQUIRE(t, t->m->referenceLock);
2014-05-29 04:17:25 +00:00
if (o) {
for (Reference* r = t->m->jniReferences; r; r = r->next) {
if (r->target == *o and r->weak == weak) {
acquire(t, r);
return &(r->target);
}
}
2008-04-13 18:15:04 +00:00
Reference* r = new (t->m->heap->allocate(sizeof(Reference)))
2014-07-11 15:50:18 +00:00
Reference(*o, &(t->m->jniReferences), weak);
2007-09-07 23:20:21 +00:00
acquire(t, r);
return &(r->target);
} else {
return 0;
}
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jobject JNICALL NewGlobalRef(Thread* t, jobject o)
{
return newGlobalRef(t, o, false);
}
2014-07-11 15:50:18 +00:00
void JNICALL DeleteGlobalRef(Thread* t, jobject r)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
ACQUIRE(t, t->m->referenceLock);
2014-05-29 04:17:25 +00:00
if (r) {
release(t, reinterpret_cast<Reference*>(r));
2007-09-07 23:20:21 +00:00
}
}
2014-07-11 15:50:18 +00:00
jobject JNICALL NewWeakGlobalRef(Thread* t, jobject o)
{
return newGlobalRef(t, o, true);
}
2014-07-11 15:50:18 +00:00
void JNICALL DeleteWeakGlobalRef(Thread* t, jobject r)
{
DeleteGlobalRef(t, r);
}
2014-07-11 15:50:18 +00:00
jint JNICALL EnsureLocalCapacity(Thread*, jint)
{
return 0;
}
2014-07-11 15:50:18 +00:00
jthrowable JNICALL ExceptionOccurred(Thread* t)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
return reinterpret_cast<jthrowable>(makeLocalReference(t, t->exception));
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL ExceptionDescribe(Thread* t)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
return printTrace(t, t->exception);
}
2014-07-11 15:50:18 +00:00
void JNICALL ExceptionClear(Thread* t)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
t->exception = 0;
}
2014-07-11 15:50:18 +00:00
uint64_t newObjectArray(Thread* t, uintptr_t* arguments)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jsize length = arguments[0];
jclass class_ = reinterpret_cast<jclass>(arguments[1]);
jobject init = reinterpret_cast<jobject>(arguments[2]);
2014-06-29 02:44:36 +00:00
object a = makeObjectArray(t, (*class_)->vmClass(), length);
object value = (init ? *init : 0);
for (jsize i = 0; i < length; ++i) {
2014-06-26 02:17:27 +00:00
reinterpret_cast<GcArray*>(a)->setBodyElement(t, i, value);
}
return reinterpret_cast<uint64_t>(makeLocalReference(t, a));
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
jobjectArray JNICALL
2014-07-11 15:50:18 +00:00
NewObjectArray(Thread* t, jsize length, jclass class_, jobject init)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {static_cast<uintptr_t>(length),
reinterpret_cast<uintptr_t>(class_),
reinterpret_cast<uintptr_t>(init)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jobjectArray>(run(t, newObjectArray, arguments));
}
jobject JNICALL
2014-07-11 15:50:18 +00:00
GetObjectArrayElement(Thread* t, jobjectArray array, jsize index)
{
ENTER(t, Thread::ActiveState);
2014-07-11 15:47:57 +00:00
return makeLocalReference(
t, objectArrayBody(t, reinterpret_cast<object>(*array), index));
}
2014-07-11 15:50:18 +00:00
void JNICALL SetObjectArrayElement(Thread* t,
jobjectArray array,
jsize index,
jobject value)
{
ENTER(t, Thread::ActiveState);
2014-07-11 15:47:57 +00:00
setField(t,
reinterpret_cast<object>(*array),
ArrayBody + (index * BytesPerWord),
(value ? *value : 0));
}
2014-07-11 15:50:18 +00:00
uint64_t newArray(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
object (*constructor)(Thread*, unsigned)
2014-07-11 15:50:18 +00:00
= reinterpret_cast<object (*)(Thread*, unsigned)>(arguments[0]);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jsize length = arguments[1];
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uint64_t>(
makeLocalReference(t, constructor(t, length)));
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2014-07-11 15:50:18 +00:00
jbooleanArray JNICALL NewBooleanArray(Thread* t, jsize length)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
uintptr_t arguments[]
2014-07-11 15:50:18 +00:00
= {reinterpret_cast<uintptr_t>(voidPointer(makeBooleanArray)),
static_cast<uintptr_t>(length)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jbooleanArray>(run(t, newArray, arguments));
}
2014-07-11 15:50:18 +00:00
object makeByteArray0(Thread* t, unsigned length)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
return makeByteArray(t, length);
}
2014-07-11 15:50:18 +00:00
jbyteArray JNICALL NewByteArray(Thread* t, jsize length)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
uintptr_t arguments[]
2014-07-11 15:50:18 +00:00
= {reinterpret_cast<uintptr_t>(voidPointer(makeByteArray0)),
static_cast<uintptr_t>(length)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jbyteArray>(run(t, newArray, arguments));
}
2014-07-11 15:50:18 +00:00
jcharArray JNICALL NewCharArray(Thread* t, jsize length)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
uintptr_t arguments[]
2014-07-11 15:50:18 +00:00
= {reinterpret_cast<uintptr_t>(voidPointer(makeCharArray)),
static_cast<uintptr_t>(length)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jcharArray>(run(t, newArray, arguments));
}
2014-07-11 15:50:18 +00:00
jshortArray JNICALL NewShortArray(Thread* t, jsize length)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
uintptr_t arguments[]
2014-07-11 15:50:18 +00:00
= {reinterpret_cast<uintptr_t>(voidPointer(makeShortArray)),
static_cast<uintptr_t>(length)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jshortArray>(run(t, newArray, arguments));
}
2014-07-11 15:50:18 +00:00
jintArray JNICALL NewIntArray(Thread* t, jsize length)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
uintptr_t arguments[]
2014-07-11 15:50:18 +00:00
= {reinterpret_cast<uintptr_t>(voidPointer(makeIntArray)),
static_cast<uintptr_t>(length)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jintArray>(run(t, newArray, arguments));
}
2014-07-11 15:50:18 +00:00
jlongArray JNICALL NewLongArray(Thread* t, jsize length)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
uintptr_t arguments[]
2014-07-11 15:50:18 +00:00
= {reinterpret_cast<uintptr_t>(voidPointer(makeLongArray)),
static_cast<uintptr_t>(length)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jlongArray>(run(t, newArray, arguments));
}
2014-07-11 15:50:18 +00:00
jfloatArray JNICALL NewFloatArray(Thread* t, jsize length)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
uintptr_t arguments[]
2014-07-11 15:50:18 +00:00
= {reinterpret_cast<uintptr_t>(voidPointer(makeFloatArray)),
static_cast<uintptr_t>(length)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jfloatArray>(run(t, newArray, arguments));
}
2014-07-11 15:50:18 +00:00
jdoubleArray JNICALL NewDoubleArray(Thread* t, jsize length)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
uintptr_t arguments[]
2014-07-11 15:50:18 +00:00
= {reinterpret_cast<uintptr_t>(voidPointer(makeDoubleArray)),
static_cast<uintptr_t>(length)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return reinterpret_cast<jdoubleArray>(run(t, newArray, arguments));
}
2007-09-07 23:20:21 +00:00
jboolean* JNICALL
2014-07-11 15:50:18 +00:00
GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jboolean);
2008-04-13 18:15:04 +00:00
jboolean* p = static_cast<jboolean*>(t->m->heap->allocate(size));
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy(p, (*array)->body().begin(), size);
2007-09-07 23:20:21 +00:00
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jbyte* JNICALL
2014-07-11 15:50:18 +00:00
GetByteArrayElements(Thread* t, jbyteArray array, jboolean* isCopy)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jbyte);
2008-04-13 18:15:04 +00:00
jbyte* p = static_cast<jbyte*>(t->m->heap->allocate(size));
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy(p, (*array)->body().begin(), size);
2007-09-07 23:20:21 +00:00
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jchar* JNICALL
2014-07-11 15:50:18 +00:00
GetCharArrayElements(Thread* t, jcharArray array, jboolean* isCopy)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jchar);
2008-04-13 18:15:04 +00:00
jchar* p = static_cast<jchar*>(t->m->heap->allocate(size));
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy(p, (*array)->body().begin(), size);
2007-09-07 23:20:21 +00:00
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jshort* JNICALL
2014-07-11 15:50:18 +00:00
GetShortArrayElements(Thread* t, jshortArray array, jboolean* isCopy)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jshort);
2008-04-13 18:15:04 +00:00
jshort* p = static_cast<jshort*>(t->m->heap->allocate(size));
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy(p, (*array)->body().begin(), size);
2007-09-07 23:20:21 +00:00
}
if (isCopy) {
*isCopy = true;
}
return p;
}
2014-07-11 15:50:18 +00:00
jint* JNICALL GetIntArrayElements(Thread* t, jintArray array, jboolean* isCopy)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jint);
2008-04-13 18:15:04 +00:00
jint* p = static_cast<jint*>(t->m->heap->allocate(size));
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy(p, (*array)->body().begin(), size);
2007-09-07 23:20:21 +00:00
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jlong* JNICALL
2014-07-11 15:50:18 +00:00
GetLongArrayElements(Thread* t, jlongArray array, jboolean* isCopy)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jlong);
2008-04-13 18:15:04 +00:00
jlong* p = static_cast<jlong*>(t->m->heap->allocate(size));
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy(p, (*array)->body().begin(), size);
2007-09-07 23:20:21 +00:00
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jfloat* JNICALL
2014-07-11 15:50:18 +00:00
GetFloatArrayElements(Thread* t, jfloatArray array, jboolean* isCopy)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jfloat);
2008-04-13 18:15:04 +00:00
jfloat* p = static_cast<jfloat*>(t->m->heap->allocate(size));
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy(p, (*array)->body().begin(), size);
2007-09-07 23:20:21 +00:00
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jdouble* JNICALL
2014-07-11 15:50:18 +00:00
GetDoubleArrayElements(Thread* t, jdoubleArray array, jboolean* isCopy)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jdouble);
2008-04-13 18:15:04 +00:00
jdouble* p = static_cast<jdouble*>(t->m->heap->allocate(size));
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy(p, (*array)->body().begin(), size);
2007-09-07 23:20:21 +00:00
}
if (isCopy) {
*isCopy = true;
}
return p;
}
2014-07-11 15:50:18 +00:00
void JNICALL ReleaseBooleanArrayElements(Thread* t,
jbooleanArray array,
jboolean* p,
jint mode)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jboolean);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy((*array)->body().begin(), p, size);
2007-09-07 23:20:21 +00:00
}
}
if (mode == 0 or mode == AVIAN_JNI_ABORT) {
2008-04-13 18:15:04 +00:00
t->m->heap->free(p, size);
2007-09-07 23:20:21 +00:00
}
}
void JNICALL
2014-07-11 15:50:18 +00:00
ReleaseByteArrayElements(Thread* t, jbyteArray array, jbyte* p, jint mode)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jbyte);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy((*array)->body().begin(), p, size);
2007-09-07 23:20:21 +00:00
}
}
if (mode == 0 or mode == AVIAN_JNI_ABORT) {
2008-04-13 18:15:04 +00:00
t->m->heap->free(p, size);
2007-09-07 23:20:21 +00:00
}
}
void JNICALL
2014-07-11 15:50:18 +00:00
ReleaseCharArrayElements(Thread* t, jcharArray array, jchar* p, jint mode)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jchar);
2014-05-29 04:17:25 +00:00
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy((*array)->body().begin(), p, size);
2007-09-07 23:20:21 +00:00
}
}
if (mode == 0 or mode == AVIAN_JNI_ABORT) {
2008-04-13 18:15:04 +00:00
t->m->heap->free(p, size);
2007-09-07 23:20:21 +00:00
}
}
2014-07-11 15:50:18 +00:00
void JNICALL ReleaseShortArrayElements(Thread* t,
jshortArray array,
jshort* p,
jint mode)
2007-09-07 23:20:21 +00:00
{
2014-05-29 04:17:25 +00:00
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jshort);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy((*array)->body().begin(), p, size);
2007-09-07 23:20:21 +00:00
}
}
if (mode == 0 or mode == AVIAN_JNI_ABORT) {
2008-04-13 18:15:04 +00:00
t->m->heap->free(p, size);
2007-09-07 23:20:21 +00:00
}
}
void JNICALL
2014-07-11 15:50:18 +00:00
ReleaseIntArrayElements(Thread* t, jintArray array, jint* p, jint mode)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jint);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy((*array)->body().begin(), p, size);
2007-09-07 23:20:21 +00:00
}
}
if (mode == 0 or mode == AVIAN_JNI_ABORT) {
2008-04-13 18:15:04 +00:00
t->m->heap->free(p, size);
2007-09-07 23:20:21 +00:00
}
}
void JNICALL
2014-07-11 15:50:18 +00:00
ReleaseLongArrayElements(Thread* t, jlongArray array, jlong* p, jint mode)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jlong);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy((*array)->body().begin(), p, size);
2007-09-07 23:20:21 +00:00
}
}
if (mode == 0 or mode == AVIAN_JNI_ABORT) {
2008-04-13 18:15:04 +00:00
t->m->heap->free(p, size);
2007-09-07 23:20:21 +00:00
}
}
2014-07-11 15:50:18 +00:00
void JNICALL ReleaseFloatArrayElements(Thread* t,
jfloatArray array,
jfloat* p,
jint mode)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jfloat);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy((*array)->body().begin(), p, size);
2007-09-07 23:20:21 +00:00
}
}
if (mode == 0 or mode == AVIAN_JNI_ABORT) {
2008-04-13 18:15:04 +00:00
t->m->heap->free(p, size);
2007-09-07 23:20:21 +00:00
}
}
2014-07-11 15:50:18 +00:00
void JNICALL ReleaseDoubleArrayElements(Thread* t,
jdoubleArray array,
jdouble* p,
jint mode)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
2014-06-29 02:44:36 +00:00
unsigned size = (*array)->length() * sizeof(jdouble);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
2014-06-29 02:44:36 +00:00
memcpy((*array)->body().begin(), p, size);
2007-09-07 23:20:21 +00:00
}
}
if (mode == 0 or mode == AVIAN_JNI_ABORT) {
2008-04-13 18:15:04 +00:00
t->m->heap->free(p, size);
2007-09-07 23:20:21 +00:00
}
}
2014-07-11 15:50:18 +00:00
void JNICALL GetBooleanArrayRegion(Thread* t,
jbooleanArray array,
jint offset,
jint length,
jboolean* dst)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-07-11 15:47:57 +00:00
memcpy(dst, &(*array)->body()[offset], length * sizeof(jboolean));
}
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL GetByteArrayRegion(Thread* t,
jbyteArray array,
jint offset,
jint length,
jbyte* dst)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(dst, &(*array)->body()[offset], length * sizeof(jbyte));
}
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL GetCharArrayRegion(Thread* t,
jcharArray array,
jint offset,
jint length,
jchar* dst)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(dst, &(*array)->body()[offset], length * sizeof(jchar));
}
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL GetShortArrayRegion(Thread* t,
jshortArray array,
jint offset,
jint length,
jshort* dst)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(dst, &(*array)->body()[offset], length * sizeof(jshort));
}
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL GetIntArrayRegion(Thread* t,
jintArray array,
jint offset,
jint length,
jint* dst)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(dst, &(*array)->body()[offset], length * sizeof(jint));
}
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL GetLongArrayRegion(Thread* t,
jlongArray array,
jint offset,
jint length,
jlong* dst)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(dst, &(*array)->body()[offset], length * sizeof(jlong));
}
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL GetFloatArrayRegion(Thread* t,
jfloatArray array,
jint offset,
jint length,
jfloat* dst)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(dst, &(*array)->body()[offset], length * sizeof(jfloat));
}
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL GetDoubleArrayRegion(Thread* t,
jdoubleArray array,
jint offset,
jint length,
jdouble* dst)
2007-09-07 23:20:21 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(dst, &(*array)->body()[offset], length * sizeof(jdouble));
}
2007-09-17 22:15:42 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetBooleanArrayRegion(Thread* t,
jbooleanArray array,
jint offset,
jint length,
const jboolean* src)
2007-09-17 22:15:42 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-07-11 15:47:57 +00:00
memcpy(&(*array)->body()[offset], src, length * sizeof(jboolean));
}
2007-09-17 22:15:42 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetByteArrayRegion(Thread* t,
jbyteArray array,
jint offset,
jint length,
const jbyte* src)
2007-09-17 22:15:42 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(&(*array)->body()[offset], src, length * sizeof(jbyte));
}
2007-09-17 22:15:42 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetCharArrayRegion(Thread* t,
jcharArray array,
jint offset,
jint length,
const jchar* src)
2007-09-17 22:15:42 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(&(*array)->body()[offset], src, length * sizeof(jchar));
}
2007-09-17 22:15:42 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetShortArrayRegion(Thread* t,
jshortArray array,
jint offset,
jint length,
const jshort* src)
2007-09-17 22:15:42 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(&(*array)->body()[offset], src, length * sizeof(jshort));
}
2007-09-17 22:15:42 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetIntArrayRegion(Thread* t,
jintArray array,
jint offset,
jint length,
const jint* src)
2007-09-17 22:15:42 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(&(*array)->body()[offset], src, length * sizeof(jint));
}
2007-09-17 22:15:42 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetLongArrayRegion(Thread* t,
jlongArray array,
jint offset,
jint length,
const jlong* src)
2007-09-17 22:15:42 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(&(*array)->body()[offset], src, length * sizeof(jlong));
}
2007-09-17 22:15:42 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetFloatArrayRegion(Thread* t,
jfloatArray array,
jint offset,
jint length,
const jfloat* src)
2007-09-17 22:15:42 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(&(*array)->body()[offset], src, length * sizeof(jfloat));
}
2007-09-17 22:15:42 +00:00
}
2014-07-11 15:50:18 +00:00
void JNICALL SetDoubleArrayRegion(Thread* t,
jdoubleArray array,
jint offset,
jint length,
const jdouble* src)
2007-09-17 22:15:42 +00:00
{
ENTER(t, Thread::ActiveState);
if (length) {
2014-06-29 02:44:36 +00:00
memcpy(&(*array)->body()[offset], src, length * sizeof(jdouble));
}
2007-09-07 23:20:21 +00:00
}
void* JNICALL
2014-07-11 15:50:18 +00:00
GetPrimitiveArrayCritical(Thread* t, jarray array, jboolean* isCopy)
2007-09-07 23:20:21 +00:00
{
if (t->criticalLevel == 0) {
2007-09-07 23:20:21 +00:00
enter(t, Thread::ActiveState);
}
2014-07-11 15:50:18 +00:00
++t->criticalLevel;
2014-05-29 04:17:25 +00:00
2007-09-07 23:20:21 +00:00
if (isCopy) {
*isCopy = true;
}
expect(t, *array);
2007-09-07 23:20:21 +00:00
return reinterpret_cast<uintptr_t*>(*array) + 2;
}
2014-07-11 15:50:18 +00:00
void JNICALL ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint)
2007-09-07 23:20:21 +00:00
{
2014-07-11 15:50:18 +00:00
if ((--t->criticalLevel) == 0) {
2007-09-07 23:20:21 +00:00
enter(t, Thread::IdleState);
}
}
2014-07-11 15:50:18 +00:00
uint64_t fromReflectedMethod(Thread* t, uintptr_t* arguments)
{
jobject m = reinterpret_cast<jobject>(arguments[0]);
2014-06-28 23:24:24 +00:00
return methodID(t, t->m->classpath->getVMMethod(t, *m));
}
2014-07-11 15:50:18 +00:00
jmethodID JNICALL FromReflectedMethod(Thread* t, jobject method)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(method)};
2012-12-19 23:48:20 +00:00
return static_cast<jmethodID>(run(t, fromReflectedMethod, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t toReflectedMethod(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[1];
jboolean isStatic = arguments[2];
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uintptr_t>(makeLocalReference(
t,
t->m->classpath->makeJMethod(
t, isStatic ? getStaticMethod(t, m) : getMethod(t, m))));
}
jobject JNICALL
2014-07-11 15:50:18 +00:00
ToReflectedMethod(Thread* t, jclass c, jmethodID method, jboolean isStatic)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c),
static_cast<uintptr_t>(method),
static_cast<uintptr_t>(isStatic)};
return reinterpret_cast<jobject>(run(t, toReflectedMethod, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t fromReflectedField(Thread* t, uintptr_t* arguments)
{
jobject f = reinterpret_cast<jobject>(arguments[0]);
2014-06-27 00:17:46 +00:00
return fieldID(t, t->m->classpath->getVMField(t, cast<GcJfield>(t, *f)));
}
2014-07-11 15:50:18 +00:00
jfieldID JNICALL FromReflectedField(Thread* t, jobject field)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(field)};
2012-12-19 23:48:20 +00:00
return static_cast<jfieldID>(run(t, fromReflectedField, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t toReflectedField(Thread* t, uintptr_t* arguments)
{
jfieldID f = arguments[1];
jboolean isStatic = arguments[2];
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uintptr_t>(makeLocalReference(
t,
t->m->classpath->makeJField(
t, isStatic ? getStaticField(t, f) : getField(t, f))));
}
jobject JNICALL
2014-07-11 15:50:18 +00:00
ToReflectedField(Thread* t, jclass c, jfieldID field, jboolean isStatic)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c),
static_cast<uintptr_t>(field),
static_cast<uintptr_t>(isStatic)};
return reinterpret_cast<jobject>(run(t, toReflectedField, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t registerNatives(Thread* t, uintptr_t* arguments)
{
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jclass c = reinterpret_cast<jclass>(arguments[0]);
const JNINativeMethod* methods
2014-07-11 15:50:18 +00:00
= reinterpret_cast<const JNINativeMethod*>(arguments[1]);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jint methodCount = arguments[2];
for (int i = 0; i < methodCount; ++i) {
if (methods[i].function) {
// Android's class library sometimes prepends a mysterious "!"
// to the method signature, which we happily ignore:
const char* sig = methods[i].signature;
2014-07-11 15:50:18 +00:00
if (*sig == '!')
++sig;
2014-07-11 15:47:57 +00:00
GcMethod* method
= findMethodOrNull(t, (*c)->vmClass(), methods[i].name, sig);
2014-05-29 04:17:25 +00:00
if (method == 0 or (method->flags() & ACC_NATIVE) == 0) {
// The JNI spec says we must throw a NoSuchMethodError in this
// case, but that would prevent using a code shrinker like
// ProGuard effectively. Instead, we just ignore it.
if (false) {
fprintf(stderr,
"not found: %s.%s%s\n",
(*c)->vmClass()->name()->body().begin(),
methods[i].name,
sig);
abort(t);
}
} else {
registerNative(t, method, methods[i].function);
}
}
}
2014-05-29 04:17:25 +00:00
return 1;
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
}
2014-07-11 15:50:18 +00:00
jint JNICALL RegisterNatives(Thread* t,
jclass c,
const JNINativeMethod* methods,
jint methodCount)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(c),
reinterpret_cast<uintptr_t>(methods),
static_cast<uintptr_t>(methodCount)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, registerNatives, arguments) ? 0 : -1;
}
2014-07-11 15:50:18 +00:00
jint JNICALL UnregisterNatives(Thread* t, jclass c)
{
ENTER(t, Thread::ActiveState);
2014-06-29 02:44:36 +00:00
unregisterNatives(t, (*c)->vmClass());
return 0;
}
2014-07-11 15:50:18 +00:00
uint64_t monitorOp(Thread* t, uintptr_t* arguments)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
void (*op)(Thread*, object)
2014-07-11 15:50:18 +00:00
= reinterpret_cast<void (*)(Thread*, object)>(arguments[0]);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
jobject o = reinterpret_cast<jobject>(arguments[1]);
2014-05-29 04:17:25 +00:00
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
op(t, *o);
return 1;
}
2014-07-11 15:50:18 +00:00
void acquire0(Thread* t, object o)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
return acquire(t, o);
}
2014-07-11 15:50:18 +00:00
jint JNICALL MonitorEnter(Thread* t, jobject o)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(voidPointer(acquire0)),
reinterpret_cast<uintptr_t>(o)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, monitorOp, arguments) ? 0 : -1;
}
2014-07-11 15:50:18 +00:00
void release0(Thread* t, object o)
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
{
return release(t, o);
}
2014-07-11 15:50:18 +00:00
jint JNICALL MonitorExit(Thread* t, jobject o)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(voidPointer(release0)),
reinterpret_cast<uintptr_t>(o)};
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
return run(t, monitorOp, arguments) ? 0 : -1;
}
2014-07-11 15:50:18 +00:00
jint JNICALL GetJavaVM(Thread* t, Machine** m)
2007-09-07 23:20:21 +00:00
{
*m = t->m;
return 0;
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
jboolean JNICALL IsSameObject(Thread* t, jobject a, jobject b)
2007-09-07 23:20:21 +00:00
{
2008-04-01 22:40:53 +00:00
if (a and b) {
ENTER(t, Thread::ActiveState);
2007-09-07 23:20:21 +00:00
2008-04-01 22:40:53 +00:00
return *a == *b;
} else {
return a == b;
}
2007-09-07 23:20:21 +00:00
}
2014-07-11 15:50:18 +00:00
uint64_t pushLocalFrame(Thread* t, uintptr_t* arguments)
{
if (t->m->processor->pushLocalFrame(t, arguments[0])) {
return 1;
} else {
2014-06-30 01:44:41 +00:00
throw_(t, roots(t)->outOfMemoryError());
}
}
2014-07-11 15:50:18 +00:00
jint JNICALL PushLocalFrame(Thread* t, jint capacity)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {static_cast<uintptr_t>(capacity)};
return run(t, pushLocalFrame, arguments) ? 0 : -1;
}
2014-07-11 15:50:18 +00:00
uint64_t popLocalFrame(Thread* t, uintptr_t* arguments)
{
2012-12-21 08:56:21 +00:00
uint64_t r;
jobject presult = reinterpret_cast<jobject>(arguments[0]);
2014-07-11 15:50:18 +00:00
if (presult != NULL) {
2012-12-21 08:56:21 +00:00
object result = *presult;
PROTECT(t, result);
2012-12-21 08:56:21 +00:00
t->m->processor->popLocalFrame(t);
r = reinterpret_cast<uint64_t>(makeLocalReference(t, result));
} else {
t->m->processor->popLocalFrame(t);
r = 0;
}
return r;
}
2014-07-11 15:50:18 +00:00
jobject JNICALL PopLocalFrame(Thread* t, jobject result)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(result)};
return reinterpret_cast<jobject>(run(t, popLocalFrame, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t newDirectByteBuffer(Thread* t, uintptr_t* arguments)
2013-02-21 22:37:17 +00:00
{
2014-07-11 15:50:18 +00:00
jlong capacity;
memcpy(&capacity, arguments + 1, sizeof(jlong));
2013-02-21 22:37:17 +00:00
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uintptr_t>(makeLocalReference(
t,
t->m->classpath->makeDirectByteBuffer(
t, reinterpret_cast<void*>(arguments[0]), capacity)));
2013-02-21 22:37:17 +00:00
}
2014-07-11 15:50:18 +00:00
jobject JNICALL NewDirectByteBuffer(Thread* t, void* p, jlong capacity)
{
2013-02-21 22:37:17 +00:00
uintptr_t arguments[1 + (sizeof(jlong) / BytesPerWord)];
arguments[0] = reinterpret_cast<uintptr_t>(p);
memcpy(arguments + 1, &capacity, sizeof(jlong));
return reinterpret_cast<jobject>(run(t, newDirectByteBuffer, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t getDirectBufferAddress(Thread* t, uintptr_t* arguments)
2013-02-21 22:37:17 +00:00
{
2014-07-11 15:50:18 +00:00
return reinterpret_cast<uintptr_t>(t->m->classpath->getDirectBufferAddress(
t, *reinterpret_cast<jobject>(arguments[0])));
}
2014-07-11 15:50:18 +00:00
void* JNICALL GetDirectBufferAddress(Thread* t, jobject b)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(b)};
2013-02-21 22:37:17 +00:00
return reinterpret_cast<void*>(run(t, getDirectBufferAddress, arguments));
}
2014-07-11 15:50:18 +00:00
uint64_t getDirectBufferCapacity(Thread* t, uintptr_t* arguments)
2013-02-21 22:37:17 +00:00
{
2014-07-11 15:50:18 +00:00
return t->m->classpath->getDirectBufferCapacity(
t, *reinterpret_cast<jobject>(arguments[0]));
}
2014-07-11 15:50:18 +00:00
jlong JNICALL GetDirectBufferCapacity(Thread* t, jobject b)
{
2014-07-11 15:50:18 +00:00
uintptr_t arguments[] = {reinterpret_cast<uintptr_t>(b)};
2013-02-21 22:37:17 +00:00
return run(t, getDirectBufferCapacity, arguments);
}
struct JavaVMOption {
char* optionString;
void* extraInfo;
};
struct JavaVMInitArgs {
jint version;
jint nOptions;
JavaVMOption* options;
jboolean ignoreUnrecognized;
};
2014-07-11 15:50:18 +00:00
int parseSize(const char* s)
{
unsigned length = strlen(s);
RUNTIME_ARRAY(char, buffer, length + 1);
2014-07-18 13:09:53 +00:00
if (length == 0)
return 0;
2014-07-18 13:09:53 +00:00
char suffix = s[length - 1];
if (suffix== 'k' or suffix == 'K') {
memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1);
RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0;
return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024;
2014-07-18 13:09:53 +00:00
}
if (suffix == 'm' or suffix == 'M') {
memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1);
RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0;
return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024 * 1024;
}
2014-07-18 13:09:53 +00:00
if (suffix == 'g' or suffix == 'G') {
memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1);
RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0;
return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024 * 1024 * 1024;
}
return atoi(s);
}
2014-07-11 15:50:18 +00:00
void append(char** p, const char* value, unsigned length, char tail)
{
if (length) {
memcpy(*p, value, length);
*p += length;
*((*p)++) = tail;
}
}
2014-07-11 15:50:18 +00:00
uint64_t boot(Thread* t, uintptr_t*)
{
2014-06-30 01:44:41 +00:00
GcThrowable* throwable = makeThrowable(t, GcNullPointerException::Type);
// sequence point, for gc (don't recombine statements)
2014-06-26 02:17:27 +00:00
roots(t)->setNullPointerException(t, throwable);
2014-05-29 04:17:25 +00:00
2014-06-30 01:44:41 +00:00
throwable = makeThrowable(t, GcArithmeticException::Type);
// sequence point, for gc (don't recombine statements)
2014-06-26 02:17:27 +00:00
roots(t)->setArithmeticException(t, throwable);
2014-06-30 01:44:41 +00:00
throwable = makeThrowable(t, GcArrayIndexOutOfBoundsException::Type);
// sequence point, for gc (don't recombine statements)
2014-06-26 02:17:27 +00:00
roots(t)->setArrayIndexOutOfBoundsException(t, throwable);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
2014-06-30 01:44:41 +00:00
throwable = makeThrowable(t, GcOutOfMemoryError::Type);
// sequence point, for gc (don't recombine statements)
2014-06-26 02:17:27 +00:00
roots(t)->setOutOfMemoryError(t, throwable);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
2014-06-30 01:44:41 +00:00
throwable = makeThrowable(t, GcThrowable::Type);
// sequence point, for gc (don't recombine statements)
2014-06-26 02:17:27 +00:00
roots(t)->setShutdownInProgress(t, throwable);
2013-02-22 21:41:24 +00:00
t->m->classpath->preBoot(t);
2013-02-22 18:06:49 +00:00
t->javaThread = t->m->classpath->makeThread(t, 0);
2014-06-28 23:24:24 +00:00
t->javaThread->peer() = reinterpret_cast<jlong>(t);
2013-02-22 18:06:49 +00:00
2014-06-30 01:44:41 +00:00
GcThread* jthread = t->m->classpath->makeThread(t, t);
// sequence point, for gc (don't recombine statements)
2014-06-26 02:17:27 +00:00
roots(t)->setFinalizerThread(t, jthread);
rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling.
2010-12-27 22:55:23 +00:00
2014-06-30 01:44:41 +00:00
roots(t)->finalizerThread()->daemon() = true;
2013-02-22 21:41:24 +00:00
t->m->classpath->boot(t);
const char* port = findProperty(t, "avian.trace.port");
if (port) {
2014-06-29 02:44:36 +00:00
GcString* host = makeString(t, "0.0.0.0");
PROTECT(t, host);
2014-07-11 15:47:57 +00:00
GcMethod* method = resolveMethod(t,
roots(t)->bootLoader(),
"avian/Traces",
"startTraceListener",
"(Ljava/lang/String;I)V");
t->m->processor->invoke(t, method, 0, host, atoi(port));
}
enter(t, Thread::IdleState);
return 1;
}
2014-07-11 15:50:18 +00:00
} // namespace local
2010-04-15 17:11:10 +00:00
2014-07-11 15:50:18 +00:00
} // namespace
namespace vm {
2014-07-11 15:50:18 +00:00
void populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
{
memset(vmTable, 0, sizeof(JavaVMVTable));
2010-04-15 17:11:10 +00:00
vmTable->DestroyJavaVM = local::DestroyJavaVM;
vmTable->AttachCurrentThread = local::AttachCurrentThread;
vmTable->AttachCurrentThreadAsDaemon = local::AttachCurrentThreadAsDaemon;
vmTable->DetachCurrentThread = local::DetachCurrentThread;
vmTable->GetEnv = local::GetEnv;
memset(envTable, 0, sizeof(JNIEnvVTable));
2010-04-15 17:11:10 +00:00
envTable->GetVersion = local::GetVersion;
envTable->GetStringLength = local::GetStringLength;
envTable->GetStringChars = local::GetStringChars;
envTable->ReleaseStringChars = local::ReleaseStringChars;
envTable->GetStringRegion = local::GetStringRegion;
envTable->GetStringCritical = local::GetStringCritical;
envTable->ReleaseStringCritical = local::ReleaseStringCritical;
2010-04-15 17:11:10 +00:00
envTable->GetStringUTFLength = local::GetStringUTFLength;
envTable->GetStringUTFChars = local::GetStringUTFChars;
envTable->ReleaseStringUTFChars = local::ReleaseStringUTFChars;
envTable->GetStringUTFRegion = local::GetStringUTFRegion;
2010-04-15 17:11:10 +00:00
envTable->GetArrayLength = local::GetArrayLength;
envTable->NewString = local::NewString;
envTable->NewStringUTF = local::NewStringUTF;
envTable->DefineClass = local::DefineClass;
2010-04-15 17:11:10 +00:00
envTable->FindClass = local::FindClass;
envTable->ThrowNew = local::ThrowNew;
envTable->Throw = local::Throw;
2010-04-15 17:11:10 +00:00
envTable->ExceptionCheck = local::ExceptionCheck;
envTable->NewDirectByteBuffer = local::NewDirectByteBuffer;
envTable->GetDirectBufferAddress = local::GetDirectBufferAddress;
envTable->GetDirectBufferCapacity = local::GetDirectBufferCapacity;
2012-12-20 16:05:30 +00:00
envTable->NewLocalRef = local::NewLocalRef;
2010-04-15 17:11:10 +00:00
envTable->DeleteLocalRef = local::DeleteLocalRef;
envTable->GetObjectClass = local::GetObjectClass;
envTable->GetSuperclass = local::GetSuperclass;
2010-04-15 17:11:10 +00:00
envTable->IsInstanceOf = local::IsInstanceOf;
envTable->IsAssignableFrom = local::IsAssignableFrom;
2010-04-15 17:11:10 +00:00
envTable->GetFieldID = local::GetFieldID;
envTable->GetMethodID = local::GetMethodID;
envTable->GetStaticMethodID = local::GetStaticMethodID;
envTable->NewObjectV = local::NewObjectV;
envTable->NewObjectA = local::NewObjectA;
envTable->NewObject = local::NewObject;
2010-04-15 17:11:10 +00:00
envTable->CallObjectMethodV = local::CallObjectMethodV;
envTable->CallObjectMethodA = local::CallObjectMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallObjectMethod = local::CallObjectMethod;
envTable->CallBooleanMethodV = local::CallBooleanMethodV;
envTable->CallBooleanMethodA = local::CallBooleanMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallBooleanMethod = local::CallBooleanMethod;
envTable->CallByteMethodV = local::CallByteMethodV;
envTable->CallByteMethodA = local::CallByteMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallByteMethod = local::CallByteMethod;
envTable->CallCharMethodV = local::CallCharMethodV;
envTable->CallCharMethodA = local::CallCharMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallCharMethod = local::CallCharMethod;
envTable->CallShortMethodV = local::CallShortMethodV;
envTable->CallShortMethodA = local::CallShortMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallShortMethod = local::CallShortMethod;
envTable->CallIntMethodV = local::CallIntMethodV;
envTable->CallIntMethodA = local::CallIntMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallIntMethod = local::CallIntMethod;
envTable->CallLongMethodV = local::CallLongMethodV;
envTable->CallLongMethodA = local::CallLongMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallLongMethod = local::CallLongMethod;
envTable->CallFloatMethodV = local::CallFloatMethodV;
envTable->CallFloatMethodA = local::CallFloatMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallFloatMethod = local::CallFloatMethod;
envTable->CallDoubleMethodV = local::CallDoubleMethodV;
envTable->CallDoubleMethodA = local::CallDoubleMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallDoubleMethod = local::CallDoubleMethod;
envTable->CallVoidMethodV = local::CallVoidMethodV;
envTable->CallVoidMethodA = local::CallVoidMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallVoidMethod = local::CallVoidMethod;
envTable->CallStaticObjectMethodV = local::CallStaticObjectMethodV;
envTable->CallStaticObjectMethodA = local::CallStaticObjectMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticObjectMethod = local::CallStaticObjectMethod;
envTable->CallStaticBooleanMethodV = local::CallStaticBooleanMethodV;
envTable->CallStaticBooleanMethodA = local::CallStaticBooleanMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticBooleanMethod = local::CallStaticBooleanMethod;
envTable->CallStaticByteMethodV = local::CallStaticByteMethodV;
envTable->CallStaticByteMethodA = local::CallStaticByteMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticByteMethod = local::CallStaticByteMethod;
envTable->CallStaticCharMethodV = local::CallStaticCharMethodV;
envTable->CallStaticCharMethodA = local::CallStaticCharMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticCharMethod = local::CallStaticCharMethod;
envTable->CallStaticShortMethodV = local::CallStaticShortMethodV;
envTable->CallStaticShortMethodA = local::CallStaticShortMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticShortMethod = local::CallStaticShortMethod;
envTable->CallStaticIntMethodV = local::CallStaticIntMethodV;
envTable->CallStaticIntMethodA = local::CallStaticIntMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticIntMethod = local::CallStaticIntMethod;
envTable->CallStaticLongMethodV = local::CallStaticLongMethodV;
envTable->CallStaticLongMethodA = local::CallStaticLongMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticLongMethod = local::CallStaticLongMethod;
envTable->CallStaticFloatMethodV = local::CallStaticFloatMethodV;
envTable->CallStaticFloatMethodA = local::CallStaticFloatMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticFloatMethod = local::CallStaticFloatMethod;
envTable->CallStaticDoubleMethodV = local::CallStaticDoubleMethodV;
envTable->CallStaticDoubleMethodA = local::CallStaticDoubleMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticDoubleMethod = local::CallStaticDoubleMethod;
envTable->CallStaticVoidMethodV = local::CallStaticVoidMethodV;
envTable->CallStaticVoidMethodA = local::CallStaticVoidMethodA;
2010-04-15 17:11:10 +00:00
envTable->CallStaticVoidMethod = local::CallStaticVoidMethod;
envTable->GetStaticFieldID = local::GetStaticFieldID;
envTable->GetObjectField = local::GetObjectField;
envTable->GetBooleanField = local::GetBooleanField;
envTable->GetByteField = local::GetByteField;
envTable->GetCharField = local::GetCharField;
envTable->GetShortField = local::GetShortField;
envTable->GetIntField = local::GetIntField;
envTable->GetLongField = local::GetLongField;
envTable->GetFloatField = local::GetFloatField;
envTable->GetDoubleField = local::GetDoubleField;
envTable->SetObjectField = local::SetObjectField;
envTable->SetBooleanField = local::SetBooleanField;
envTable->SetByteField = local::SetByteField;
envTable->SetCharField = local::SetCharField;
envTable->SetShortField = local::SetShortField;
envTable->SetIntField = local::SetIntField;
envTable->SetLongField = local::SetLongField;
envTable->SetFloatField = local::SetFloatField;
envTable->SetDoubleField = local::SetDoubleField;
envTable->GetStaticObjectField = local::GetStaticObjectField;
envTable->GetStaticBooleanField = local::GetStaticBooleanField;
envTable->GetStaticByteField = local::GetStaticByteField;
envTable->GetStaticCharField = local::GetStaticCharField;
envTable->GetStaticShortField = local::GetStaticShortField;
envTable->GetStaticIntField = local::GetStaticIntField;
envTable->GetStaticLongField = local::GetStaticLongField;
envTable->GetStaticFloatField = local::GetStaticFloatField;
envTable->GetStaticDoubleField = local::GetStaticDoubleField;
envTable->SetStaticObjectField = local::SetStaticObjectField;
envTable->SetStaticBooleanField = local::SetStaticBooleanField;
envTable->SetStaticByteField = local::SetStaticByteField;
envTable->SetStaticCharField = local::SetStaticCharField;
envTable->SetStaticShortField = local::SetStaticShortField;
envTable->SetStaticIntField = local::SetStaticIntField;
envTable->SetStaticLongField = local::SetStaticLongField;
envTable->SetStaticFloatField = local::SetStaticFloatField;
envTable->SetStaticDoubleField = local::SetStaticDoubleField;
envTable->NewGlobalRef = local::NewGlobalRef;
envTable->NewWeakGlobalRef = local::NewWeakGlobalRef;
2010-04-15 17:11:10 +00:00
envTable->DeleteGlobalRef = local::DeleteGlobalRef;
envTable->DeleteWeakGlobalRef = local::DeleteWeakGlobalRef;
envTable->EnsureLocalCapacity = local::EnsureLocalCapacity;
2010-04-15 17:11:10 +00:00
envTable->ExceptionOccurred = local::ExceptionOccurred;
envTable->ExceptionDescribe = local::ExceptionDescribe;
envTable->ExceptionClear = local::ExceptionClear;
envTable->NewObjectArray = local::NewObjectArray;
envTable->GetObjectArrayElement = local::GetObjectArrayElement;
envTable->SetObjectArrayElement = local::SetObjectArrayElement;
envTable->NewBooleanArray = local::NewBooleanArray;
envTable->NewByteArray = local::NewByteArray;
envTable->NewCharArray = local::NewCharArray;
envTable->NewShortArray = local::NewShortArray;
envTable->NewIntArray = local::NewIntArray;
envTable->NewLongArray = local::NewLongArray;
envTable->NewFloatArray = local::NewFloatArray;
envTable->NewDoubleArray = local::NewDoubleArray;
envTable->GetBooleanArrayElements = local::GetBooleanArrayElements;
envTable->GetByteArrayElements = local::GetByteArrayElements;
envTable->GetCharArrayElements = local::GetCharArrayElements;
envTable->GetShortArrayElements = local::GetShortArrayElements;
envTable->GetIntArrayElements = local::GetIntArrayElements;
envTable->GetLongArrayElements = local::GetLongArrayElements;
envTable->GetFloatArrayElements = local::GetFloatArrayElements;
envTable->GetDoubleArrayElements = local::GetDoubleArrayElements;
envTable->ReleaseBooleanArrayElements = local::ReleaseBooleanArrayElements;
envTable->ReleaseByteArrayElements = local::ReleaseByteArrayElements;
envTable->ReleaseCharArrayElements = local::ReleaseCharArrayElements;
envTable->ReleaseShortArrayElements = local::ReleaseShortArrayElements;
envTable->ReleaseIntArrayElements = local::ReleaseIntArrayElements;
envTable->ReleaseLongArrayElements = local::ReleaseLongArrayElements;
envTable->ReleaseFloatArrayElements = local::ReleaseFloatArrayElements;
envTable->ReleaseDoubleArrayElements = local::ReleaseDoubleArrayElements;
envTable->GetBooleanArrayRegion = local::GetBooleanArrayRegion;
envTable->GetByteArrayRegion = local::GetByteArrayRegion;
envTable->GetCharArrayRegion = local::GetCharArrayRegion;
envTable->GetShortArrayRegion = local::GetShortArrayRegion;
envTable->GetIntArrayRegion = local::GetIntArrayRegion;
envTable->GetLongArrayRegion = local::GetLongArrayRegion;
envTable->GetFloatArrayRegion = local::GetFloatArrayRegion;
envTable->GetDoubleArrayRegion = local::GetDoubleArrayRegion;
envTable->SetBooleanArrayRegion = local::SetBooleanArrayRegion;
envTable->SetByteArrayRegion = local::SetByteArrayRegion;
envTable->SetCharArrayRegion = local::SetCharArrayRegion;
envTable->SetShortArrayRegion = local::SetShortArrayRegion;
envTable->SetIntArrayRegion = local::SetIntArrayRegion;
envTable->SetLongArrayRegion = local::SetLongArrayRegion;
envTable->SetFloatArrayRegion = local::SetFloatArrayRegion;
envTable->SetDoubleArrayRegion = local::SetDoubleArrayRegion;
envTable->GetPrimitiveArrayCritical = local::GetPrimitiveArrayCritical;
envTable->ReleasePrimitiveArrayCritical
2014-07-11 15:50:18 +00:00
= local::ReleasePrimitiveArrayCritical;
envTable->RegisterNatives = local::RegisterNatives;
envTable->UnregisterNatives = local::UnregisterNatives;
2010-04-15 17:11:10 +00:00
envTable->MonitorEnter = local::MonitorEnter;
envTable->MonitorExit = local::MonitorExit;
envTable->GetJavaVM = local::GetJavaVM;
envTable->IsSameObject = local::IsSameObject;
envTable->PushLocalFrame = local::PushLocalFrame;
envTable->PopLocalFrame = local::PopLocalFrame;
envTable->FromReflectedMethod = local::FromReflectedMethod;
envTable->ToReflectedMethod = local::ToReflectedMethod;
envTable->FromReflectedField = local::FromReflectedField;
envTable->ToReflectedField = local::ToReflectedField;
}
2014-07-11 15:50:18 +00:00
} // namespace vm
2014-07-11 15:50:18 +00:00
extern "C" AVIAN_EXPORT jint JNICALL JNI_GetDefaultJavaVMInitArgs(void*)
{
return 0;
}
extern "C" AVIAN_EXPORT jint JNICALL
2014-07-11 15:50:18 +00:00
JNI_GetCreatedJavaVMs(Machine**, jsize, jsize*)
{
// todo
return -1;
}
extern "C" AVIAN_EXPORT jint JNICALL
2014-07-11 15:50:18 +00:00
JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
{
2010-04-15 17:11:10 +00:00
local::JavaVMInitArgs* a = static_cast<local::JavaVMInitArgs*>(args);
unsigned heapLimit = 0;
2012-03-14 18:36:42 +00:00
unsigned stackLimit = 0;
const char* bootLibraries = 0;
const char* classpath = 0;
2010-09-21 00:38:38 +00:00
const char* javaHome = AVIAN_JAVA_HOME;
const char* embedPrefix = AVIAN_EMBED_PREFIX;
const char* bootClasspathPrepend = "";
const char* bootClasspath = 0;
const char* bootClasspathAppend = "";
const char* crashDumpDirectory = 0;
unsigned propertyCount = 0;
for (int i = 0; i < a->nOptions; ++i) {
if (strncmp(a->options[i].optionString, "-X", 2) == 0) {
const char* p = a->options[i].optionString + 2;
if (strncmp(p, "mx", 2) == 0) {
2010-04-15 17:11:10 +00:00
heapLimit = local::parseSize(p + 2);
2012-03-14 18:36:42 +00:00
} else if (strncmp(p, "ss", 2) == 0) {
stackLimit = local::parseSize(p + 2);
2014-07-11 15:50:18 +00:00
} else if (strncmp(p,
BOOTCLASSPATH_PREPEND_OPTION ":",
sizeof(BOOTCLASSPATH_PREPEND_OPTION)) == 0) {
bootClasspathPrepend = p + sizeof(BOOTCLASSPATH_PREPEND_OPTION);
2014-07-11 15:50:18 +00:00
} else if (strncmp(
p, BOOTCLASSPATH_OPTION ":", sizeof(BOOTCLASSPATH_OPTION))
== 0) {
bootClasspath = p + sizeof(BOOTCLASSPATH_OPTION);
2014-07-11 15:50:18 +00:00
} else if (strncmp(p,
BOOTCLASSPATH_APPEND_OPTION ":",
sizeof(BOOTCLASSPATH_APPEND_OPTION)) == 0) {
bootClasspathAppend = p + sizeof(BOOTCLASSPATH_APPEND_OPTION);
}
} else if (strncmp(a->options[i].optionString, "-D", 2) == 0) {
const char* p = a->options[i].optionString + 2;
2014-07-11 15:50:18 +00:00
if (strncmp(p, BOOTSTRAP_PROPERTY "=", sizeof(BOOTSTRAP_PROPERTY)) == 0) {
bootLibraries = p + sizeof(BOOTSTRAP_PROPERTY);
2014-07-11 15:50:18 +00:00
} else if (strncmp(p,
JAVA_COMMAND_PROPERTY "=",
sizeof(JAVA_COMMAND_PROPERTY)) == 0
2014-07-11 15:50:18 +00:00
or strncmp(p,
JAVA_LAUNCHER_PROPERTY "=",
sizeof(JAVA_LAUNCHER_PROPERTY)) == 0) {
// this means we're being invoked via the javac or java
// command, so the bootstrap library should be e.g. libjvm.so
bootLibraries = SO_PREFIX "jvm" SO_SUFFIX;
2014-07-11 15:50:18 +00:00
} else if (strncmp(p, CRASHDIR_PROPERTY "=", sizeof(CRASHDIR_PROPERTY))
== 0) {
crashDumpDirectory = p + sizeof(CRASHDIR_PROPERTY);
2014-07-11 15:50:18 +00:00
} else if (strncmp(p, CLASSPATH_PROPERTY "=", sizeof(CLASSPATH_PROPERTY))
== 0) {
classpath = p + sizeof(CLASSPATH_PROPERTY);
2014-07-11 15:50:18 +00:00
} else if (strncmp(p, JAVA_HOME_PROPERTY "=", sizeof(JAVA_HOME_PROPERTY))
== 0) {
2010-09-21 00:38:38 +00:00
javaHome = p + sizeof(JAVA_HOME_PROPERTY);
2014-07-11 15:50:18 +00:00
} else if (strncmp(p,
EMBED_PREFIX_PROPERTY "=",
sizeof(EMBED_PREFIX_PROPERTY)) == 0) {
embedPrefix = p + sizeof(EMBED_PREFIX_PROPERTY);
}
2014-07-11 15:50:18 +00:00
++propertyCount;
}
}
2014-07-11 15:50:18 +00:00
if (heapLimit == 0)
heapLimit = 128 * 1024 * 1024;
2012-03-14 18:36:42 +00:00
2014-07-11 15:50:18 +00:00
if (stackLimit == 0)
stackLimit = 128 * 1024;
bool addClasspathProperty = classpath == 0;
if (addClasspathProperty) {
classpath = ".";
++propertyCount;
}
2014-02-22 00:06:17 +00:00
System* s = makeSystem();
Heap* h = makeHeap(s, heapLimit);
Classpath* c = makeClasspath(s, h, javaHome, embedPrefix);
if (bootClasspath == 0) {
bootClasspath = c->bootClasspath();
}
unsigned bcppl = strlen(bootClasspathPrepend);
unsigned bcpl = strlen(bootClasspath);
unsigned bcpal = strlen(bootClasspathAppend);
unsigned bootClasspathBufferSize = bcppl + bcpl + bcpal + 3;
RUNTIME_ARRAY(char, bootClasspathBuffer, bootClasspathBufferSize);
char* bootClasspathPointer = RUNTIME_ARRAY_BODY(bootClasspathBuffer);
if (bootClasspathBufferSize > 3) {
2014-07-11 15:50:18 +00:00
local::append(&bootClasspathPointer,
bootClasspathPrepend,
bcppl,
bcpl + bcpal ? PATH_SEPARATOR : 0);
2014-07-11 15:50:18 +00:00
local::append(
&bootClasspathPointer, bootClasspath, bcpl, bcpal ? PATH_SEPARATOR : 0);
local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0);
} else {
*RUNTIME_ARRAY_BODY(bootClasspathBuffer) = 0;
}
char* bootLibrary = bootLibraries ? strdup(bootLibraries) : 0;
char* bootLibraryEnd = bootLibrary ? strchr(bootLibrary, PATH_SEPARATOR) : 0;
2014-07-11 15:50:18 +00:00
if (bootLibraryEnd)
*bootLibraryEnd = 0;
2014-07-11 15:50:18 +00:00
Finder* bf
= makeFinder(s, h, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
Finder* af = makeFinder(s, h, classpath, bootLibrary);
2014-07-11 15:50:18 +00:00
if (bootLibrary)
free(bootLibrary);
2014-02-22 00:06:17 +00:00
Processor* p = makeProcessor(s, h, crashDumpDirectory, true);
// reserve space for avian.version and file.encoding:
propertyCount += 2;
2014-07-11 15:50:18 +00:00
const char** properties = static_cast<const char**>(
h->allocate(sizeof(const char*) * propertyCount));
const char** propertyPointer = properties;
2014-07-11 15:50:18 +00:00
const char** arguments = static_cast<const char**>(
h->allocate(sizeof(const char*) * a->nOptions));
const char** argumentPointer = arguments;
for (int i = 0; i < a->nOptions; ++i) {
if (strncmp(a->options[i].optionString, "-D", 2) == 0) {
*(propertyPointer++) = a->options[i].optionString + 2;
}
*(argumentPointer++) = a->options[i].optionString;
}
unsigned cpl = strlen(classpath);
RUNTIME_ARRAY(char, classpathProperty, cpl + strlen(CLASSPATH_PROPERTY) + 2);
if (addClasspathProperty) {
char* p = RUNTIME_ARRAY_BODY(classpathProperty);
local::append(&p, CLASSPATH_PROPERTY, strlen(CLASSPATH_PROPERTY), '=');
local::append(&p, classpath, cpl, 0);
*(propertyPointer++) = RUNTIME_ARRAY_BODY(classpathProperty);
}
*(propertyPointer++) = "avian.version=" AVIAN_VERSION;
// todo: should this be derived from the OS locale? Should it be
// overrideable via JavaVMInitArgs?
*(propertyPointer++) = "file.encoding=UTF-8";
2014-07-11 15:50:18 +00:00
*m = new (h->allocate(sizeof(Machine))) Machine(s,
h,
bf,
af,
p,
c,
properties,
propertyCount,
arguments,
a->nOptions,
stackLimit);
h->free(properties, sizeof(const char*) * propertyCount);
*t = p->makeThread(*m, 0, 0);
enter(*t, Thread::ActiveState);
enter(*t, Thread::IdleState);
return run(*t, local::boot, 0) ? 0 : -1;
}