corda/src/jnienv.cpp

3978 lines
100 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 {
jint JNICALL
AttachCurrentThread(Machine* m, Thread** t, void*)
{
*t = static_cast<Thread*>(m->localThread->get());
if (*t == 0) {
*t = attachThread(m, false);
}
return 0;
}
jint JNICALL
AttachCurrentThreadAsDaemon(Machine* m, Thread** t, void*)
{
*t = static_cast<Thread*>(m->localThread->get());
if (*t == 0) {
*t = attachThread(m, true);
}
return 0;
}
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);
threadPeer(t, t->javaThread) = 0;
enter(t, Thread::ZombieState);
t->state = Thread::JoinedState;
}
return 0;
} else {
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
uint64_t
destroyJavaVM(Thread* t, uintptr_t*)
{
// wait for other non-daemon threads to exit
{ ACQUIRE(t, t->m->stateLock);
while (t->m->liveCount - t->m->daemonCount > 1) {
t->m->stateLock->wait(t->systemThread, 0);
}
}
{ ENTER(t, Thread::ActiveState);
t->m->classpath->shutDown(t);
}
// wait again in case the Classpath::shutDown process started new
// threads:
{ 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;
}
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 JNICALL
DestroyJavaVM(Machine* m)
{
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;
}
}
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;
}
}
2010-04-15 17:11:10 +00:00
jint JNICALL
2009-06-22 22:25:13 +00:00
GetVersion(Thread* t)
{
ENTER(t, Thread::ActiveState);
return JNI_VERSION_1_6;
}
jsize JNICALL
GetStringLength(Thread* t, jstring s)
{
ENTER(t, Thread::ActiveState);
return stringLength(t, *s);
}
const jchar* JNICALL
GetStringChars(Thread* t, jstring s, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
jchar* chars = static_cast<jchar*>
2008-04-13 18:15:04 +00:00
(t->m->heap->allocate((stringLength(t, *s) + 1) * sizeof(jchar)));
2008-04-02 12:57:25 +00:00
stringChars(t, *s, chars);
if (isCopy) *isCopy = true;
return chars;
}
void JNICALL
ReleaseStringChars(Thread* t, jstring s, const jchar* chars)
{
ENTER(t, Thread::ActiveState);
2008-04-13 18:15:04 +00:00
t->m->heap->free(chars, (stringLength(t, *s) + 1) * sizeof(jchar));
}
void JNICALL
GetStringRegion(Thread* t, jstring s, jsize start, jsize length, jchar* dst)
{
ENTER(t, Thread::ActiveState);
stringChars(t, *s, start, length, dst);
}
const jchar* JNICALL
GetStringCritical(Thread* t, jstring s, jboolean* isCopy)
{
if (t->criticalLevel == 0) {
enter(t, Thread::ActiveState);
}
++ t->criticalLevel;
if (isCopy) {
*isCopy = true;
}
2014-05-29 04:17:25 +00:00
object data = stringData(t, *s);
2014-05-29 04:17:25 +00:00
if (objectClass(t, data) == type(t, GcByteArray::Type)) {
return GetStringChars(t, s, isCopy);
} else {
return &charArrayBody(t, data, stringOffset(t, *s));
}
}
void JNICALL
ReleaseStringCritical(Thread* t, jstring s, const jchar* chars)
{
2014-05-29 04:17:25 +00:00
if (objectClass(t, stringData(t, *s)) == type(t, GcByteArray::Type)) {
ReleaseStringChars(t, s, chars);
}
if ((-- t->criticalLevel) == 0) {
enter(t, Thread::IdleState);
}
}
jsize JNICALL
2007-07-06 23:18:40 +00:00
GetStringUTFLength(Thread* t, jstring s)
{
ENTER(t, Thread::ActiveState);
return stringUTFLength(t, *s);
}
const char* JNICALL
2007-07-06 23:18:40 +00:00
GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
int length = stringUTFLength(t, *s);
2007-07-06 23:18:40 +00:00
char* chars = static_cast<char*>
(t->m->heap->allocate(length + 1));
stringUTFChars(t, *s, chars, length);
if (isCopy) *isCopy = true;
return chars;
}
void JNICALL
ReleaseStringUTFChars(Thread* t, jstring s, const char* chars)
{
ENTER(t, Thread::ActiveState);
t->m->heap->free(chars, stringUTFLength(t, *s) + 1);
}
void JNICALL
GetStringUTFRegion(Thread* t, jstring s, jsize start, jsize length, char* dst)
{
ENTER(t, Thread::ActiveState);
stringUTFChars
(t, *s, start, length, dst, stringUTFLength(t, *s, start, length));
}
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);
}
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
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-05-29 04:17:25 +00:00
object a = reinterpret_cast<object>(makeCharArray(t, size));
2007-10-26 21:23:54 +00:00
if (size) {
memcpy(&charArrayBody(t, a, 0), chars, size * sizeof(jchar));
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
return reinterpret_cast<uint64_t>
(makeLocalReference(t, t->m->classpath->makeString(t, a, 0, size)));
2007-10-26 21:23:54 +00:00
}
jstring JNICALL
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
NewString(Thread* t, const jchar* chars, jsize size)
2007-07-07 23:47:35 +00:00
{
if (chars == 0) return 0;
2012-06-01 17:46:56 +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));
}
uint64_t
newStringUTF(Thread* t, uintptr_t* arguments)
{
const char* chars = reinterpret_cast<const char*>(arguments[0]);
2007-07-07 23:47:35 +00:00
object array = parseUtf8(t, chars, strlen(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<uint64_t>
(makeLocalReference
(t, t->m->classpath->makeString
2013-02-11 00:38:51 +00:00
(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
}
jstring JNICALL
NewStringUTF(Thread* t, const char* chars)
{
if (chars == 0) return 0;
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(chars) };
return reinterpret_cast<jstring>(run(t, newStringUTF, arguments));
2007-07-07 23:47:35 +00:00
}
void
replace(int a, int b, const char* in, int8_t* out)
{
while (*in) {
*out = (*in == a ? b : *in);
++ in;
++ out;
}
*out = 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
uint64_t
defineClass(Thread* t, uintptr_t* arguments)
{
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,
getJClass(t,
cast<GcClass>(t, defineClass(t,
loader ? *loader : root(t, Machine::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
}
jclass JNICALL
DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer,
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[] = { reinterpret_cast<uintptr_t>(loader),
reinterpret_cast<uintptr_t>(buffer),
2012-06-01 17:46:56 +00:00
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));
}
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
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-05-29 04:17:25 +00:00
object n = reinterpret_cast<object>(makeByteArray(t, strlen(name) + 1));
replace('.', '/', name, &byteArrayBody(t, n, 0));
2014-05-29 04:17:25 +00:00
GcMethod* caller = getCaller(t, 0);
2014-05-29 04:17:25 +00:00
GcClass* c = resolveClass(t,
caller ? t->m->classpath->libraryClassLoader(t, caller)
: root(t, Machine::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
}
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 JNICALL
FindClass(Thread* t, const char* name)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(name) };
return reinterpret_cast<jclass>(run(t, findClass, 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
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]);
object m = 0;
PROTECT(t, m);
if (message) {
m = makeString(t, "%s", message);
}
object trace = makeTrace(t);
PROTECT(t, trace);
2014-05-29 04:17:25 +00:00
t->exception = make(t, cast<GcClass>(t, jclassVmClass(t, *c)));
set(t, t->exception, ThrowableMessage, m);
set(t, t->exception, ThrowableTrace, 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;
}
jint JNICALL
ThrowNew(Thread* t, jclass c, const char* message)
{
if (t->exception) {
return -1;
}
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
reinterpret_cast<uintptr_t>(message) };
return run(t, throwNew, arguments) ? 0 : -1;
}
jint JNICALL
Throw(Thread* t, jthrowable throwable)
{
if (t->exception) {
return -1;
}
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
t->exception = *throwable;
return 0;
}
2012-12-20 16:05:30 +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);
}
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
}
jboolean JNICALL
ExceptionCheck(Thread* t)
{
return t->exception != 0;
}
uint64_t
getObjectClass(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jclass>(arguments[0]);
2014-05-29 04:17:25 +00:00
return reinterpret_cast<uint64_t>(makeLocalReference(
t, getJClass(t, objectClass(t, *o))));
}
jclass JNICALL
GetObjectClass(Thread* t, jobject o)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o) };
return reinterpret_cast<jclass>(run(t, getObjectClass, arguments));
}
uint64_t
getSuperclass(Thread* t, uintptr_t* arguments)
{
object class_ = jclassVmClass(t, *reinterpret_cast<jclass>(arguments[0]));
if (classFlags(t, class_) & ACC_INTERFACE) {
return 0;
} else {
object super = classSuper(t, class_);
return super ? reinterpret_cast<uint64_t>
2014-05-29 04:17:25 +00:00
(makeLocalReference(t, getJClass(t, cast<GcClass>(t, super)))) : 0;
}
}
jclass JNICALL
GetSuperclass(Thread* t, jclass c)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
2007-09-07 23:20:21 +00:00
return reinterpret_cast<jclass>(run(t, getSuperclass, arguments));
}
uint64_t
isInstanceOf(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
jclass c = reinterpret_cast<jclass>(arguments[1]);
2014-05-29 04:17:25 +00:00
return instanceOf(t, cast<GcClass>(t, jclassVmClass(t, *c)), *o);
}
jboolean JNICALL
IsInstanceOf(Thread* t, jobject o, jclass c)
{
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);
}
uint64_t
isAssignableFrom(Thread* t, uintptr_t* arguments)
{
jclass b = reinterpret_cast<jclass>(arguments[0]);
jclass a = reinterpret_cast<jclass>(arguments[1]);
2014-05-29 04:17:25 +00:00
return isAssignableFrom(t, cast<GcClass>(t, jclassVmClass(t, *a)), cast<GcClass>(t, jclassVmClass(t, *b)));
}
jboolean JNICALL
IsAssignableFrom(Thread* t, jclass b, jclass a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(b),
reinterpret_cast<uintptr_t>(a) };
return run(t, isAssignableFrom, arguments);
}
2014-05-29 04:17:25 +00:00
GcMethod*
findMethod(Thread* t, jclass c, const char* name, const char* spec)
{
object n = makeByteArray(t, "%s", name);
PROTECT(t, n);
object s = makeByteArray(t, "%s", spec);
2014-05-29 04:17:25 +00:00
return vm::findMethod(t, cast<GcClass>(t, jclassVmClass(t, *c)), n, s);
}
jint
2014-05-29 04:17:25 +00:00
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) {
setRoot(t, Machine::JNIMethodTable, vectorAppend
2014-05-29 04:17:25 +00:00
(t, root(t, Machine::JNIMethodTable), reinterpret_cast<object>(method)));
storeStoreMemoryBarrier();
2014-05-29 04:17:25 +00:00
method->nativeID() = vectorSize
(t, root(t, Machine::JNIMethodTable));
}
}
2014-05-29 04:17:25 +00:00
return method->nativeID();
}
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
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
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
GetMethodID(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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
reinterpret_cast<uintptr_t>(name),
reinterpret_cast<uintptr_t>(spec) };
return run(t, getMethodID, arguments);
}
uint64_t
getStaticMethodID(Thread* t, uintptr_t* arguments)
{
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
GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
reinterpret_cast<uintptr_t>(name),
reinterpret_cast<uintptr_t>(spec) };
return run(t, getStaticMethodID, arguments);
}
2014-05-29 04:17:25 +00:00
GcMethod*
getMethod(Thread* t, jmethodID m)
{
assertT(t, m);
2014-05-29 04:17:25 +00:00
GcMethod* method = cast<GcMethod>(t, vectorBody(t, root(t, Machine::JNIMethodTable), 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;
}
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
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-05-29 04:17:25 +00:00
object o = make(t, cast<GcClass>(t, jclassVmClass(t, *c)));
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));
}
jobject JNICALL
NewObjectV(Thread* t, jclass c, jmethodID m, va_list a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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));
}
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;
}
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-05-29 04:17:25 +00:00
object o = make(t, cast<GcClass>(t, jclassVmClass(t, *c)));
PROTECT(t, o);
t->m->processor->invokeArray(t, getMethod(t, m), o, a);
return reinterpret_cast<uint64_t>(makeLocalReference(t, o));
}
jobject JNICALL
NewObjectA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return reinterpret_cast<jobject>(run(t, newObjectA, 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
uint64_t
callObjectMethodV(Thread* t, uintptr_t* arguments)
{
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]);
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
}
2007-09-07 23:20:21 +00:00
jobject JNICALL
CallObjectMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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));
}
jobject JNICALL
2007-09-07 23:20:21 +00:00
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;
}
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]);
return reinterpret_cast<uint64_t>
(makeLocalReference
(t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a)));
}
jobject JNICALL
CallObjectMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return reinterpret_cast<jobject>(run(t, callObjectMethodA, 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
uint64_t
callIntMethodV(Thread* t, uintptr_t* arguments)
{
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]);
return intValue
(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
}
jboolean JNICALL
2007-09-07 23:20:21 +00:00
CallBooleanMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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
}
jboolean JNICALL
CallBooleanMethod(Thread* t, jobject o, jmethodID m, ...)
{
va_list a;
va_start(a, m);
jboolean r = CallBooleanMethodV(t, o, m, a);
va_end(a);
return r;
}
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]);
return intValue
(t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a));
}
jboolean JNICALL
CallBooleanMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return run(t, callIntMethodA, arguments) != 0;
}
jbyte JNICALL
2007-09-07 23:20:21 +00:00
CallByteMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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
}
jbyte JNICALL
CallByteMethod(Thread* t, jobject o, jmethodID m, ...)
{
va_list a;
va_start(a, m);
jbyte r = CallByteMethodV(t, o, m, a);
va_end(a);
return r;
}
jbyte JNICALL
CallByteMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return run(t, callIntMethodA, arguments);
}
jchar JNICALL
2007-09-07 23:20:21 +00:00
CallCharMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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
}
jchar JNICALL
CallCharMethod(Thread* t, jobject o, jmethodID m, ...)
{
va_list a;
va_start(a, m);
jchar r = CallCharMethodV(t, o, m, a);
va_end(a);
return r;
}
jchar JNICALL
CallCharMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return run(t, callIntMethodA, arguments);
}
jshort JNICALL
2007-09-07 23:20:21 +00:00
CallShortMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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
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
CallShortMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return run(t, callIntMethodA, arguments);
}
2007-09-07 23:20:21 +00:00
jint JNICALL
CallIntMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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
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;
}
jint JNICALL
CallIntMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return run(t, callIntMethodA, 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
uint64_t
callLongMethodV(Thread* t, uintptr_t* arguments)
{
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]);
return longValue
(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
}
2007-09-07 23:20:21 +00:00
jlong JNICALL
CallLongMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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);
}
2007-09-07 23:20:21 +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;
}
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]);
return longValue
(t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a));
}
jlong JNICALL
CallLongMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return run(t, callLongMethodA, arguments);
}
2007-09-07 23:20:21 +00:00
jfloat JNICALL
CallFloatMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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));
}
2007-09-07 23:20:21 +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
CallFloatMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return bitsToFloat(run(t, callIntMethodA, arguments));
}
2007-09-07 23:20:21 +00:00
jdouble JNICALL
CallDoubleMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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));
}
2007-09-07 23:20:21 +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
CallDoubleMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
return bitsToDouble(run(t, callLongMethodA, 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
uint64_t
callVoidMethodV(Thread* t, uintptr_t* arguments)
{
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;
}
void JNICALL
2007-09-07 23:20:21 +00:00
CallVoidMethodV(Thread* t, jobject o, 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
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +00:00
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);
}
void JNICALL
2007-09-07 23:20:21 +00:00
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);
}
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;
}
void JNICALL
CallVoidMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
m,
reinterpret_cast<uintptr_t>(a) };
run(t, callVoidMethodA, arguments);
}
2014-05-29 04:17:25 +00:00
GcMethod*
getStaticMethod(Thread* t, jmethodID m)
{
assertT(t, m);
2014-05-29 04:17:25 +00:00
GcMethod* method = cast<GcMethod>(t, vectorBody(t, root(t, Machine::JNIMethodTable), 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;
}
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
uint64_t
callStaticObjectMethodV(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
return reinterpret_cast<uint64_t>
(makeLocalReference
(t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a)));
}
2007-09-07 23:20:21 +00:00
jobject JNICALL
CallStaticObjectMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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));
}
jobject JNICALL
2007-09-07 23:20:21 +00:00
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;
}
uint64_t
callStaticObjectMethodA(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
return reinterpret_cast<uint64_t>
(makeLocalReference
(t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a)));
}
jobject JNICALL
CallStaticObjectMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
return reinterpret_cast<jobject>(run(t, callStaticObjectMethodA, 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
uint64_t
callStaticIntMethodV(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
return intValue
(t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a));
}
jboolean JNICALL
CallStaticBooleanMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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;
}
2007-09-07 23:20:21 +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;
}
uint64_t
callStaticIntMethodA(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
return intValue
(t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a));
}
jboolean JNICALL
CallStaticBooleanMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
return run(t, callStaticIntMethodA, arguments) != 0;
}
2007-09-07 23:20:21 +00:00
jbyte JNICALL
CallStaticByteMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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);
}
2007-09-07 23:20:21 +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
CallStaticByteMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
return run(t, callStaticIntMethodA, arguments);
}
2007-09-07 23:20:21 +00:00
jchar JNICALL
CallStaticCharMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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);
}
2007-09-07 23:20:21 +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
CallStaticCharMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
return run(t, callStaticIntMethodA, arguments);
}
2007-09-07 23:20:21 +00:00
jshort JNICALL
CallStaticShortMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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);
}
2007-09-07 23:20:21 +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
CallStaticShortMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
return run(t, callStaticIntMethodA, arguments);
}
2007-09-07 23:20:21 +00:00
jint JNICALL
CallStaticIntMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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);
}
2007-09-07 23:20:21 +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
CallStaticIntMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
return run(t, callStaticIntMethodA, 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
uint64_t
callStaticLongMethodV(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
return longValue
(t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a));
}
2007-09-07 23:20:21 +00:00
jlong JNICALL
CallStaticLongMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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);
}
2007-09-07 23:20:21 +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;
}
uint64_t
callStaticLongMethodA(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[0];
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
return longValue
(t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a));
}
jlong JNICALL
CallStaticLongMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
return run(t, callStaticLongMethodA, arguments);
}
2007-09-07 23:20:21 +00:00
jfloat JNICALL
CallStaticFloatMethodV(Thread* t, jclass, jmethodID m, va_list a)
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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));
}
2007-09-07 23:20:21 +00:00
jfloat JNICALL
CallStaticFloatMethod(Thread* t, jclass c, jmethodID m, ...)
{
va_list a;
va_start(a, m);
jfloat r = CallStaticFloatMethodV(t, c, m, a);
va_end(a);
return r;
}
jfloat JNICALL
CallStaticFloatMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
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
CallStaticDoubleMethodV(Thread* t, jclass, jmethodID m, va_list a)
2007-09-07 23:20:21 +00:00
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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
}
jdouble JNICALL
CallStaticDoubleMethod(Thread* t, jclass c, jmethodID m, ...)
{
va_list a;
va_start(a, m);
jdouble r = CallStaticDoubleMethodV(t, c, m, a);
va_end(a);
return r;
}
jdouble JNICALL
CallStaticDoubleMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
return bitsToDouble(run(t, callStaticLongMethodA, 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
uint64_t
callStaticVoidMethodV(Thread* t, uintptr_t* arguments)
{
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;
}
2007-09-07 23:20:21 +00:00
void JNICALL
CallStaticVoidMethodV(Thread* t, jclass, jmethodID m, va_list a)
2007-09-07 23:20:21 +00:00
{
support stack unwinding without using a frame pointer Previously, we unwound the stack by following the chain of frame pointers for normal returns, stack trace creation, and exception unwinding. On x86, this required reserving EBP/RBP for frame pointer duties, making it unavailable for general computation and requiring that it be explicitly saved and restored on entry and exit, respectively. On PowerPC, we use an ABI that makes the stack pointer double as a frame pointer, so it doesn't cost us anything. We've been using the same convention on ARM, but it doesn't match the native calling convention, which makes it unusable when we want to call native code from Java and pass arguments on the stack. So far, the ARM calling convention mismatch hasn't been an issue because we've never passed more arguments from Java to native code than would fit in registers. However, we must now pass an extra argument (the thread pointer) to e.g. divideLong so it can throw an exception on divide by zero, which means the last argument must be passed on the stack. This will clobber the linkage area we've been using to hold the frame pointer, so we need to stop using it. One solution would be to use the same convention on ARM as we do on x86, but this would introduce the same overhead of making a register unavailable for general use and extra code at method entry and exit. Instead, this commit removes the need for a frame pointer. Unwinding involves consulting a map of instruction offsets to frame sizes which is generated at compile time. This is necessary because stack trace creation can happen at any time due to Thread.getStackTrace being called by another thread, and the frame size varies during the execution of a method. So far, only x86(_64) is working, and continuations and tail call optimization are probably broken. More to come.
2011-01-17 02:05:05 +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
}
void JNICALL
CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...)
{
va_list a;
va_start(a, m);
CallStaticVoidMethodV(t, c, m, a);
va_end(a);
}
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
CallStaticVoidMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
{
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
run(t, callStaticVoidMethodA, arguments);
}
jint
fieldID(Thread* t, object field)
{
int id = fieldNativeID(t, field);
loadMemoryBarrier();
if (id == 0) {
PROTECT(t, field);
ACQUIRE(t, t->m->referenceLock);
2014-05-29 04:17:25 +00:00
if (fieldNativeID(t, field) == 0) {
setRoot(t, Machine::JNIFieldTable, vectorAppend
(t, root(t, Machine::JNIFieldTable), field));
storeStoreMemoryBarrier();
fieldNativeID(t, field) = vectorSize(t, root(t, Machine::JNIFieldTable));
}
}
return fieldNativeID(t, field);
}
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
uint64_t
getFieldID(Thread* t, uintptr_t* arguments)
{
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
return fieldID(t, resolveField(t, cast<GcClass>(t, jclassVmClass(t, *c)), 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
GetFieldID(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
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
GetStaticFieldID(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
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
}
object
getField(Thread* t, jfieldID f)
{
assertT(t, f);
object field = vectorBody(t, root(t, Machine::JNIFieldTable), f - 1);
assertT(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
return field;
}
uint64_t
getObjectField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
return reinterpret_cast<uintptr_t>
2013-02-11 00:38:51 +00:00
(makeLocalReference(t, fieldAtOffset<object>(*o, fieldOffset(t, field))));
}
2007-09-07 23:20:21 +00:00
jobject JNICALL
GetObjectField(Thread* t, jobject o, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field };
return reinterpret_cast<jobject>(run(t, getObjectField, arguments));
}
uint64_t
getBooleanField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jboolean>(*o, fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jboolean JNICALL
GetBooleanField(Thread* t, jobject o, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field };
return run(t, getBooleanField, arguments);
}
uint64_t
getByteField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jbyte>(*o, fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jbyte JNICALL
GetByteField(Thread* t, jobject o, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field };
2007-09-07 23:20:21 +00:00
return run(t, getByteField, arguments);
}
uint64_t
getCharField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jchar>(*o, fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jchar JNICALL
GetCharField(Thread* t, jobject o, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field };
return run(t, getCharField, arguments);
}
uint64_t
getShortField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jshort>(*o, fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jshort JNICALL
GetShortField(Thread* t, jobject o, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field };
return run(t, getShortField, arguments);
}
uint64_t
getIntField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jint>(*o, fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jint JNICALL
GetIntField(Thread* t, jobject o, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field };
2007-09-07 23:20:21 +00:00
return run(t, getIntField, arguments);
}
uint64_t
getLongField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jlong>(*o, fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jlong JNICALL
GetLongField(Thread* t, jobject o, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field };
2007-09-07 23:20:21 +00:00
return run(t, getLongField, arguments);
}
uint64_t
getFloatField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2013-02-11 00:38:51 +00:00
return floatToBits(fieldAtOffset<jfloat>(*o, fieldOffset(t, field)));
2007-09-07 23:20:21 +00:00
}
jfloat JNICALL
GetFloatField(Thread* t, jobject o, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field };
2007-09-07 23:20:21 +00:00
return bitsToFloat(run(t, getFloatField, arguments));
}
uint64_t
getDoubleField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2013-02-11 00:38:51 +00:00
return doubleToBits(fieldAtOffset<jdouble>(*o, fieldOffset(t, field)));
2007-09-07 23:20:21 +00:00
}
jdouble JNICALL
GetDoubleField(Thread* t, jobject o, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field };
return bitsToDouble(run(t, getDoubleField, arguments));
}
uint64_t
setObjectField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
jobject v = reinterpret_cast<jobject>(arguments[2]);
2014-05-29 04:17:25 +00:00
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2007-09-07 23:20:21 +00:00
set(t, *o, fieldOffset(t, field), (v ? *v : 0));
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetObjectField(Thread* t, jobject o, jfieldID field, jobject v)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field,
reinterpret_cast<uintptr_t>(v) };
run(t, setObjectField, arguments);
}
uint64_t
setBooleanField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
jboolean v = arguments[2];
2014-05-29 04:17:25 +00:00
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jboolean>(*o, fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetBooleanField(Thread* t, jobject o, jfieldID field, jboolean v)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field,
v };
run(t, setBooleanField, arguments);
}
2007-09-07 23:20:21 +00:00
uint64_t
setByteField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
jbyte v = arguments[2];
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jbyte>(*o, fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetByteField(Thread* t, jobject o, jfieldID field, jbyte v)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field,
2012-06-01 17:46:56 +00:00
static_cast<uintptr_t>(v) };
2007-09-07 23:20:21 +00:00
run(t, setByteField, arguments);
}
uint64_t
setCharField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
jchar v = arguments[2];
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jchar>(*o, fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetCharField(Thread* t, jobject o, jfieldID field, jchar v)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field,
v };
2007-09-07 23:20:21 +00:00
run(t, setCharField, arguments);
}
uint64_t
setShortField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
jshort v = arguments[2];
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jshort>(*o, fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetShortField(Thread* t, jobject o, jfieldID field, jshort v)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field,
2012-06-01 17:46:56 +00:00
static_cast<uintptr_t>(v) };
2007-09-07 23:20:21 +00:00
run(t, setShortField, arguments);
}
uint64_t
setIntField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
jint v = arguments[2];
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jint>(*o, fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetIntField(Thread* t, jobject o, jfieldID field, jint v)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field,
2012-06-01 17:46:56 +00:00
static_cast<uintptr_t>(v) };
2007-09-07 23:20:21 +00:00
run(t, setIntField, arguments);
}
uint64_t
setLongField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
jlong v; memcpy(&v, arguments + 2, sizeof(jlong));
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jlong>(*o, fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetLongField(Thread* t, jobject o, jfieldID field, jlong v)
{
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
uint64_t
setFloatField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
jfloat v = bitsToFloat(arguments[2]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jfloat>(*o, fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetFloatField(Thread* t, jobject o, jfieldID field, jfloat v)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
field,
floatToBits(v) };
run(t, setFloatField, arguments);
}
uint64_t
setDoubleField(Thread* t, uintptr_t* arguments)
{
jobject o = reinterpret_cast<jobject>(arguments[0]);
object field = getField(t, arguments[1]);
jdouble v; memcpy(&v, arguments + 2, sizeof(jdouble));
2007-09-07 23:20:21 +00:00
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jdouble>(*o, fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetDoubleField(Thread* t, jobject o, jfieldID field, jdouble v)
{
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);
}
object
getStaticField(Thread* t, jfieldID f)
{
assertT(t, f);
object field = vectorBody(t, root(t, Machine::JNIFieldTable), f - 1);
assertT(t, fieldFlags(t, field) & ACC_STATIC);
return field;
}
uint64_t
getStaticObjectField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
return reinterpret_cast<uintptr_t>
(makeLocalReference
2013-02-11 00:38:51 +00:00
(t, fieldAtOffset<object>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field))));
2007-09-07 23:20:21 +00:00
}
jobject JNICALL
GetStaticObjectField(Thread* t, jobject c, jfieldID field)
2007-09-07 23:20:21 +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));
}
uint64_t
getStaticBooleanField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jboolean>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jboolean JNICALL
GetStaticBooleanField(Thread* t, jobject c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field };
return run(t, getStaticBooleanField, arguments);
}
uint64_t
getStaticByteField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jbyte>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jbyte JNICALL
GetStaticByteField(Thread* t, jobject c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field };
return run(t, getStaticByteField, arguments);
}
uint64_t
getStaticCharField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jchar>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jchar JNICALL
GetStaticCharField(Thread* t, jobject c, jfieldID field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field };
2007-09-07 23:20:21 +00:00
return run(t, getStaticCharField, arguments);
}
uint64_t
getStaticShortField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jshort>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jshort JNICALL
GetStaticShortField(Thread* t, jobject c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field };
return run(t, getStaticShortField, arguments);
}
uint64_t
getStaticIntField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jint>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jint JNICALL
GetStaticIntField(Thread* t, jobject c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field };
return run(t, getStaticIntField, arguments);
}
uint64_t
getStaticLongField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
return fieldAtOffset<jlong>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
2007-09-07 23:20:21 +00:00
}
jlong JNICALL
GetStaticLongField(Thread* t, jobject c, jfieldID field)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field };
return run(t, getStaticLongField, arguments);
}
uint64_t
getStaticFloatField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
return floatToBits
2013-02-11 00:38:51 +00:00
(fieldAtOffset<jfloat>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)));
2007-09-07 23:20:21 +00:00
}
jfloat JNICALL
GetStaticFloatField(Thread* t, jobject c, jfieldID field)
2007-09-07 23:20:21 +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));
}
uint64_t
getStaticDoubleField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_READ(t, field);
return doubleToBits
2013-02-11 00:38:51 +00:00
(fieldAtOffset<jdouble>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)));
2007-09-07 23:20:21 +00:00
}
jdouble JNICALL
GetStaticDoubleField(Thread* t, jobject c, jfieldID field)
2007-09-07 23:20:21 +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));
}
uint64_t
setStaticObjectField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
jobject v = reinterpret_cast<jobject>(arguments[2]);
2014-05-29 04:17:25 +00:00
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
set(t, classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field),
(v ? *v : 0));
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetStaticObjectField(Thread* t, jobject c, jfieldID field, jobject v)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field,
reinterpret_cast<uintptr_t>(v) };
run(t, setStaticObjectField, arguments);
}
uint64_t
setStaticBooleanField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
jboolean v = arguments[2];
2014-05-29 04:17:25 +00:00
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2007-09-07 23:20:21 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jboolean>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetStaticBooleanField(Thread* t, jobject c, jfieldID field, jboolean v)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field,
v };
run(t, setStaticBooleanField, arguments);
}
uint64_t
setStaticByteField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
jbyte v = arguments[2];
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jbyte>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetStaticByteField(Thread* t, jobject c, jfieldID field, jbyte v)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field,
2012-06-01 17:46:56 +00:00
static_cast<uintptr_t>(v) };
run(t, setStaticByteField, arguments);
}
uint64_t
setStaticCharField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
jchar v = arguments[2];
2007-09-07 23:20:21 +00:00
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jchar>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetStaticCharField(Thread* t, jobject c, jfieldID field, jchar v)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field,
v };
2007-09-07 23:20:21 +00:00
run(t, setStaticCharField, arguments);
}
uint64_t
setStaticShortField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
jshort v = arguments[2];
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jshort>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetStaticShortField(Thread* t, jobject c, jfieldID field, jshort v)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field,
2012-06-01 17:46:56 +00:00
static_cast<uintptr_t>(v) };
run(t, setStaticShortField, arguments);
}
2007-09-07 23:20:21 +00:00
uint64_t
setStaticIntField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
jint v = arguments[2];
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jint>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
2007-09-07 23:20:21 +00:00
}
void JNICALL
SetStaticIntField(Thread* t, jobject c, jfieldID field, jint v)
2007-09-07 23:20:21 +00:00
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field,
2012-06-01 17:46:56 +00:00
static_cast<uintptr_t>(v) };
2007-09-07 23:20:21 +00:00
run(t, setStaticIntField, arguments);
}
uint64_t
setStaticLongField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
jlong v; memcpy(&v, arguments + 2, sizeof(jlong));
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jlong>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
}
void JNICALL
SetStaticLongField(Thread* t, jobject 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);
}
uint64_t
setStaticFloatField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
jfloat v = bitsToFloat(arguments[2]);
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jfloat>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
}
void JNICALL
SetStaticFloatField(Thread* t, jobject c, jfieldID field, jfloat v)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
field,
floatToBits(v) };
2007-09-07 23:20:21 +00:00
run(t, setStaticFloatField, arguments);
}
uint64_t
setStaticDoubleField(Thread* t, uintptr_t* arguments)
{
jobject c = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
initClass(t, cast<GcClass>(t, jclassVmClass(t, *c)));
object field = getStaticField(t, arguments[1]);
jdouble v; memcpy(&v, arguments + 2, sizeof(jdouble));
PROTECT(t, field);
ACQUIRE_FIELD_FOR_WRITE(t, field);
2014-05-29 04:17:25 +00:00
2013-02-11 00:38:51 +00:00
fieldAtOffset<jdouble>
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
2014-05-29 04:17:25 +00:00
return 1;
}
void JNICALL
SetStaticDoubleField(Thread* t, jobject 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);
}
2007-09-07 23:20:21 +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)))
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
}
jobject JNICALL
NewGlobalRef(Thread* t, jobject o)
{
return newGlobalRef(t, o, false);
}
2007-09-07 23:20:21 +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
}
}
jobject JNICALL
NewWeakGlobalRef(Thread* t, jobject o)
{
return newGlobalRef(t, o, true);
}
void JNICALL
DeleteWeakGlobalRef(Thread* t, jobject r)
{
DeleteGlobalRef(t, r);
}
jint JNICALL
EnsureLocalCapacity(Thread*, jint)
{
return 0;
}
2007-09-07 23:20:21 +00:00
jthrowable JNICALL
ExceptionOccurred(Thread* t)
{
ENTER(t, Thread::ActiveState);
return makeLocalReference(t, t->exception);
2007-09-07 23:20:21 +00:00
}
void JNICALL
ExceptionDescribe(Thread* t)
{
ENTER(t, Thread::ActiveState);
return printTrace(t, t->exception);
}
void JNICALL
ExceptionClear(Thread* t)
{
ENTER(t, Thread::ActiveState);
t->exception = 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
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-05-29 04:17:25 +00:00
object a = makeObjectArray(t, cast<GcClass>(t, jclassVmClass(t, *class_)), length);
object value = (init ? *init : 0);
for (jsize i = 0; i < length; ++i) {
set(t, a, ArrayBody + (i * BytesPerWord), 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
return reinterpret_cast<uint64_t>(makeLocalReference(t, a));
}
jobjectArray JNICALL
NewObjectArray(Thread* t, jsize length, jclass class_, jobject init)
{
2012-06-01 17:46:56 +00:00
uintptr_t arguments[] = { 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
reinterpret_cast<uintptr_t>(class_),
reinterpret_cast<uintptr_t>(init) };
return reinterpret_cast<jobjectArray>(run(t, newObjectArray, arguments));
}
jobject JNICALL
GetObjectArrayElement(Thread* t, jobjectArray array, jsize index)
{
ENTER(t, Thread::ActiveState);
return makeLocalReference(t, objectArrayBody(t, *array, index));
}
void JNICALL
SetObjectArrayElement(Thread* t, jobjectArray array, jsize index,
jobject value)
{
ENTER(t, Thread::ActiveState);
set(t, *array, ArrayBody + (index * BytesPerWord), (value ? *value : 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
uint64_t
newArray(Thread* t, uintptr_t* arguments)
{
object (*constructor)(Thread*, unsigned)
= reinterpret_cast<object (*)(Thread*, unsigned)>(arguments[0]);
jsize length = arguments[1];
return reinterpret_cast<uint64_t>
(makeLocalReference(t, constructor(t, length)));
}
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[]
= { reinterpret_cast<uintptr_t>(voidPointer(makeBooleanArray)),
2012-06-01 17:46:56 +00:00
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));
}
object
makeByteArray0(Thread* t, unsigned length)
{
2014-05-29 04:17:25 +00:00
return reinterpret_cast<object>(makeByteArray(t, length));
}
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[]
= { reinterpret_cast<uintptr_t>(voidPointer(makeByteArray0)),
2012-06-01 17:46:56 +00:00
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));
}
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[]
= { reinterpret_cast<uintptr_t>(voidPointer(makeCharArray)),
2012-06-01 17:46:56 +00:00
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));
}
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[]
= { reinterpret_cast<uintptr_t>(voidPointer(makeShortArray)),
2012-06-01 17:46:56 +00:00
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));
}
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[]
= { reinterpret_cast<uintptr_t>(voidPointer(makeIntArray)),
2012-06-01 17:46:56 +00:00
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));
}
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[]
= { reinterpret_cast<uintptr_t>(voidPointer(makeLongArray)),
2012-06-01 17:46:56 +00:00
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));
}
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[]
= { reinterpret_cast<uintptr_t>(voidPointer(makeFloatArray)),
2012-06-01 17:46:56 +00:00
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));
}
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[]
= { reinterpret_cast<uintptr_t>(voidPointer(makeDoubleArray)),
2012-06-01 17:46:56 +00:00
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
GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
unsigned size = booleanArrayLength(t, *array) * 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) {
memcpy(p, &booleanArrayBody(t, *array, 0), size);
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jbyte* JNICALL
GetByteArrayElements(Thread* t, jbyteArray array, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
unsigned size = byteArrayLength(t, *array) * 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) {
memcpy(p, &byteArrayBody(t, *array, 0), size);
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jchar* JNICALL
GetCharArrayElements(Thread* t, jcharArray array, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
unsigned size = charArrayLength(t, *array) * 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) {
memcpy(p, &charArrayBody(t, *array, 0), size);
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jshort* JNICALL
GetShortArrayElements(Thread* t, jshortArray array, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
unsigned size = shortArrayLength(t, *array) * 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) {
memcpy(p, &shortArrayBody(t, *array, 0), size);
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jint* JNICALL
GetIntArrayElements(Thread* t, jintArray array, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
unsigned size = intArrayLength(t, *array) * 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) {
memcpy(p, &intArrayBody(t, *array, 0), size);
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jlong* JNICALL
GetLongArrayElements(Thread* t, jlongArray array, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
unsigned size = longArrayLength(t, *array) * 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) {
memcpy(p, &longArrayBody(t, *array, 0), size);
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jfloat* JNICALL
GetFloatArrayElements(Thread* t, jfloatArray array, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
unsigned size = floatArrayLength(t, *array) * 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) {
memcpy(p, &floatArrayBody(t, *array, 0), size);
}
if (isCopy) {
*isCopy = true;
}
return p;
}
jdouble* JNICALL
GetDoubleArrayElements(Thread* t, jdoubleArray array, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
unsigned size = doubleArrayLength(t, *array) * 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) {
memcpy(p, &doubleArrayBody(t, *array, 0), size);
}
if (isCopy) {
*isCopy = true;
}
return p;
}
void JNICALL
ReleaseBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* p,
jint mode)
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
memcpy(&booleanArrayBody(t, *array, 0), p, size);
}
}
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
ReleaseByteArrayElements(Thread* t, jbyteArray array, jbyte* p, jint mode)
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
unsigned size = byteArrayLength(t, *array) * sizeof(jbyte);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
memcpy(&byteArrayBody(t, *array, 0), p, size);
}
}
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
ReleaseCharArrayElements(Thread* t, jcharArray array, jchar* p, jint mode)
{
ENTER(t, Thread::ActiveState);
unsigned size = charArrayLength(t, *array) * 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) {
memcpy(&charArrayBody(t, *array, 0), p, size);
}
}
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
ReleaseShortArrayElements(Thread* t, jshortArray array, jshort* p, jint mode)
{
2014-05-29 04:17:25 +00:00
ENTER(t, Thread::ActiveState);
unsigned size = shortArrayLength(t, *array) * sizeof(jshort);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
memcpy(&shortArrayBody(t, *array, 0), p, size);
}
}
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
ReleaseIntArrayElements(Thread* t, jintArray array, jint* p, jint mode)
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
unsigned size = intArrayLength(t, *array) * sizeof(jint);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
memcpy(&intArrayBody(t, *array, 0), p, size);
}
}
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
ReleaseLongArrayElements(Thread* t, jlongArray array, jlong* p, jint mode)
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
unsigned size = longArrayLength(t, *array) * sizeof(jlong);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
memcpy(&longArrayBody(t, *array, 0), p, size);
}
}
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
ReleaseFloatArrayElements(Thread* t, jfloatArray array, jfloat* p, jint mode)
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
unsigned size = floatArrayLength(t, *array) * sizeof(jfloat);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
memcpy(&floatArrayBody(t, *array, 0), p, size);
}
}
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
ReleaseDoubleArrayElements(Thread* t, jdoubleArray array, jdouble* p,
jint mode)
{
ENTER(t, Thread::ActiveState);
2014-05-29 04:17:25 +00:00
unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble);
if (mode == 0 or mode == AVIAN_JNI_COMMIT) {
2007-09-07 23:20:21 +00:00
if (size) {
memcpy(&doubleArrayBody(t, *array, 0), p, size);
}
}
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
GetBooleanArrayRegion(Thread* t, jbooleanArray array, jint offset, jint length,
jboolean* dst)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(dst, &booleanArrayBody(t, *array, offset),
length * sizeof(jboolean));
}
2007-09-07 23:20:21 +00:00
}
void JNICALL
GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
jbyte* dst)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(dst, &byteArrayBody(t, *array, offset), length * sizeof(jbyte));
}
2007-09-07 23:20:21 +00:00
}
void JNICALL
GetCharArrayRegion(Thread* t, jcharArray array, jint offset, jint length,
jchar* dst)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(dst, &charArrayBody(t, *array, offset), length * sizeof(jchar));
}
2007-09-07 23:20:21 +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) {
memcpy(dst, &shortArrayBody(t, *array, offset), length * sizeof(jshort));
}
2007-09-07 23:20:21 +00:00
}
void JNICALL
GetIntArrayRegion(Thread* t, jintArray array, jint offset, jint length,
jint* dst)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(dst, &intArrayBody(t, *array, offset), length * sizeof(jint));
}
2007-09-07 23:20:21 +00:00
}
void JNICALL
GetLongArrayRegion(Thread* t, jlongArray array, jint offset, jint length,
jlong* dst)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(dst, &longArrayBody(t, *array, offset), length * sizeof(jlong));
}
2007-09-07 23:20:21 +00:00
}
void JNICALL
GetFloatArrayRegion(Thread* t, jfloatArray array, jint offset, jint length,
jfloat* dst)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(dst, &floatArrayBody(t, *array, offset), length * sizeof(jfloat));
}
2007-09-07 23:20:21 +00:00
}
void JNICALL
GetDoubleArrayRegion(Thread* t, jdoubleArray array, jint offset, jint length,
jdouble* dst)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(dst, &doubleArrayBody(t, *array, offset), length * sizeof(jdouble));
}
2007-09-17 22:15:42 +00:00
}
void JNICALL
SetBooleanArrayRegion(Thread* t, jbooleanArray array, jint offset, jint length,
const jboolean* src)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(&booleanArrayBody(t, *array, offset), src,
length * sizeof(jboolean));
}
2007-09-17 22:15:42 +00:00
}
void JNICALL
SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
const jbyte* src)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(&byteArrayBody(t, *array, offset), src, length * sizeof(jbyte));
}
2007-09-17 22:15:42 +00:00
}
void JNICALL
SetCharArrayRegion(Thread* t, jcharArray array, jint offset, jint length,
const jchar* src)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(&charArrayBody(t, *array, offset), src, length * sizeof(jchar));
}
2007-09-17 22:15:42 +00:00
}
void JNICALL
SetShortArrayRegion(Thread* t, jshortArray array, jint offset, jint length,
const jshort* src)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(&shortArrayBody(t, *array, offset), src, length * sizeof(jshort));
}
2007-09-17 22:15:42 +00:00
}
void JNICALL
SetIntArrayRegion(Thread* t, jintArray array, jint offset, jint length,
const jint* src)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(&intArrayBody(t, *array, offset), src, length * sizeof(jint));
}
2007-09-17 22:15:42 +00:00
}
void JNICALL
SetLongArrayRegion(Thread* t, jlongArray array, jint offset, jint length,
const jlong* src)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(&longArrayBody(t, *array, offset), src, length * sizeof(jlong));
}
2007-09-17 22:15:42 +00:00
}
void JNICALL
SetFloatArrayRegion(Thread* t, jfloatArray array, jint offset, jint length,
const jfloat* src)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(&floatArrayBody(t, *array, offset), src, length * sizeof(jfloat));
}
2007-09-17 22:15:42 +00:00
}
void JNICALL
SetDoubleArrayRegion(Thread* t, jdoubleArray array, jint offset, jint length,
const jdouble* src)
{
ENTER(t, Thread::ActiveState);
if (length) {
memcpy(&doubleArrayBody(t, *array, offset), src, length * sizeof(jdouble));
}
2007-09-07 23:20:21 +00:00
}
void* JNICALL
GetPrimitiveArrayCritical(Thread* t, jarray array, jboolean* isCopy)
{
if (t->criticalLevel == 0) {
2007-09-07 23:20:21 +00:00
enter(t, Thread::ActiveState);
}
++ 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;
}
void JNICALL
ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint)
{
if ((-- t->criticalLevel) == 0) {
enter(t, Thread::IdleState);
}
}
uint64_t
fromReflectedMethod(Thread* t, uintptr_t* arguments)
{
jobject m = reinterpret_cast<jobject>(arguments[0]);
2014-05-29 04:17:25 +00:00
return methodID(t, cast<GcMethod>(t, t->m->classpath->getVMMethod(t, *m)));
}
jmethodID JNICALL
FromReflectedMethod(Thread* t, jobject method)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(method) };
2012-12-19 23:48:20 +00:00
return static_cast<jmethodID>(run(t, fromReflectedMethod, arguments));
}
uint64_t
toReflectedMethod(Thread* t, uintptr_t* arguments)
{
jmethodID m = arguments[1];
jboolean isStatic = arguments[2];
return reinterpret_cast<uintptr_t>
(makeLocalReference
(t, t->m->classpath->makeJMethod
(t, isStatic ? getStaticMethod(t, m) : getMethod(t, m))));
}
jobject JNICALL
ToReflectedMethod(Thread* t, jclass c, jmethodID method, jboolean isStatic)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
2012-12-19 23:48:20 +00:00
static_cast<uintptr_t>(method),
static_cast<uintptr_t>(isStatic) };
return reinterpret_cast<jobject>(run(t, toReflectedMethod, arguments));
}
uint64_t
fromReflectedField(Thread* t, uintptr_t* arguments)
{
jobject f = reinterpret_cast<jobject>(arguments[0]);
return fieldID(t, t->m->classpath->getVMField(t, *f));
}
jfieldID JNICALL
FromReflectedField(Thread* t, jobject field)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(field) };
2012-12-19 23:48:20 +00:00
return static_cast<jfieldID>(run(t, fromReflectedField, arguments));
}
uint64_t
toReflectedField(Thread* t, uintptr_t* arguments)
{
jfieldID f = arguments[1];
jboolean isStatic = arguments[2];
return reinterpret_cast<uintptr_t>
(makeLocalReference
(t, t->m->classpath->makeJField
(t, isStatic ? getStaticField(t, f) : getField(t, f))));
}
jobject JNICALL
ToReflectedField(Thread* t, jclass c, jfieldID field, jboolean isStatic)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
2012-12-19 23:48:20 +00:00
static_cast<uintptr_t>(field),
static_cast<uintptr_t>(isStatic) };
return reinterpret_cast<jobject>(run(t, toReflectedField, 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
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
= reinterpret_cast<const JNINativeMethod*>(arguments[1]);
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;
if (*sig == '!') ++ sig;
2014-05-29 04:17:25 +00:00
GcMethod* method = findMethodOrNull
(t, cast<GcClass>(t, jclassVmClass(t, *c)), 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.
// fprintf(stderr, "not found: %s.%s%s\n", &byteArrayBody(t, className(t, jclassVmClass(t, *c)), 0), 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
}
jint JNICALL
RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods,
jint methodCount)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
reinterpret_cast<uintptr_t>(methods),
2012-06-01 17:46:56 +00:00
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;
}
jint JNICALL
UnregisterNatives(Thread* t, jclass c)
{
ENTER(t, Thread::ActiveState);
unregisterNatives(t, *c);
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
uint64_t
monitorOp(Thread* t, uintptr_t* arguments)
{
void (*op)(Thread*, object)
= reinterpret_cast<void (*)(Thread*, object)>(arguments[0]);
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;
}
void
acquire0(Thread* t, object o)
{
return acquire(t, o);
}
jint JNICALL
MonitorEnter(Thread* t, jobject 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
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;
}
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
release0(Thread* t, object o)
{
return release(t, o);
}
jint JNICALL
MonitorExit(Thread* t, jobject 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
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;
}
2007-09-07 23:20:21 +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
}
jboolean JNICALL
IsSameObject(Thread* t, jobject a, jobject b)
{
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
}
uint64_t
pushLocalFrame(Thread* t, uintptr_t* arguments)
{
if (t->m->processor->pushLocalFrame(t, arguments[0])) {
return 1;
} else {
throw_(t, root(t, Machine::OutOfMemoryError));
}
}
jint JNICALL
PushLocalFrame(Thread* t, jint capacity)
{
uintptr_t arguments[] = { static_cast<uintptr_t>(capacity) };
return run(t, pushLocalFrame, arguments) ? 0 : -1;
}
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]);
if(presult != NULL) {
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;
}
jobject JNICALL
PopLocalFrame(Thread* t, jobject result)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(result) };
return reinterpret_cast<jobject>(run(t, popLocalFrame, arguments));
}
2013-02-21 22:37:17 +00:00
uint64_t
newDirectByteBuffer(Thread* t, uintptr_t* arguments)
{
jlong capacity; memcpy(&capacity, arguments + 1, sizeof(jlong));
return reinterpret_cast<uintptr_t>
(makeLocalReference
(t, t->m->classpath->makeDirectByteBuffer
(t, reinterpret_cast<void*>(arguments[0]), capacity)));
}
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));
}
uint64_t
getDirectBufferAddress(Thread* t, uintptr_t* arguments)
{
return reinterpret_cast<uintptr_t>
(t->m->classpath->getDirectBufferAddress
(t, *reinterpret_cast<jobject>(arguments[0])));
}
void* JNICALL
GetDirectBufferAddress(Thread* t, jobject b)
{
2013-02-21 22:37:17 +00:00
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(b) };
return reinterpret_cast<void*>(run(t, getDirectBufferAddress, arguments));
}
uint64_t
getDirectBufferCapacity(Thread* t, uintptr_t* arguments)
{
return t->m->classpath->getDirectBufferCapacity
(t, *reinterpret_cast<jobject>(arguments[0]));
}
jlong JNICALL
GetDirectBufferCapacity(Thread* t, jobject b)
{
2013-02-21 22:37:17 +00:00
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(b) };
return run(t, getDirectBufferCapacity, arguments);
}
struct JavaVMOption {
char* optionString;
void* extraInfo;
};
struct JavaVMInitArgs {
jint version;
jint nOptions;
JavaVMOption* options;
jboolean ignoreUnrecognized;
};
int
parseSize(const char* s)
{
unsigned length = strlen(s);
RUNTIME_ARRAY(char, buffer, length + 1);
if (length == 0) {
return 0;
} else if (s[length - 1] == 'k' or s[length - 1] == 'K') {
memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1);
RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0;
return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024;
} else if (s[length - 1] == 'm' or s[length - 1] == 'M') {
memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1);
RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0;
return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024 * 1024;
} else {
return atoi(s);
}
}
void
append(char** p, const char* value, unsigned length, char tail)
{
if (length) {
memcpy(*p, value, length);
*p += length;
*((*p)++) = tail;
}
}
uint64_t
boot(Thread* t, uintptr_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
setRoot(t, Machine::NullPointerException, makeThrowable
2014-05-29 04:17:25 +00:00
(t, GcNullPointerException::Type));
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
setRoot(t, Machine::ArithmeticException,
2014-05-29 04:17:25 +00:00
makeThrowable(t, GcArithmeticException::Type));
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
setRoot(t, Machine::ArrayIndexOutOfBoundsException,
2014-05-29 04:17:25 +00:00
makeThrowable(t, GcArrayIndexOutOfBoundsException::Type));
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
setRoot(t, Machine::OutOfMemoryError,
2014-05-29 04:17:25 +00:00
makeThrowable(t, GcOutOfMemoryError::Type));
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-05-29 04:17:25 +00:00
setRoot(t, Machine::Shutdown, makeThrowable(t, GcThrowable::Type));
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);
threadPeer(t, t->javaThread) = reinterpret_cast<jlong>(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
setRoot(t, Machine::FinalizerThread, t->m->classpath->makeThread(t, t));
threadDaemon(t, root(t, Machine::FinalizerThread)) = true;
2013-02-22 21:41:24 +00:00
t->m->classpath->boot(t);
const char* port = findProperty(t, "avian.trace.port");
if (port) {
object host = makeString(t, "0.0.0.0");
PROTECT(t, host);
2014-05-29 04:17:25 +00:00
GcMethod* method = resolveMethod
(t, root(t, Machine::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;
}
2010-04-15 17:11:10 +00:00
} // namespace local
} // namespace
namespace vm {
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
= 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;
}
} // namespace vm
extern "C" AVIAN_EXPORT jint JNICALL
JNI_GetDefaultJavaVMInitArgs(void*)
{
return 0;
}
extern "C" AVIAN_EXPORT jint JNICALL
JNI_GetCreatedJavaVMs(Machine**, jsize, jsize*)
{
// todo
return -1;
}
extern "C" AVIAN_EXPORT jint JNICALL
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);
} else if (strncmp(p, BOOTCLASSPATH_PREPEND_OPTION ":",
sizeof(BOOTCLASSPATH_PREPEND_OPTION)) == 0)
{
bootClasspathPrepend = p + sizeof(BOOTCLASSPATH_PREPEND_OPTION);
} else if (strncmp(p, BOOTCLASSPATH_OPTION ":",
sizeof(BOOTCLASSPATH_OPTION)) == 0)
{
bootClasspath = p + sizeof(BOOTCLASSPATH_OPTION);
} 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;
if (strncmp(p, BOOTSTRAP_PROPERTY "=",
sizeof(BOOTSTRAP_PROPERTY)) == 0)
{
bootLibraries = p + sizeof(BOOTSTRAP_PROPERTY);
} else if (strncmp(p, JAVA_COMMAND_PROPERTY "=",
sizeof(JAVA_COMMAND_PROPERTY)) == 0
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;
} else if (strncmp(p, CRASHDIR_PROPERTY "=",
sizeof(CRASHDIR_PROPERTY)) == 0)
{
crashDumpDirectory = p + sizeof(CRASHDIR_PROPERTY);
} else if (strncmp(p, CLASSPATH_PROPERTY "=",
sizeof(CLASSPATH_PROPERTY)) == 0)
{
classpath = p + sizeof(CLASSPATH_PROPERTY);
2010-09-21 00:38:38 +00:00
} else if (strncmp(p, JAVA_HOME_PROPERTY "=",
sizeof(JAVA_HOME_PROPERTY)) == 0)
{
javaHome = p + sizeof(JAVA_HOME_PROPERTY);
} else if (strncmp(p, EMBED_PREFIX_PROPERTY "=",
sizeof(EMBED_PREFIX_PROPERTY)) == 0)
{
embedPrefix = p + sizeof(EMBED_PREFIX_PROPERTY);
}
++ propertyCount;
}
}
if (heapLimit == 0) heapLimit = 128 * 1024 * 1024;
2012-03-14 18:36:42 +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) {
local::append(&bootClasspathPointer, bootClasspathPrepend, bcppl,
bcpl + bcpal ? PATH_SEPARATOR : 0);
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;
if(bootLibraryEnd)
*bootLibraryEnd = 0;
Finder* bf = makeFinder
(s, h, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
Finder* af = makeFinder(s, h, classpath, bootLibrary);
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;
const char** properties = static_cast<const char**>
(h->allocate(sizeof(const char*) * propertyCount));
const char** propertyPointer = properties;
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";
2012-02-29 18:48:06 +00:00
*m = new (h->allocate(sizeof(Machine))) Machine
2012-03-14 18:36:42 +00:00
(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;
}