2011-07-13 14:25:21 +00:00
|
|
|
/* Copyright (c) 2008-2011 Avian Contributors
|
2008-02-19 18:06:52 +00:00
|
|
|
|
|
|
|
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. */
|
|
|
|
|
2013-02-27 20:25:50 +00:00
|
|
|
#include "avian/jnienv.h"
|
|
|
|
#include "avian/machine.h"
|
|
|
|
#include "avian/util.h"
|
|
|
|
#include "avian/processor.h"
|
|
|
|
#include "avian/constants.h"
|
2007-10-25 15:04:13 +00:00
|
|
|
|
2013-02-20 05:56:05 +00:00
|
|
|
#include <avian/util/runtime-array.h>
|
2013-02-11 00:51:59 +00:00
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
using namespace vm;
|
2007-07-20 14:36:31 +00:00
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
namespace {
|
2007-07-06 15:24:06 +00:00
|
|
|
|
2010-04-15 17:11:10 +00:00
|
|
|
namespace local {
|
|
|
|
|
2007-09-10 23:33:58 +00:00
|
|
|
jint JNICALL
|
|
|
|
AttachCurrentThread(Machine* m, Thread** t, void*)
|
|
|
|
{
|
|
|
|
*t = static_cast<Thread*>(m->localThread->get());
|
|
|
|
if (*t == 0) {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
*t = attachThread(m, false);
|
2007-09-10 23:33:58 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-11-03 21:52:14 +00:00
|
|
|
jint JNICALL
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
AttachCurrentThreadAsDaemon(Machine* m, Thread** t, void*)
|
2009-11-03 21:52:14 +00:00
|
|
|
{
|
|
|
|
*t = static_cast<Thread*>(m->localThread->get());
|
|
|
|
if (*t == 0) {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
*t = attachThread(m, true);
|
2009-11-03 21:52:14 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-09-10 23:33:58 +00:00
|
|
|
jint JNICALL
|
|
|
|
DetachCurrentThread(Machine* m)
|
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(m->localThread->get());
|
|
|
|
if (t) {
|
2012-09-07 14:47:49 +00:00
|
|
|
// 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);
|
2009-08-18 21:29:25 +00:00
|
|
|
|
2012-09-07 14:47:49 +00:00
|
|
|
ACQUIRE_RAW(t, t->m->stateLock);
|
2009-08-18 21:29:25 +00:00
|
|
|
|
2012-09-07 14:47:49 +00:00
|
|
|
enter(t, Thread::ActiveState);
|
2009-08-20 14:49:01 +00:00
|
|
|
|
2012-09-07 14:47:49 +00:00
|
|
|
threadPeer(t, t->javaThread) = 0;
|
2009-08-20 14:49:01 +00:00
|
|
|
|
2012-09-07 14:47:49 +00:00
|
|
|
enter(t, Thread::ZombieState);
|
2009-08-18 21:29:25 +00:00
|
|
|
|
2012-09-07 14:47:49 +00:00
|
|
|
t->state = Thread::JoinedState;
|
|
|
|
}
|
2009-08-18 21:29:25 +00:00
|
|
|
|
2007-09-10 23:33:58 +00:00
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
destroyJavaVM(Thread* t, uintptr_t*)
|
2009-08-19 20:27:03 +00:00
|
|
|
{
|
2013-05-13 19:17:42 +00:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-23 03:29:58 +00:00
|
|
|
{ ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
t->m->classpath->shutDown(t);
|
|
|
|
}
|
|
|
|
|
2013-05-13 19:17:42 +00:00
|
|
|
// wait again in case the Classpath::shutDown process started new
|
|
|
|
// threads:
|
2009-08-19 20:27:03 +00:00
|
|
|
{ ACQUIRE(t, t->m->stateLock);
|
|
|
|
while (t->m->liveCount - t->m->daemonCount > 1) {
|
|
|
|
t->m->stateLock->wait(t->systemThread, 0);
|
|
|
|
}
|
2013-04-15 18:37:23 +00:00
|
|
|
|
|
|
|
enter(t, Thread::ExclusiveState);
|
2009-08-19 20:27:03 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
shutDown(t);
|
2009-08-19 20:27:03 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2009-08-19 20:27:03 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
jint JNICALL
|
|
|
|
DestroyJavaVM(Machine* m)
|
|
|
|
{
|
|
|
|
Thread* t; AttachCurrentThread(m, &t, 0);
|
2009-08-19 20:27:03 +00:00
|
|
|
|
2011-02-02 00:45:43 +00:00
|
|
|
if (runRaw(t, destroyJavaVM, 0)) {
|
2010-12-27 22:55:23 +00:00
|
|
|
t->exit();
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
2009-08-19 20:27:03 +00:00
|
|
|
}
|
|
|
|
|
2007-09-10 23:33:58 +00:00
|
|
|
jint JNICALL
|
|
|
|
GetEnv(Machine* m, Thread** t, jint version)
|
|
|
|
{
|
|
|
|
*t = static_cast<Thread*>(m->localThread->get());
|
|
|
|
if (*t) {
|
2013-02-19 23:48:33 +00:00
|
|
|
if (version <= JNI_VERSION_1_6) {
|
2007-09-10 23:33:58 +00:00
|
|
|
return JNI_OK;
|
|
|
|
} else {
|
|
|
|
return JNI_EVERSION;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 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;
|
|
|
|
}
|
|
|
|
|
2008-04-01 23:24:43 +00:00
|
|
|
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);
|
2008-04-01 23:24:43 +00:00
|
|
|
|
|
|
|
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));
|
2008-04-01 23:24:43 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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)
|
|
|
|
{
|
2013-02-12 15:15:39 +00:00
|
|
|
if (t->criticalLevel == 0) {
|
2010-09-10 21:05:29 +00:00
|
|
|
enter(t, Thread::ActiveState);
|
|
|
|
}
|
|
|
|
|
2013-02-12 15:15:39 +00:00
|
|
|
++ t->criticalLevel;
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
if (isCopy) {
|
|
|
|
*isCopy = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
object data = stringData(t, *s);
|
2010-09-14 16:49:41 +00:00
|
|
|
if (objectClass(t, data) == type(t, Machine::ByteArrayType)) {
|
2010-09-10 21:05:29 +00:00
|
|
|
return GetStringChars(t, s, isCopy);
|
|
|
|
} else {
|
|
|
|
return &charArrayBody(t, data, stringOffset(t, *s));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
ReleaseStringCritical(Thread* t, jstring s, const jchar* chars)
|
|
|
|
{
|
2010-09-14 16:49:41 +00:00
|
|
|
if (objectClass(t, stringData(t, *s)) == type(t, Machine::ByteArrayType)) {
|
2010-09-10 21:05:29 +00:00
|
|
|
ReleaseStringChars(t, s, chars);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((-- t->criticalLevel) == 0) {
|
|
|
|
enter(t, Thread::IdleState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jsize JNICALL
|
2007-07-06 23:18:40 +00:00
|
|
|
GetStringUTFLength(Thread* t, jstring s)
|
2007-07-06 15:24:06 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
return stringUTFLength(t, *s);
|
2007-07-06 15:24:06 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
const char* JNICALL
|
2007-07-06 23:18:40 +00:00
|
|
|
GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
2007-07-06 15:24:06 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
int length = stringUTFLength(t, *s);
|
2007-07-06 23:18:40 +00:00
|
|
|
char* chars = static_cast<char*>
|
2010-04-20 16:03:07 +00:00
|
|
|
(t->m->heap->allocate(length + 1));
|
|
|
|
stringUTFChars(t, *s, chars, length);
|
2007-07-06 15:24:06 +00:00
|
|
|
|
|
|
|
if (isCopy) *isCopy = true;
|
|
|
|
return chars;
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
void JNICALL
|
2008-01-10 01:20:36 +00:00
|
|
|
ReleaseStringUTFChars(Thread* t, jstring s, const char* chars)
|
2007-07-06 15:24:06 +00:00
|
|
|
{
|
2008-04-01 23:24:43 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2013-02-21 22:36:01 +00:00
|
|
|
t->m->heap->free(chars, stringUTFLength(t, *s) + 1);
|
2007-07-06 15:24:06 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
jsize JNICALL
|
|
|
|
GetArrayLength(Thread* t, jarray array)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
return fieldAtOffset<uintptr_t>(*array, BytesPerWord);
|
2007-11-14 23:22:29 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
newString(Thread* t, uintptr_t* arguments)
|
2007-10-26 21:23:54 +00:00
|
|
|
{
|
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
|
|
|
|
2012-10-03 14:16:41 +00:00
|
|
|
object a = makeCharArray(t, size);
|
2007-10-26 21:23:54 +00:00
|
|
|
if (size) {
|
2007-10-27 00:04:20 +00:00
|
|
|
memcpy(&charArrayBody(t, a, 0), chars, size * sizeof(jchar));
|
2007-10-26 21:23:54 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jstring JNICALL
|
2010-12-27 22:55:23 +00:00
|
|
|
NewString(Thread* t, const jchar* chars, jsize size)
|
2007-07-07 23:47:35 +00:00
|
|
|
{
|
2009-11-18 18:01:47 +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) };
|
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
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
object array = parseUtf8(t, chars, strlen(chars));
|
2007-10-27 00:04:20 +00:00
|
|
|
|
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)));
|
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
|
|
|
}
|
|
|
|
|
2008-01-19 20:30:11 +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;
|
|
|
|
}
|
|
|
|
|
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];
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, getJClass
|
|
|
|
(t, defineClass
|
|
|
|
(t, loader ? *loader : root(t, Machine::BootLoader), buffer, length))));
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
jclass JNICALL
|
|
|
|
DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer,
|
|
|
|
jsize length)
|
|
|
|
{
|
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) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jclass>(run(t, defineClass, arguments));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
findClass(Thread* t, uintptr_t* arguments)
|
2007-07-27 00:06:05 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
const char* name = reinterpret_cast<const char*>(arguments[0]);
|
2007-07-27 00:06:05 +00:00
|
|
|
|
2009-03-04 03:05:48 +00:00
|
|
|
object n = makeByteArray(t, strlen(name) + 1);
|
2008-01-19 20:30:11 +00:00
|
|
|
replace('.', '/', name, &byteArrayBody(t, n, 0));
|
2007-07-27 00:06:05 +00:00
|
|
|
|
2010-09-25 21:54:01 +00:00
|
|
|
object caller = getCaller(t, 0);
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, getJClass
|
|
|
|
(t, resolveClass
|
|
|
|
(t, caller ? classLoader(t, methodClass(t, caller))
|
|
|
|
: root(t, Machine::AppLoader), n))));
|
|
|
|
}
|
2010-09-01 16:13:52 +00:00
|
|
|
|
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));
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
throwNew(Thread* t, uintptr_t* arguments)
|
2007-07-27 00:06:05 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
const char* message = reinterpret_cast<const char*>(arguments[1]);
|
2007-07-27 00:06:05 +00:00
|
|
|
|
|
|
|
object m = 0;
|
|
|
|
PROTECT(t, m);
|
|
|
|
|
|
|
|
if (message) {
|
|
|
|
m = makeString(t, "%s", message);
|
|
|
|
}
|
|
|
|
|
|
|
|
object trace = makeTrace(t);
|
|
|
|
PROTECT(t, trace);
|
|
|
|
|
2010-09-01 16:13:52 +00:00
|
|
|
t->exception = make(t, jclassVmClass(t, *c));
|
2007-10-22 17:22:30 +00:00
|
|
|
set(t, t->exception, ThrowableMessage, m);
|
|
|
|
set(t, t->exception, ThrowableTrace, trace);
|
2007-07-27 00:06:05 +00:00
|
|
|
|
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;
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
jint JNICALL
|
|
|
|
Throw(Thread* t, jthrowable throwable)
|
|
|
|
{
|
|
|
|
if (t->exception) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
t->exception = *throwable;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-20 16:05:30 +00:00
|
|
|
jobject JNICALL
|
|
|
|
NewLocalRef(Thread* t, jobject o)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return makeLocalReference(t, *o);
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
void JNICALL
|
2007-09-24 01:39:03 +00:00
|
|
|
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);
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
disposeLocalReference(t, r);
|
2007-08-14 13:27:10 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jboolean JNICALL
|
2007-07-27 00:06:05 +00:00
|
|
|
ExceptionCheck(Thread* t)
|
|
|
|
{
|
|
|
|
return t->exception != 0;
|
|
|
|
}
|
|
|
|
|
2011-03-02 15:29:44 +00:00
|
|
|
uint64_t
|
|
|
|
getObjectClass(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference(t, getJClass(t, objectClass(t, *o))));
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jclass JNICALL
|
|
|
|
GetObjectClass(Thread* t, jobject o)
|
|
|
|
{
|
2011-03-02 15:29:44 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o) };
|
|
|
|
|
2012-08-11 12:56:19 +00:00
|
|
|
return reinterpret_cast<jclass>(run(t, getObjectClass, arguments));
|
2011-03-02 15:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
getSuperclass(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
2012-09-28 21:03:14 +00:00
|
|
|
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>
|
|
|
|
(makeLocalReference(t, getJClass(t, super))) : 0;
|
|
|
|
}
|
2011-03-02 15:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jclass JNICALL
|
|
|
|
GetSuperclass(Thread* t, jclass c)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-02 15:29:44 +00:00
|
|
|
return reinterpret_cast<jclass>(run(t, getSuperclass, arguments));
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2011-04-10 03:07:10 +00:00
|
|
|
uint64_t
|
|
|
|
isInstanceOf(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[1]);
|
|
|
|
|
|
|
|
return instanceOf(t, jclassVmClass(t, *c), *o);
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jboolean JNICALL
|
|
|
|
IsInstanceOf(Thread* t, jobject o, jclass c)
|
|
|
|
{
|
2011-04-10 03:07:10 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
|
|
|
|
reinterpret_cast<uintptr_t>(c) };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-04-10 03:07:10 +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]);
|
|
|
|
|
|
|
|
return isAssignableFrom(t, jclassVmClass(t, *a), jclassVmClass(t, *b));
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
jboolean JNICALL
|
2010-09-10 23:45:52 +00:00
|
|
|
IsAssignableFrom(Thread* t, jclass b, jclass a)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2011-04-10 03:07:10 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(b),
|
|
|
|
reinterpret_cast<uintptr_t>(a) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-04-10 03:07:10 +00:00
|
|
|
return run(t, isAssignableFrom, arguments);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
object
|
2008-03-21 00:36:53 +00:00
|
|
|
findMethod(Thread* t, jclass c, const char* name, const char* spec)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
2007-09-13 00:21:37 +00:00
|
|
|
object n = makeByteArray(t, "%s", name);
|
2007-09-07 00:21:52 +00:00
|
|
|
PROTECT(t, n);
|
|
|
|
|
2007-09-13 00:21:37 +00:00
|
|
|
object s = makeByteArray(t, "%s", spec);
|
2010-09-01 16:13:52 +00:00
|
|
|
return vm::findMethod(t, jclassVmClass(t, *c), n, s);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2008-08-15 18:32:33 +00:00
|
|
|
jint
|
|
|
|
methodID(Thread* t, object method)
|
|
|
|
{
|
2011-04-10 20:46:53 +00:00
|
|
|
int id = methodNativeID(t, method);
|
|
|
|
|
|
|
|
loadMemoryBarrier();
|
|
|
|
|
|
|
|
if (id == 0) {
|
2008-08-15 18:32:33 +00:00
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
if (methodNativeID(t, method) == 0) {
|
2010-09-14 16:49:41 +00:00
|
|
|
setRoot(t, Machine::JNIMethodTable, vectorAppend
|
|
|
|
(t, root(t, Machine::JNIMethodTable), method));
|
2011-04-10 20:46:53 +00:00
|
|
|
|
|
|
|
storeStoreMemoryBarrier();
|
|
|
|
|
2010-11-26 19:41:31 +00:00
|
|
|
methodNativeID(t, method) = vectorSize
|
|
|
|
(t, root(t, Machine::JNIMethodTable));
|
2008-08-15 18:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return methodNativeID(t, method);
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
getMethodID(Thread* t, uintptr_t* arguments)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
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
|
|
|
|
2008-03-21 00:36:53 +00:00
|
|
|
object method = findMethod(t, c, name, spec);
|
2007-09-07 00:21:52 +00:00
|
|
|
|
2008-08-15 18:32:33 +00:00
|
|
|
assert(t, (methodFlags(t, method) & ACC_STATIC) == 0);
|
2007-09-07 00:21:52 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return methodID(t, method);
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
2007-09-07 00:21:52 +00:00
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jmethodID JNICALL
|
2010-12-27 22:55:23 +00:00
|
|
|
GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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]);
|
2007-09-07 00:21:52 +00:00
|
|
|
|
2008-03-21 00:36:53 +00:00
|
|
|
object method = findMethod(t, c, name, spec);
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2008-08-15 18:32:33 +00:00
|
|
|
assert(t, methodFlags(t, method) & ACC_STATIC);
|
|
|
|
|
|
|
|
return methodID(t, method);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object
|
2008-08-15 18:32:33 +00:00
|
|
|
getMethod(Thread* t, jmethodID m)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
assert(t, m);
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
object method = vectorBody(t, root(t, Machine::JNIMethodTable), m - 1);
|
2008-04-01 17:37:59 +00:00
|
|
|
|
2008-08-15 18:32:33 +00:00
|
|
|
assert(t, (methodFlags(t, method) & ACC_STATIC) == 0);
|
2008-04-01 17:37:59 +00:00
|
|
|
|
2008-08-15 18:32:33 +00:00
|
|
|
return method;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
newObjectV(Thread* t, uintptr_t* arguments)
|
2007-11-14 23:22:29 +00:00
|
|
|
{
|
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]);
|
2007-11-14 23:22:29 +00:00
|
|
|
|
2010-09-01 16:13:52 +00:00
|
|
|
object o = make(t, jclassVmClass(t, *c));
|
2007-11-14 23:22:29 +00:00
|
|
|
PROTECT(t, o);
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
t->m->processor->invokeList(t, getMethod(t, m), o, true, *a);
|
2007-11-14 23:22:29 +00:00
|
|
|
|
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)) };
|
2010-12-27 22:55:23 +00:00
|
|
|
|
|
|
|
return reinterpret_cast<jobject>(run(t, newObjectV, arguments));
|
2007-11-14 23:22:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jobject JNICALL
|
|
|
|
NewObject(Thread* t, jclass c, jmethodID m, ...)
|
|
|
|
{
|
|
|
|
va_list a;
|
|
|
|
va_start(a, m);
|
|
|
|
|
2007-11-29 15:04:07 +00:00
|
|
|
jobject r = NewObjectV(t, c, m, a);
|
2007-11-14 23:22:29 +00:00
|
|
|
|
|
|
|
va_end(a);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
uint64_t
|
|
|
|
newObjectA(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
jmethodID m = arguments[1];
|
|
|
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
|
|
|
|
|
|
|
|
object o = make(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));
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
callObjectMethodV(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
2012-06-15 23:41:40 +00:00
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
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
|
2012-06-15 23:41:40 +00:00
|
|
|
(t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a)));
|
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)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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 00:21:52 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jobject>(run(t, callObjectMethodV, arguments));
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jobject JNICALL
|
2007-09-07 23:20:21 +00:00
|
|
|
CallObjectMethod(Thread* t, jobject o, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
uint64_t
|
|
|
|
callObjectMethodA(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jmethodID m = arguments[1];
|
|
|
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
callIntMethodV(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
2012-06-15 23:41:40 +00:00
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
2010-12-27 22:55:23 +00:00
|
|
|
jmethodID m = arguments[1];
|
|
|
|
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
return intValue
|
|
|
|
(t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a));
|
2010-12-27 22:55:23 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jboolean JNICALL
|
2007-09-07 23:20:21 +00:00
|
|
|
CallBooleanMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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
|
|
|
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
uint64_t
|
|
|
|
callIntMethodA(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jmethodID m = arguments[1];
|
|
|
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jbyte JNICALL
|
2007-09-07 23:20:21 +00:00
|
|
|
CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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
|
|
|
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jchar JNICALL
|
2007-09-07 23:20:21 +00:00
|
|
|
CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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
|
|
|
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jshort JNICALL
|
2007-09-07 23:20:21 +00:00
|
|
|
CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, callIntMethodV, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jshort JNICALL
|
|
|
|
CallShortMethod(Thread* t, jobject o, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, callIntMethodV, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jint JNICALL
|
|
|
|
CallIntMethod(Thread* t, jobject o, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
callLongMethodV(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
2012-06-15 23:41:40 +00:00
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
2010-12-27 22:55:23 +00:00
|
|
|
jmethodID m = arguments[1];
|
|
|
|
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
return longValue
|
|
|
|
(t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a));
|
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)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, callLongMethodV, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jlong JNICALL
|
|
|
|
CallLongMethod(Thread* t, jobject o, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
uint64_t
|
|
|
|
callLongMethodA(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jmethodID m = arguments[1];
|
|
|
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
|
|
|
|
|
|
|
|
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)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return bitsToFloat(run(t, callIntMethodV, arguments));
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jfloat JNICALL
|
|
|
|
CallFloatMethod(Thread* t, jobject o, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return bitsToDouble(run(t, callLongMethodV, arguments));
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jdouble JNICALL
|
|
|
|
CallDoubleMethod(Thread* t, jobject o, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
callVoidMethodV(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
2012-06-15 23:41:40 +00:00
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
2010-12-27 22:55:23 +00:00
|
|
|
jmethodID m = arguments[1];
|
|
|
|
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a);
|
2010-12-27 22:55:23 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
void JNICALL
|
2007-09-07 23:20:21 +00:00
|
|
|
CallVoidMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
run(t, callVoidMethodV, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2007-09-07 23:20:21 +00:00
|
|
|
CallVoidMethod(Thread* t, jobject o, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
2007-09-07 23:20:21 +00:00
|
|
|
va_list a;
|
|
|
|
va_start(a, m);
|
|
|
|
|
|
|
|
CallVoidMethodV(t, o, m, a);
|
|
|
|
|
|
|
|
va_end(a);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
uint64_t
|
|
|
|
callVoidMethodA(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jmethodID m = arguments[1];
|
|
|
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
|
|
|
|
|
|
|
|
t->m->processor->invokeArray(t, getMethod(t, m), *o, a);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object
|
2008-08-15 18:32:33 +00:00
|
|
|
getStaticMethod(Thread* t, jmethodID m)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
assert(t, m);
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
object method = vectorBody(t, root(t, Machine::JNIMethodTable), m - 1);
|
2008-04-01 17:37:59 +00:00
|
|
|
|
2008-08-15 18:32:33 +00:00
|
|
|
assert(t, methodFlags(t, method) & ACC_STATIC);
|
2008-04-01 17:37:59 +00:00
|
|
|
|
2008-08-15 18:32:33 +00:00
|
|
|
return method;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
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
|
2008-08-15 18:32:33 +00:00
|
|
|
CallStaticObjectMethodV(Thread* t, jclass, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jobject>(run(t, callStaticObjectMethodV, arguments));
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jobject JNICALL
|
2007-09-07 23:20:21 +00:00
|
|
|
CallStaticObjectMethod(Thread* t, jclass c, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2007-09-07 00:21:52 +00:00
|
|
|
jboolean JNICALL
|
2008-08-15 18:32:33 +00:00
|
|
|
CallStaticBooleanMethodV(Thread* t, jclass, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, callStaticIntMethodV, arguments) != 0;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jboolean JNICALL
|
|
|
|
CallStaticBooleanMethod(Thread* t, jclass c, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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
|
2008-08-15 18:32:33 +00:00
|
|
|
CallStaticByteMethodV(Thread* t, jclass, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, callStaticIntMethodV, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jbyte JNICALL
|
|
|
|
CallStaticByteMethod(Thread* t, jclass c, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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
|
2008-08-15 18:32:33 +00:00
|
|
|
CallStaticCharMethodV(Thread* t, jclass, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, callStaticIntMethodV, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jchar JNICALL
|
|
|
|
CallStaticCharMethod(Thread* t, jclass c, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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
|
2008-08-15 18:32:33 +00:00
|
|
|
CallStaticShortMethodV(Thread* t, jclass, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, callStaticIntMethodV, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jshort JNICALL
|
|
|
|
CallStaticShortMethod(Thread* t, jclass c, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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
|
2008-08-15 18:32:33 +00:00
|
|
|
CallStaticIntMethodV(Thread* t, jclass, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, callStaticIntMethodV, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jint JNICALL
|
|
|
|
CallStaticIntMethod(Thread* t, jclass c, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
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
|
2008-08-15 18:32:33 +00:00
|
|
|
CallStaticLongMethodV(Thread* t, jclass, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, callStaticLongMethodV, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jlong JNICALL
|
|
|
|
CallStaticLongMethod(Thread* t, jclass c, jmethodID m, ...)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
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;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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
|
2008-08-15 18:32:33 +00:00
|
|
|
CallStaticFloatMethodV(Thread* t, jclass, jmethodID m, va_list a)
|
2007-09-07 00:21:52 +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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return bitsToFloat(run(t, callStaticIntMethodV, arguments));
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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
|
2008-08-15 18:32:33 +00:00
|
|
|
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
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
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
|
2008-08-15 18:32:33 +00:00
|
|
|
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
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
uint64_t
|
|
|
|
callStaticVoidMethodA(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jmethodID m = arguments[0];
|
|
|
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
|
|
|
|
|
|
|
|
t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
CallStaticVoidMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { m, reinterpret_cast<uintptr_t>(a) };
|
|
|
|
|
|
|
|
run(t, callStaticVoidMethodA, arguments);
|
|
|
|
}
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
jint
|
|
|
|
fieldID(Thread* t, object field)
|
|
|
|
{
|
2011-04-10 20:46:53 +00:00
|
|
|
int id = fieldNativeID(t, field);
|
|
|
|
|
|
|
|
loadMemoryBarrier();
|
|
|
|
|
|
|
|
if (id == 0) {
|
2011-03-16 01:34:00 +00:00
|
|
|
PROTECT(t, field);
|
|
|
|
|
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
if (fieldNativeID(t, field) == 0) {
|
|
|
|
setRoot(t, Machine::JNIFieldTable, vectorAppend
|
|
|
|
(t, root(t, Machine::JNIFieldTable), field));
|
2011-04-10 20:46:53 +00:00
|
|
|
|
|
|
|
storeStoreMemoryBarrier();
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
fieldNativeID(t, field) = vectorSize(t, root(t, Machine::JNIFieldTable));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fieldNativeID(t, field);
|
|
|
|
}
|
|
|
|
|
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]);
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
return fieldID(t, resolveField(t, jclassVmClass(t, *c), name, spec));
|
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)
|
|
|
|
{
|
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
|
|
|
|
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)
|
|
|
|
{
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, getFieldID, arguments);
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object
|
|
|
|
getField(Thread* t, jfieldID f)
|
|
|
|
{
|
|
|
|
assert(t, f);
|
|
|
|
|
|
|
|
object field = vectorBody(t, root(t, Machine::JNIFieldTable), f - 1);
|
|
|
|
|
|
|
|
assert(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))));
|
2011-03-16 01:34:00 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jobject JNICALL
|
|
|
|
GetObjectField(Thread* t, jobject o, jfieldID field)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
|
|
|
|
field };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +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)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
|
|
|
|
field };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +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)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
|
|
|
|
field };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +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)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
|
|
|
|
field };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +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)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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]);
|
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
set(t, *o, fieldOffset(t, field), (v ? *v : 0));
|
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
SetObjectField(Thread* t, jobject o, jfieldID field, jobject v)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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];
|
|
|
|
|
|
|
|
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;
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
SetBooleanField(Thread* t, jobject o, jfieldID field, jboolean v)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
|
|
|
|
field,
|
|
|
|
v };
|
|
|
|
|
|
|
|
run(t, setBooleanField, arguments);
|
|
|
|
}
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jbyte>(*o, fieldOffset(t, field)) = v;
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
SetByteField(Thread* t, jobject o, jfieldID field, jbyte v)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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
|
|
|
|
2011-03-16 01:34:00 +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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jchar>(*o, fieldOffset(t, field)) = v;
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
SetCharField(Thread* t, jobject o, jfieldID field, jchar v)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o),
|
|
|
|
field,
|
|
|
|
v };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jshort>(*o, fieldOffset(t, field)) = v;
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
SetShortField(Thread* t, jobject o, jfieldID field, jshort v)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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
|
|
|
|
2011-03-16 01:34:00 +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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jint>(*o, fieldOffset(t, field)) = v;
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
SetIntField(Thread* t, jobject o, jfieldID field, jint v)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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
|
|
|
|
2011-03-16 01:34:00 +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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jlong>(*o, fieldOffset(t, field)) = v;
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
SetLongField(Thread* t, jobject o, jfieldID field, jlong v)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[2 + (sizeof(jlong) / BytesPerWord)];
|
|
|
|
arguments[0] = reinterpret_cast<uintptr_t>(o);
|
|
|
|
arguments[1] = field;
|
|
|
|
memcpy(arguments + 2, &v, sizeof(jlong));
|
|
|
|
|
|
|
|
run(t, setLongField, arguments);
|
|
|
|
}
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jfloat>(*o, fieldOffset(t, field)) = v;
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
SetFloatField(Thread* t, jobject o, jfieldID field, jfloat v)
|
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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]);
|
2011-06-20 20:24:11 +00:00
|
|
|
jdouble v; memcpy(&v, arguments + 2, sizeof(jdouble));
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jdouble>(*o, fieldOffset(t, field)) = v;
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
SetDoubleField(Thread* t, jobject o, jfieldID field, jdouble v)
|
|
|
|
{
|
2011-06-20 20:24:11 +00:00
|
|
|
uintptr_t arguments[2 + (sizeof(jdouble) / BytesPerWord)];
|
|
|
|
arguments[0] = reinterpret_cast<uintptr_t>(o);
|
|
|
|
arguments[1] = field;
|
|
|
|
memcpy(arguments + 2, &v, sizeof(jdouble));
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
run(t, setDoubleField, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
getStaticField(Thread* t, jfieldID f)
|
|
|
|
{
|
|
|
|
assert(t, f);
|
|
|
|
|
|
|
|
object field = vectorBody(t, root(t, Machine::JNIFieldTable), f - 1);
|
|
|
|
|
|
|
|
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
|
|
|
|
|
|
|
return field;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
getStaticObjectField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field))));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jobject JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
GetStaticObjectField(Thread* t, jobject c, jfieldID field)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
|
|
|
field };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +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]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jboolean JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
GetStaticBooleanField(Thread* t, jobject c, jfieldID field)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +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]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jbyte JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
GetStaticByteField(Thread* t, jobject c, jfieldID field)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +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]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jchar JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
GetStaticCharField(Thread* t, jobject c, jfieldID field)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
|
|
|
field };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
return run(t, getStaticCharField, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
getStaticShortField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jshort JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
GetStaticShortField(Thread* t, jobject c, jfieldID field)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +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]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jint JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
GetStaticIntField(Thread* t, jobject c, jfieldID field)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +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]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jlong JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
GetStaticLongField(Thread* t, jobject c, jfieldID field)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
|
|
|
field };
|
2007-09-13 00:21:37 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
return run(t, getStaticLongField, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
getStaticFloatField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jfloat JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
GetStaticFloatField(Thread* t, jobject c, jfieldID field)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
|
|
|
field };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
return bitsToFloat(run(t, getStaticFloatField, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
getStaticDoubleField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jdouble JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
GetStaticDoubleField(Thread* t, jobject c, jfieldID field)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
|
|
|
field };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
return bitsToDouble(run(t, getStaticDoubleField, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
setStaticObjectField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object field = getStaticField(t, arguments[1]);
|
|
|
|
jobject v = reinterpret_cast<jobject>(arguments[2]);
|
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
|
|
|
|
|
|
|
set(t, classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field),
|
|
|
|
(v ? *v : 0));
|
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
SetStaticObjectField(Thread* t, jobject c, jfieldID field, jobject v)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +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]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object field = getStaticField(t, arguments[1]);
|
|
|
|
jboolean v = arguments[2];
|
|
|
|
|
|
|
|
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>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
|
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
SetStaticBooleanField(Thread* t, jobject c, jfieldID field, jboolean v)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +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]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object field = getStaticField(t, arguments[1]);
|
|
|
|
jbyte v = arguments[2];
|
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jbyte>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
|
2009-08-03 22:18:16 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
SetStaticByteField(Thread* t, jobject c, jfieldID field, jbyte v)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
|
|
|
field,
|
2012-06-01 17:46:56 +00:00
|
|
|
static_cast<uintptr_t>(v) };
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
run(t, setStaticByteField, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
setStaticCharField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object field = getStaticField(t, arguments[1]);
|
|
|
|
jchar v = arguments[2];
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jchar>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
|
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
SetStaticCharField(Thread* t, jobject c, jfieldID field, jchar v)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
|
|
|
field,
|
|
|
|
v };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
run(t, setStaticCharField, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
setStaticShortField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object field = getStaticField(t, arguments[1]);
|
|
|
|
jshort v = arguments[2];
|
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jshort>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
|
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
SetStaticShortField(Thread* t, jobject c, jfieldID field, jshort v)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
|
|
|
field,
|
2012-06-01 17:46:56 +00:00
|
|
|
static_cast<uintptr_t>(v) };
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
run(t, setStaticShortField, arguments);
|
|
|
|
}
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
uint64_t
|
|
|
|
setStaticIntField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object field = getStaticField(t, arguments[1]);
|
|
|
|
jint v = arguments[2];
|
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jint>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
|
|
|
|
|
|
|
|
return 1;
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
SetStaticIntField(Thread* t, jobject c, jfieldID field, jint v)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +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
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
run(t, setStaticIntField, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
setStaticLongField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object field = getStaticField(t, arguments[1]);
|
|
|
|
jlong v; memcpy(&v, arguments + 2, sizeof(jlong));
|
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jlong>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
|
|
|
|
|
|
|
|
return 1;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
SetStaticLongField(Thread* t, jobject c, jfieldID field, jlong v)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
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
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
run(t, setStaticLongField, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
setStaticFloatField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object field = getStaticField(t, arguments[1]);
|
|
|
|
jfloat v = bitsToFloat(arguments[2]);
|
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jfloat>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
|
|
|
|
|
|
|
|
return 1;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
SetStaticFloatField(Thread* t, jobject c, jfieldID field, jfloat v)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
2011-03-16 01:34:00 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
|
|
|
field,
|
|
|
|
floatToBits(v) };
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
run(t, setStaticFloatField, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
setStaticDoubleField(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject c = reinterpret_cast<jobject>(arguments[0]);
|
2011-05-26 23:39:19 +00:00
|
|
|
|
|
|
|
initClass(t, jclassVmClass(t, *c));
|
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
object field = getStaticField(t, arguments[1]);
|
2011-06-20 20:24:11 +00:00
|
|
|
jdouble v; memcpy(&v, arguments + 2, sizeof(jdouble));
|
2011-03-16 01:34:00 +00:00
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<jdouble>
|
2011-03-16 01:34:00 +00:00
|
|
|
(classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v;
|
|
|
|
|
|
|
|
return 1;
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
2011-03-16 01:34:00 +00:00
|
|
|
SetStaticDoubleField(Thread* t, jobject c, jfieldID field, jdouble v)
|
2007-09-07 00:21:52 +00:00
|
|
|
{
|
2011-06-20 20:24:11 +00:00
|
|
|
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
|
|
|
|
2011-03-16 01:34:00 +00:00
|
|
|
run(t, setStaticDoubleField, arguments);
|
2007-09-07 00:21:52 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jobject JNICALL
|
2012-02-29 18:51:30 +00:00
|
|
|
newGlobalRef(Thread* t, jobject o, bool weak)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2007-09-30 03:33:38 +00:00
|
|
|
if (o) {
|
2009-12-17 02:16:51 +00:00
|
|
|
for (Reference* r = t->m->jniReferences; r; r = r->next) {
|
2012-02-29 18:51:30 +00:00
|
|
|
if (r->target == *o and r->weak == weak) {
|
2009-12-17 02:16:51 +00:00
|
|
|
acquire(t, r);
|
|
|
|
|
|
|
|
return &(r->target);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-13 18:15:04 +00:00
|
|
|
Reference* r = new (t->m->heap->allocate(sizeof(Reference)))
|
2012-02-29 18:51:30 +00:00
|
|
|
Reference(*o, &(t->m->jniReferences), weak);
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2009-12-17 02:16:51 +00:00
|
|
|
acquire(t, r);
|
|
|
|
|
2007-09-30 03:33:38 +00:00
|
|
|
return &(r->target);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
|
2012-02-29 18:51:30 +00:00
|
|
|
jobject JNICALL
|
|
|
|
NewGlobalRef(Thread* t, jobject o)
|
|
|
|
{
|
|
|
|
return newGlobalRef(t, o, false);
|
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
void JNICALL
|
2007-09-30 03:33:38 +00:00
|
|
|
DeleteGlobalRef(Thread* t, jobject r)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
2007-09-07 23:20:21 +00:00
|
|
|
|
2007-09-30 03:33:38 +00:00
|
|
|
if (r) {
|
2009-12-17 02:16:51 +00:00
|
|
|
release(t, reinterpret_cast<Reference*>(r));
|
2007-09-07 23:20:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-29 18:51:30 +00:00
|
|
|
jobject JNICALL
|
|
|
|
NewWeakGlobalRef(Thread* t, jobject o)
|
|
|
|
{
|
|
|
|
return newGlobalRef(t, o, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
DeleteWeakGlobalRef(Thread* t, jobject r)
|
|
|
|
{
|
|
|
|
DeleteGlobalRef(t, r);
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
jint JNICALL
|
|
|
|
EnsureLocalCapacity(Thread*, jint)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jthrowable JNICALL
|
|
|
|
ExceptionOccurred(Thread* t)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
newObjectArray(Thread* t, uintptr_t* arguments)
|
2007-10-25 15:04:13 +00:00
|
|
|
{
|
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]);
|
2007-10-25 15:04:13 +00:00
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
object a = makeObjectArray(t, jclassVmClass(t, *class_), length);
|
2007-10-25 15:04:13 +00:00
|
|
|
object value = (init ? *init : 0);
|
|
|
|
for (jsize i = 0; i < length; ++i) {
|
|
|
|
set(t, a, ArrayBody + (i * BytesPerWord), value);
|
|
|
|
}
|
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),
|
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));
|
2007-10-25 15:04:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2009-08-19 13:36:52 +00:00
|
|
|
set(t, *array, ArrayBody + (index * BytesPerWord), (value ? *value : 0));
|
2007-10-25 15:04:13 +00:00
|
|
|
}
|
|
|
|
|
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)));
|
|
|
|
}
|
|
|
|
|
2007-09-10 23:33:58 +00:00
|
|
|
jbooleanArray JNICALL
|
|
|
|
NewBooleanArray(Thread* t, jsize length)
|
|
|
|
{
|
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) };
|
2007-09-10 23:33:58 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jbooleanArray>(run(t, newArray, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeByteArray0(Thread* t, unsigned length)
|
|
|
|
{
|
|
|
|
return makeByteArray(t, length);
|
2007-09-10 23:33:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jbyteArray JNICALL
|
|
|
|
NewByteArray(Thread* t, jsize length)
|
|
|
|
{
|
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) };
|
2007-09-10 23:33:58 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jbyteArray>(run(t, newArray, arguments));
|
2007-09-10 23:33:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jcharArray JNICALL
|
|
|
|
NewCharArray(Thread* t, jsize length)
|
|
|
|
{
|
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) };
|
2007-09-10 23:33:58 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jcharArray>(run(t, newArray, arguments));
|
2007-09-10 23:33:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jshortArray JNICALL
|
|
|
|
NewShortArray(Thread* t, jsize length)
|
|
|
|
{
|
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) };
|
2007-09-10 23:33:58 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jshortArray>(run(t, newArray, arguments));
|
2007-09-10 23:33:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jintArray JNICALL
|
|
|
|
NewIntArray(Thread* t, jsize length)
|
|
|
|
{
|
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) };
|
2007-09-10 23:33:58 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jintArray>(run(t, newArray, arguments));
|
2007-09-10 23:33:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jlongArray JNICALL
|
|
|
|
NewLongArray(Thread* t, jsize length)
|
|
|
|
{
|
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) };
|
2007-09-10 23:33:58 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jlongArray>(run(t, newArray, arguments));
|
2007-09-10 23:33:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jfloatArray JNICALL
|
|
|
|
NewFloatArray(Thread* t, jsize length)
|
|
|
|
{
|
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) };
|
2007-09-10 23:33:58 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jfloatArray>(run(t, newArray, arguments));
|
2007-09-10 23:33:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jdoubleArray JNICALL
|
|
|
|
NewDoubleArray(Thread* t, jsize length)
|
|
|
|
{
|
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) };
|
2007-09-10 23:33:58 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jdoubleArray>(run(t, newArray, arguments));
|
2007-09-10 23:33:58 +00:00
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2008-01-18 01:26:46 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean);
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
if (mode == 0 or mode == JNI_COMMIT) {
|
|
|
|
if (size) {
|
|
|
|
memcpy(&booleanArrayBody(t, *array, 0), p, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == 0 or mode == 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)
|
|
|
|
{
|
2008-01-18 01:26:46 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
unsigned size = byteArrayLength(t, *array) * sizeof(jbyte);
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
if (mode == 0 or mode == JNI_COMMIT) {
|
|
|
|
if (size) {
|
|
|
|
memcpy(&byteArrayBody(t, *array, 0), p, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == 0 or mode == 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)
|
|
|
|
{
|
2008-01-18 01:26:46 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
unsigned size = charArrayLength(t, *array) * sizeof(jchar);
|
|
|
|
|
2008-01-18 01:26:46 +00:00
|
|
|
if (mode == 0 or mode == JNI_COMMIT) {
|
2007-09-07 23:20:21 +00:00
|
|
|
if (size) {
|
|
|
|
memcpy(&charArrayBody(t, *array, 0), p, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == 0 or mode == 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)
|
|
|
|
{
|
2008-01-18 01:26:46 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
unsigned size = shortArrayLength(t, *array) * sizeof(jshort);
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
if (mode == 0 or mode == JNI_COMMIT) {
|
|
|
|
if (size) {
|
|
|
|
memcpy(&shortArrayBody(t, *array, 0), p, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == 0 or mode == 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)
|
|
|
|
{
|
2008-01-18 01:26:46 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
unsigned size = intArrayLength(t, *array) * sizeof(jint);
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
if (mode == 0 or mode == JNI_COMMIT) {
|
|
|
|
if (size) {
|
|
|
|
memcpy(&intArrayBody(t, *array, 0), p, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == 0 or mode == 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)
|
|
|
|
{
|
2008-01-18 01:26:46 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
unsigned size = longArrayLength(t, *array) * sizeof(jlong);
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
if (mode == 0 or mode == JNI_COMMIT) {
|
|
|
|
if (size) {
|
|
|
|
memcpy(&longArrayBody(t, *array, 0), p, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == 0 or mode == 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)
|
|
|
|
{
|
2008-01-18 01:26:46 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
unsigned size = floatArrayLength(t, *array) * sizeof(jfloat);
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
if (mode == 0 or mode == JNI_COMMIT) {
|
|
|
|
if (size) {
|
|
|
|
memcpy(&floatArrayBody(t, *array, 0), p, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == 0 or mode == 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)
|
|
|
|
{
|
2008-01-18 01:26:46 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble);
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
if (mode == 0 or mode == JNI_COMMIT) {
|
|
|
|
if (size) {
|
|
|
|
memcpy(&doubleArrayBody(t, *array, 0), p, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == 0 or mode == 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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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,
|
2007-11-14 23:22:29 +00:00
|
|
|
jshort* dst)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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);
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
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)
|
|
|
|
{
|
2013-02-12 15:15:39 +00:00
|
|
|
if (t->criticalLevel == 0) {
|
2007-09-07 23:20:21 +00:00
|
|
|
enter(t, Thread::ActiveState);
|
|
|
|
}
|
2013-02-12 15:15:39 +00:00
|
|
|
|
|
|
|
++ t->criticalLevel;
|
2007-09-07 23:20:21 +00:00
|
|
|
|
|
|
|
if (isCopy) {
|
|
|
|
*isCopy = true;
|
|
|
|
}
|
|
|
|
|
2012-08-11 12:56:19 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-19 19:39:33 +00:00
|
|
|
uint64_t
|
|
|
|
fromReflectedMethod(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject m = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
|
|
|
|
return methodID(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));
|
2012-12-19 19:39:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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),
|
2012-12-19 19:39:33 +00:00
|
|
|
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));
|
2012-12-19 19:39:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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),
|
2012-12-19 19:39:33 +00:00
|
|
|
static_cast<uintptr_t>(isStatic) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jobject>(run(t, toReflectedField, arguments));
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
registerNatives(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
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];
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < methodCount; ++i) {
|
|
|
|
if (methods[i].function) {
|
2013-02-26 23:24:02 +00:00
|
|
|
// 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;
|
|
|
|
|
2010-11-04 17:02:09 +00:00
|
|
|
object method = findMethodOrNull
|
2013-02-26 23:24:02 +00:00
|
|
|
(t, jclassVmClass(t, *c), methods[i].name, sig);
|
2010-11-04 17:02:09 +00:00
|
|
|
|
|
|
|
if (method == 0 or (methodFlags(t, method) & 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.
|
2013-02-26 23:24:02 +00:00
|
|
|
|
|
|
|
// fprintf(stderr, "not found: %s.%s%s\n", &byteArrayBody(t, className(t, jclassVmClass(t, *c)), 0), methods[i].name, sig);
|
|
|
|
// abort(t);
|
2010-11-04 17:02:09 +00:00
|
|
|
} else {
|
|
|
|
registerNative(t, method, methods[i].function);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
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) };
|
2010-12-27 22:55:23 +00:00
|
|
|
|
|
|
|
return run(t, registerNatives, arguments) ? 0 : -1;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jint JNICALL
|
|
|
|
UnregisterNatives(Thread* t, jclass c)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
unregisterNatives(t, *c);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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]);
|
|
|
|
|
|
|
|
op(t, *o);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
acquire0(Thread* t, object o)
|
|
|
|
{
|
|
|
|
return acquire(t, o);
|
|
|
|
}
|
|
|
|
|
2007-11-14 23:22:29 +00:00
|
|
|
jint JNICALL
|
|
|
|
MonitorEnter(Thread* t, jobject o)
|
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[]
|
|
|
|
= { reinterpret_cast<uintptr_t>(voidPointer(acquire0)),
|
|
|
|
reinterpret_cast<uintptr_t>(o) };
|
2007-11-14 23:22:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, monitorOp, arguments) ? 0 : -1;
|
|
|
|
}
|
2007-11-14 23:22:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
void
|
|
|
|
release0(Thread* t, object o)
|
|
|
|
{
|
2011-02-01 21:23:53 +00:00
|
|
|
return release(t, o);
|
2007-11-14 23:22:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jint JNICALL
|
|
|
|
MonitorExit(Thread* t, jobject o)
|
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[]
|
|
|
|
= { reinterpret_cast<uintptr_t>(voidPointer(release0)),
|
|
|
|
reinterpret_cast<uintptr_t>(o) };
|
2007-11-14 23:22:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return run(t, monitorOp, arguments) ? 0 : -1;
|
2007-11-14 23:22:29 +00:00
|
|
|
}
|
|
|
|
|
2007-09-07 23:20:21 +00:00
|
|
|
jint JNICALL
|
2007-09-10 23:33:58 +00:00
|
|
|
GetJavaVM(Thread* t, Machine** m)
|
2007-09-07 23:20:21 +00:00
|
|
|
{
|
2007-09-24 01:39:03 +00:00
|
|
|
*m = t->m;
|
2007-09-10 23:33:58 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-08-11 12:56:19 +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-08-11 12:56:19 +00:00
|
|
|
|
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;
|
2012-08-11 12:56:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)));
|
|
|
|
}
|
|
|
|
|
2012-08-11 12:56:19 +00:00
|
|
|
jobject JNICALL
|
|
|
|
NewDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
|
|
|
{
|
2013-02-21 22:37:17 +00:00
|
|
|
uintptr_t arguments[1 + (sizeof(jlong) / BytesPerWord)];
|
|
|
|
arguments[0] = reinterpret_cast<uintptr_t>(p);
|
|
|
|
memcpy(arguments + 1, &capacity, sizeof(jlong));
|
|
|
|
|
|
|
|
return reinterpret_cast<jobject>(run(t, newDirectByteBuffer, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
getDirectBufferAddress(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(t->m->classpath->getDirectBufferAddress
|
|
|
|
(t, *reinterpret_cast<jobject>(arguments[0])));
|
2012-08-11 12:56:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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]));
|
2012-08-11 12:56:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2012-08-11 12:56:19 +00:00
|
|
|
}
|
|
|
|
|
2008-07-14 17:02:43 +00:00
|
|
|
struct JavaVMOption {
|
|
|
|
char* optionString;
|
|
|
|
void* extraInfo;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct JavaVMInitArgs {
|
2007-10-25 15:04:13 +00:00
|
|
|
jint version;
|
|
|
|
|
2008-07-14 17:02:43 +00:00
|
|
|
jint nOptions;
|
|
|
|
JavaVMOption* options;
|
|
|
|
jboolean ignoreUnrecognized;
|
2007-10-25 15:04:13 +00:00
|
|
|
};
|
|
|
|
|
2008-07-14 17:02:43 +00:00
|
|
|
int
|
|
|
|
parseSize(const char* s)
|
|
|
|
{
|
|
|
|
unsigned length = strlen(s);
|
2009-08-27 00:26:44 +00:00
|
|
|
RUNTIME_ARRAY(char, buffer, length + 1);
|
2008-07-14 17:02:43 +00:00
|
|
|
if (length == 0) {
|
|
|
|
return 0;
|
2012-11-12 21:35:58 +00:00
|
|
|
} else if (s[length - 1] == 'k' or s[length - 1] == 'K') {
|
2009-08-27 00:26:44 +00:00
|
|
|
memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1);
|
2010-09-17 01:43:27 +00:00
|
|
|
RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0;
|
2009-08-27 00:26:44 +00:00
|
|
|
return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024;
|
2012-11-12 21:35:58 +00:00
|
|
|
} else if (s[length - 1] == 'm' or s[length - 1] == 'M') {
|
2009-08-27 00:26:44 +00:00
|
|
|
memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1);
|
2010-09-17 01:43:27 +00:00
|
|
|
RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0;
|
2009-08-27 00:26:44 +00:00
|
|
|
return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024 * 1024;
|
2008-07-14 17:02:43 +00:00
|
|
|
} else {
|
|
|
|
return atoi(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-14 17:51:20 +00:00
|
|
|
void
|
|
|
|
append(char** p, const char* value, unsigned length, char tail)
|
|
|
|
{
|
|
|
|
if (length) {
|
|
|
|
memcpy(*p, value, length);
|
|
|
|
*p += length;
|
|
|
|
*((*p)++) = tail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-21 23:00:20 +00:00
|
|
|
uint64_t
|
|
|
|
boot(Thread* t, uintptr_t*)
|
2010-11-26 19:41:31 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
setRoot(t, Machine::NullPointerException, makeThrowable
|
|
|
|
(t, Machine::NullPointerExceptionType));
|
2010-11-26 19:41:31 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
setRoot(t, Machine::ArithmeticException,
|
|
|
|
makeThrowable(t, Machine::ArithmeticExceptionType));
|
2010-12-20 00:47:21 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
setRoot(t, Machine::ArrayIndexOutOfBoundsException,
|
|
|
|
makeThrowable(t, Machine::ArrayIndexOutOfBoundsExceptionType));
|
|
|
|
|
|
|
|
setRoot(t, Machine::OutOfMemoryError,
|
|
|
|
makeThrowable(t, Machine::OutOfMemoryErrorType));
|
|
|
|
|
support multiple sequential VM instances with bootimage build
Until now, the bootimage build hasn't supported using the Java
invocation API to create a VM, destroy it, and create another in the
same process. Ideally, we would be able to create multiple VMs
simultaneously without any interference between them. In fact, Avian
is designed to support this for the most part, but there are a few
places we use global, mutable state which prevent this from working.
Most notably, the bootimage is modified in-place at runtime, so the
best we can do without extensive changes is to clean up the bootimage
when the VM is destroyed so it's ready for later instances. Hence
this commit.
Ultimately, we can move towards a fully reentrant VM by making the
bootimage immutable, but this will require some care to avoid
performance regressions. Another challenge is our Posix signal
handlers, which currently rely on a global handle to the VM, since you
can't, to my knowledge, pass a context pointer when registering a
signal handler. Thread local variables won't necessarily help, since
a thread might attatch to more than one VM at a time.
2011-11-10 20:10:53 +00:00
|
|
|
setRoot(t, Machine::Shutdown, makeThrowable(t, Machine::ThrowableType));
|
|
|
|
|
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);
|
|
|
|
|
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;
|
2010-11-26 19:41:31 +00:00
|
|
|
|
2013-02-22 21:41:24 +00:00
|
|
|
t->m->classpath->boot(t);
|
|
|
|
|
2013-03-08 21:47:27 +00:00
|
|
|
const char* port = findProperty(t, "avian.trace.port");
|
|
|
|
if (port) {
|
|
|
|
object host = makeString(t, "0.0.0.0");
|
|
|
|
PROTECT(t, host);
|
|
|
|
|
|
|
|
object 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));
|
|
|
|
}
|
|
|
|
|
2010-11-26 19:41:31 +00:00
|
|
|
enter(t, Thread::IdleState);
|
2011-02-21 23:00:20 +00:00
|
|
|
|
|
|
|
return 1;
|
2010-11-26 19:41:31 +00:00
|
|
|
}
|
|
|
|
|
2010-04-15 17:11:10 +00:00
|
|
|
} // namespace local
|
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
|
|
|
void
|
2007-09-10 23:33:58 +00:00
|
|
|
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;
|
2007-09-10 23:33:58 +00:00
|
|
|
|
|
|
|
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;
|
2010-09-10 21:05:29 +00:00
|
|
|
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;
|
2010-09-10 21:05:29 +00:00
|
|
|
envTable->GetStringUTFRegion = local::GetStringUTFRegion;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->GetArrayLength = local::GetArrayLength;
|
|
|
|
envTable->NewString = local::NewString;
|
|
|
|
envTable->NewStringUTF = local::NewStringUTF;
|
2010-09-10 21:05:29 +00:00
|
|
|
envTable->DefineClass = local::DefineClass;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->FindClass = local::FindClass;
|
|
|
|
envTable->ThrowNew = local::ThrowNew;
|
2010-09-10 21:05:29 +00:00
|
|
|
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;
|
2011-03-02 15:29:44 +00:00
|
|
|
envTable->GetSuperclass = local::GetSuperclass;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->IsInstanceOf = local::IsInstanceOf;
|
2010-09-10 21:05:29 +00:00
|
|
|
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;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->NewObjectA = local::NewObjectA;
|
|
|
|
envTable->NewObject = local::NewObject;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallObjectMethodV = local::CallObjectMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallObjectMethodA = local::CallObjectMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallObjectMethod = local::CallObjectMethod;
|
|
|
|
envTable->CallBooleanMethodV = local::CallBooleanMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallBooleanMethodA = local::CallBooleanMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallBooleanMethod = local::CallBooleanMethod;
|
|
|
|
envTable->CallByteMethodV = local::CallByteMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallByteMethodA = local::CallByteMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallByteMethod = local::CallByteMethod;
|
|
|
|
envTable->CallCharMethodV = local::CallCharMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallCharMethodA = local::CallCharMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallCharMethod = local::CallCharMethod;
|
|
|
|
envTable->CallShortMethodV = local::CallShortMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallShortMethodA = local::CallShortMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallShortMethod = local::CallShortMethod;
|
|
|
|
envTable->CallIntMethodV = local::CallIntMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallIntMethodA = local::CallIntMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallIntMethod = local::CallIntMethod;
|
|
|
|
envTable->CallLongMethodV = local::CallLongMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallLongMethodA = local::CallLongMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallLongMethod = local::CallLongMethod;
|
|
|
|
envTable->CallFloatMethodV = local::CallFloatMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallFloatMethodA = local::CallFloatMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallFloatMethod = local::CallFloatMethod;
|
|
|
|
envTable->CallDoubleMethodV = local::CallDoubleMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallDoubleMethodA = local::CallDoubleMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallDoubleMethod = local::CallDoubleMethod;
|
|
|
|
envTable->CallVoidMethodV = local::CallVoidMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallVoidMethodA = local::CallVoidMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallVoidMethod = local::CallVoidMethod;
|
|
|
|
envTable->CallStaticObjectMethodV = local::CallStaticObjectMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallStaticObjectMethodA = local::CallStaticObjectMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallStaticObjectMethod = local::CallStaticObjectMethod;
|
|
|
|
envTable->CallStaticBooleanMethodV = local::CallStaticBooleanMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallStaticBooleanMethodA = local::CallStaticBooleanMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallStaticBooleanMethod = local::CallStaticBooleanMethod;
|
|
|
|
envTable->CallStaticByteMethodV = local::CallStaticByteMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallStaticByteMethodA = local::CallStaticByteMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallStaticByteMethod = local::CallStaticByteMethod;
|
|
|
|
envTable->CallStaticCharMethodV = local::CallStaticCharMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallStaticCharMethodA = local::CallStaticCharMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallStaticCharMethod = local::CallStaticCharMethod;
|
|
|
|
envTable->CallStaticShortMethodV = local::CallStaticShortMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallStaticShortMethodA = local::CallStaticShortMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallStaticShortMethod = local::CallStaticShortMethod;
|
|
|
|
envTable->CallStaticIntMethodV = local::CallStaticIntMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallStaticIntMethodA = local::CallStaticIntMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallStaticIntMethod = local::CallStaticIntMethod;
|
|
|
|
envTable->CallStaticLongMethodV = local::CallStaticLongMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallStaticLongMethodA = local::CallStaticLongMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallStaticLongMethod = local::CallStaticLongMethod;
|
|
|
|
envTable->CallStaticFloatMethodV = local::CallStaticFloatMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallStaticFloatMethodA = local::CallStaticFloatMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallStaticFloatMethod = local::CallStaticFloatMethod;
|
|
|
|
envTable->CallStaticDoubleMethodV = local::CallStaticDoubleMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
envTable->CallStaticDoubleMethodA = local::CallStaticDoubleMethodA;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->CallStaticDoubleMethod = local::CallStaticDoubleMethod;
|
|
|
|
envTable->CallStaticVoidMethodV = local::CallStaticVoidMethodV;
|
2012-06-15 23:41:40 +00:00
|
|
|
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;
|
2012-02-29 18:51:30 +00:00
|
|
|
envTable->NewWeakGlobalRef = local::NewWeakGlobalRef;
|
2010-04-15 17:11:10 +00:00
|
|
|
envTable->DeleteGlobalRef = local::DeleteGlobalRef;
|
2012-02-29 18:51:30 +00:00
|
|
|
envTable->DeleteWeakGlobalRef = local::DeleteWeakGlobalRef;
|
2010-09-10 21:05:29 +00:00
|
|
|
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;
|
2010-09-10 21:05:29 +00:00
|
|
|
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;
|
2012-08-11 12:56:19 +00:00
|
|
|
envTable->PushLocalFrame = local::PushLocalFrame;
|
|
|
|
envTable->PopLocalFrame = local::PopLocalFrame;
|
2012-12-19 19:39:33 +00:00
|
|
|
envTable->FromReflectedMethod = local::FromReflectedMethod;
|
|
|
|
envTable->ToReflectedMethod = local::ToReflectedMethod;
|
|
|
|
envTable->FromReflectedField = local::FromReflectedField;
|
|
|
|
envTable->ToReflectedField = local::ToReflectedField;
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
2007-07-20 14:36:31 +00:00
|
|
|
|
2007-07-06 15:24:06 +00:00
|
|
|
} // namespace vm
|
2007-10-25 15:04:13 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2008-07-14 17:02:43 +00:00
|
|
|
JNI_GetDefaultJavaVMInitArgs(void*)
|
2007-10-25 15:04:13 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-08 01:05:05 +00:00
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
|
|
|
JNI_GetCreatedJavaVMs(Machine**, jsize, jsize*)
|
|
|
|
{
|
|
|
|
// todo
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:04:13 +00:00
|
|
|
extern "C" JNIEXPORT 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);
|
2007-10-25 15:04:13 +00:00
|
|
|
|
2008-07-14 17:02:43 +00:00
|
|
|
unsigned heapLimit = 0;
|
2012-03-14 18:36:42 +00:00
|
|
|
unsigned stackLimit = 0;
|
2013-02-02 10:27:36 +00:00
|
|
|
const char* bootLibraries = 0;
|
2008-07-14 17:02:43 +00:00
|
|
|
const char* classpath = 0;
|
2010-09-21 00:38:38 +00:00
|
|
|
const char* javaHome = AVIAN_JAVA_HOME;
|
2010-11-05 19:18:28 +00:00
|
|
|
const char* embedPrefix = AVIAN_EMBED_PREFIX;
|
2008-07-14 17:51:20 +00:00
|
|
|
const char* bootClasspathPrepend = "";
|
2010-10-24 17:49:12 +00:00
|
|
|
const char* bootClasspath = 0;
|
2008-07-14 17:51:20 +00:00
|
|
|
const char* bootClasspathAppend = "";
|
2008-11-11 15:20:49 +00:00
|
|
|
const char* crashDumpDirectory = 0;
|
|
|
|
|
|
|
|
unsigned propertyCount = 0;
|
2008-07-14 17:02:43 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < a->nOptions; ++i) {
|
2008-07-14 17:51:20 +00:00
|
|
|
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);
|
2008-07-14 17:51:20 +00:00
|
|
|
} 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);
|
|
|
|
}
|
2008-07-14 17:02:43 +00:00
|
|
|
} else if (strncmp(a->options[i].optionString, "-D", 2) == 0) {
|
|
|
|
const char* p = a->options[i].optionString + 2;
|
2008-11-11 15:20:49 +00:00
|
|
|
if (strncmp(p, BOOTSTRAP_PROPERTY "=",
|
|
|
|
sizeof(BOOTSTRAP_PROPERTY)) == 0)
|
2008-03-31 03:43:43 +00:00
|
|
|
{
|
2013-02-02 10:27:36 +00:00
|
|
|
bootLibraries = p + sizeof(BOOTSTRAP_PROPERTY);
|
2013-04-20 01:28:20 +00:00
|
|
|
} 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;
|
2008-11-11 15:20:49 +00:00
|
|
|
} else if (strncmp(p, CRASHDIR_PROPERTY "=",
|
|
|
|
sizeof(CRASHDIR_PROPERTY)) == 0)
|
|
|
|
{
|
|
|
|
crashDumpDirectory = p + sizeof(CRASHDIR_PROPERTY);
|
2008-07-14 17:02:43 +00:00
|
|
|
} 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);
|
2010-11-05 19:18:28 +00:00
|
|
|
} else if (strncmp(p, EMBED_PREFIX_PROPERTY "=",
|
|
|
|
sizeof(EMBED_PREFIX_PROPERTY)) == 0)
|
|
|
|
{
|
|
|
|
embedPrefix = p + sizeof(EMBED_PREFIX_PROPERTY);
|
2007-10-25 18:33:43 +00:00
|
|
|
}
|
2008-07-14 17:02:43 +00:00
|
|
|
|
2008-11-11 15:20:49 +00:00
|
|
|
++ propertyCount;
|
2007-10-25 18:33:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-14 17:02:43 +00:00
|
|
|
if (heapLimit == 0) heapLimit = 128 * 1024 * 1024;
|
2012-03-14 18:36:42 +00:00
|
|
|
|
|
|
|
if (stackLimit == 0) stackLimit = 128 * 1024;
|
2008-07-14 17:02:43 +00:00
|
|
|
|
|
|
|
if (classpath == 0) classpath = ".";
|
|
|
|
|
2010-09-20 23:31:23 +00:00
|
|
|
System* s = makeSystem(crashDumpDirectory);
|
|
|
|
Heap* h = makeHeap(s, heapLimit);
|
2010-11-05 19:18:28 +00:00
|
|
|
Classpath* c = makeClasspath(s, h, javaHome, embedPrefix);
|
2010-10-24 17:49:12 +00:00
|
|
|
|
|
|
|
if (bootClasspath == 0) {
|
|
|
|
bootClasspath = c->bootClasspath();
|
|
|
|
}
|
2010-09-20 23:31:23 +00:00
|
|
|
|
2008-07-14 17:51:20 +00:00
|
|
|
unsigned bcppl = strlen(bootClasspathPrepend);
|
|
|
|
unsigned bcpl = strlen(bootClasspath);
|
|
|
|
unsigned bcpal = strlen(bootClasspathAppend);
|
2008-07-14 17:02:43 +00:00
|
|
|
|
2010-10-24 17:49:12 +00:00
|
|
|
unsigned bootClasspathBufferSize = bcppl + bcpl + bcpal + 3;
|
2010-09-14 16:49:41 +00:00
|
|
|
RUNTIME_ARRAY(char, bootClasspathBuffer, bootClasspathBufferSize);
|
|
|
|
char* bootClasspathPointer = RUNTIME_ARRAY_BODY(bootClasspathBuffer);
|
2011-09-01 03:16:22 +00:00
|
|
|
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;
|
|
|
|
}
|
2008-07-14 17:02:43 +00:00
|
|
|
|
2013-02-02 10:27:36 +00:00
|
|
|
char* bootLibrary = bootLibraries ? strdup(bootLibraries) : 0;
|
|
|
|
char* bootLibraryEnd = bootLibrary ? strchr(bootLibrary, PATH_SEPARATOR) : 0;
|
|
|
|
if(bootLibraryEnd)
|
|
|
|
*bootLibraryEnd = 0;
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
Finder* bf = makeFinder
|
2010-11-05 19:18:28 +00:00
|
|
|
(s, h, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
|
|
|
|
Finder* af = makeFinder(s, h, classpath, bootLibrary);
|
2013-02-02 10:27:36 +00:00
|
|
|
if(bootLibrary)
|
|
|
|
free(bootLibrary);
|
2009-11-28 04:15:12 +00:00
|
|
|
Processor* p = makeProcessor(s, h, true);
|
2008-03-31 03:43:43 +00:00
|
|
|
|
2008-11-11 15:20:49 +00:00
|
|
|
const char** properties = static_cast<const char**>
|
|
|
|
(h->allocate(sizeof(const char*) * propertyCount));
|
2011-08-06 00:06:29 +00:00
|
|
|
|
2008-11-11 15:20:49 +00:00
|
|
|
const char** propertyPointer = properties;
|
2011-08-06 00:06:29 +00:00
|
|
|
|
|
|
|
const char** arguments = static_cast<const char**>
|
|
|
|
(h->allocate(sizeof(const char*) * a->nOptions));
|
|
|
|
|
|
|
|
const char** argumentPointer = arguments;
|
|
|
|
|
2008-11-11 15:20:49 +00:00
|
|
|
for (int i = 0; i < a->nOptions; ++i) {
|
|
|
|
if (strncmp(a->options[i].optionString, "-D", 2) == 0) {
|
|
|
|
*(propertyPointer++) = a->options[i].optionString + 2;
|
|
|
|
}
|
2011-08-06 00:06:29 +00:00
|
|
|
*(argumentPointer++) = a->options[i].optionString;
|
2008-11-11 15:20:49 +00:00
|
|
|
}
|
|
|
|
|
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);
|
2008-03-31 03:43:43 +00:00
|
|
|
|
2007-10-25 15:04:13 +00:00
|
|
|
*t = p->makeThread(*m, 0, 0);
|
|
|
|
|
2011-02-21 23:00:20 +00:00
|
|
|
enter(*t, Thread::ActiveState);
|
|
|
|
enter(*t, Thread::IdleState);
|
2010-11-26 19:41:31 +00:00
|
|
|
|
2011-02-21 23:00:20 +00:00
|
|
|
return run(*t, local::boot, 0) ? 0 : -1;
|
2007-10-25 15:04:13 +00:00
|
|
|
}
|