2010-09-10 21:05:29 +00:00
|
|
|
/* Copyright (c) 2010, Avian Contributors
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
|
|
for any purpose with or without fee is hereby granted, provided
|
|
|
|
that the above copyright notice and this permission notice appear
|
|
|
|
in all copies.
|
|
|
|
|
|
|
|
There is NO WARRANTY for this software. See license.txt for
|
|
|
|
details. */
|
|
|
|
|
|
|
|
#include "machine.h"
|
|
|
|
#include "classpath-common.h"
|
2010-09-10 23:47:23 +00:00
|
|
|
#include "util.h"
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
|
|
|
|
# include <windows.h>
|
|
|
|
# include <io.h>
|
|
|
|
# include <direct.h>
|
|
|
|
# include <share.h>
|
2010-11-07 04:21:19 +00:00
|
|
|
# include <errno.h>
|
|
|
|
# include <fcntl.h>
|
|
|
|
# include <sys/stat.h>
|
|
|
|
# include <sys/types.h>
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
# undef interface
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
# define CLOSE _close
|
|
|
|
# define READ _read
|
|
|
|
# define WRITE _write
|
2010-11-07 04:21:19 +00:00
|
|
|
# define FSTAT _fstat
|
|
|
|
# define STAT _stat
|
|
|
|
# define LSEEK _lseek
|
|
|
|
|
|
|
|
# define S_ISSOCK(x) false
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
# ifdef _MSC_VER
|
|
|
|
# define S_ISREG(x) ((x) | _S_IFREG)
|
|
|
|
# define S_ISDIR(x) ((x) | _S_IFDIR)
|
|
|
|
# define S_IRUSR _S_IREAD
|
|
|
|
# define S_IWUSR _S_IWRITE
|
|
|
|
# else
|
2010-11-07 04:21:19 +00:00
|
|
|
# define OPEN _open
|
|
|
|
# define CREAT _creat
|
2010-09-10 21:05:29 +00:00
|
|
|
# endif
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
# define O_RDONLY _O_RDONLY
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
# ifdef AVIAN_OPENJDK_SRC
|
|
|
|
# define EXPORT(x) x
|
|
|
|
# else
|
|
|
|
# define EXPORT(x) _##x
|
|
|
|
# endif
|
2010-11-07 04:21:19 +00:00
|
|
|
|
|
|
|
typedef int socklen_t;
|
|
|
|
|
2010-12-02 03:05:22 +00:00
|
|
|
# define RTLD_DEFAULT 0
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
#else // not PLATFORM_WINDOWS
|
|
|
|
|
|
|
|
# include <unistd.h>
|
|
|
|
# include <sys/types.h>
|
|
|
|
# include <sys/stat.h>
|
2010-09-14 16:49:41 +00:00
|
|
|
# include <sys/socket.h>
|
2010-09-23 14:49:36 +00:00
|
|
|
# include <sys/ioctl.h>
|
2010-09-10 21:05:29 +00:00
|
|
|
# include <fcntl.h>
|
|
|
|
# include <errno.h>
|
2010-09-17 22:10:01 +00:00
|
|
|
# include <sched.h>
|
2010-11-27 18:25:02 +00:00
|
|
|
# include <dlfcn.h>
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
# define OPEN open
|
|
|
|
# define CLOSE close
|
|
|
|
# define READ read
|
|
|
|
# define WRITE write
|
2010-11-07 17:08:04 +00:00
|
|
|
# define STAT stat
|
2010-09-23 14:49:36 +00:00
|
|
|
# define FSTAT fstat
|
2010-09-10 21:05:29 +00:00
|
|
|
# define LSEEK lseek
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
# define EXPORT(x) x
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
#endif // not PLATFORM_WINDOWS
|
|
|
|
|
|
|
|
using namespace vm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
inline int
|
|
|
|
OPEN(string_t path, int mask, int mode)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
if (_wsopen_s(&fd, path, mask, _SH_DENYNO, mode) == 0) {
|
|
|
|
return fd;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int
|
|
|
|
CREAT(string_t path, int mode)
|
|
|
|
{
|
|
|
|
return OPEN(path, _O_CREAT, mode);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace local {
|
|
|
|
|
|
|
|
const unsigned InterfaceVersion = 4;
|
2010-09-14 16:49:41 +00:00
|
|
|
const unsigned PageSize = 4 * 1024;
|
2010-11-05 19:18:28 +00:00
|
|
|
const int VirtualFileBase = 1000000000;
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
Machine* globalMachine;
|
|
|
|
|
|
|
|
const char*
|
|
|
|
primitiveName(Thread* t, object c)
|
|
|
|
{
|
|
|
|
if (c == primitiveClass(t, 'V')) {
|
|
|
|
return "void";
|
|
|
|
} else if (c == primitiveClass(t, 'Z')) {
|
|
|
|
return "boolean";
|
|
|
|
} else if (c == primitiveClass(t, 'B')) {
|
|
|
|
return "byte";
|
|
|
|
} else if (c == primitiveClass(t, 'C')) {
|
|
|
|
return "char";
|
|
|
|
} else if (c == primitiveClass(t, 'S')) {
|
|
|
|
return "short";
|
|
|
|
} else if (c == primitiveClass(t, 'I')) {
|
|
|
|
return "int";
|
|
|
|
} else if (c == primitiveClass(t, 'F')) {
|
|
|
|
return "float";
|
|
|
|
} else if (c == primitiveClass(t, 'J')) {
|
|
|
|
return "long";
|
|
|
|
} else if (c == primitiveClass(t, 'D')) {
|
|
|
|
return "double";
|
|
|
|
} else {
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
getClassName(Thread* t, object c)
|
|
|
|
{
|
|
|
|
if (className(t, c) == 0) {
|
|
|
|
if (classVmFlags(t, c) & PrimitiveFlag) {
|
|
|
|
PROTECT(t, c);
|
|
|
|
|
|
|
|
object name = makeByteArray(t, primitiveName(t, c));
|
|
|
|
|
|
|
|
set(t, c, ClassName, name);
|
|
|
|
} else {
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return className(t, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeClassNameString(Thread* t, object name)
|
|
|
|
{
|
|
|
|
RUNTIME_ARRAY(char, s, byteArrayLength(t, name));
|
|
|
|
replace('/', '.', RUNTIME_ARRAY_BODY(s),
|
|
|
|
reinterpret_cast<char*>(&byteArrayBody(t, name, 0)));
|
|
|
|
|
|
|
|
return makeString(t, "%s", s);
|
|
|
|
}
|
|
|
|
|
2010-11-04 17:02:09 +00:00
|
|
|
void
|
2010-11-07 17:08:04 +00:00
|
|
|
interceptFileOperations(Thread*);
|
2010-11-04 17:02:09 +00:00
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
class MyClasspath : public Classpath {
|
|
|
|
public:
|
2010-09-21 00:38:38 +00:00
|
|
|
static const unsigned BufferSize = 1024;
|
2010-09-20 23:31:23 +00:00
|
|
|
|
2010-11-05 19:18:28 +00:00
|
|
|
MyClasspath(System* s, Allocator* allocator, const char* javaHome,
|
|
|
|
const char* embedPrefix):
|
2010-12-09 04:38:16 +00:00
|
|
|
allocator(allocator), ranNetOnLoad(0)
|
2010-09-20 23:31:23 +00:00
|
|
|
{
|
|
|
|
class StringBuilder {
|
|
|
|
public:
|
|
|
|
StringBuilder(System* s, char* pointer, unsigned remaining):
|
|
|
|
s(s), pointer(pointer), remaining(remaining)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
void append(const char* append) {
|
|
|
|
unsigned length = strlen(append);
|
2010-09-21 00:38:38 +00:00
|
|
|
expect(s, remaining > length);
|
2010-09-20 23:31:23 +00:00
|
|
|
|
|
|
|
strncpy(pointer, append, remaining);
|
|
|
|
|
|
|
|
remaining -= length;
|
|
|
|
pointer += length;
|
|
|
|
}
|
|
|
|
|
|
|
|
void append(char c) {
|
|
|
|
assert(s, remaining > 1);
|
|
|
|
|
|
|
|
pointer[0] = c;
|
|
|
|
pointer[1] = 0;
|
|
|
|
|
|
|
|
-- remaining;
|
|
|
|
++ pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
System* s;
|
|
|
|
char* pointer;
|
|
|
|
unsigned remaining;
|
|
|
|
} sb(s, buffer, BufferSize);
|
|
|
|
|
|
|
|
this->javaHome = sb.pointer;
|
|
|
|
sb.append(javaHome);
|
|
|
|
sb.append('\0');
|
|
|
|
|
|
|
|
this->classpath = sb.pointer;
|
2010-11-26 19:41:31 +00:00
|
|
|
sb.append(AVIAN_CLASSPATH);
|
2010-10-24 17:49:12 +00:00
|
|
|
sb.append(s->pathSeparator());
|
2010-09-20 23:31:23 +00:00
|
|
|
sb.append(javaHome);
|
2010-09-21 00:38:38 +00:00
|
|
|
sb.append("/lib/rt.jar");
|
2010-09-20 23:31:23 +00:00
|
|
|
sb.append(s->pathSeparator());
|
|
|
|
sb.append(javaHome);
|
2010-09-21 00:38:38 +00:00
|
|
|
sb.append("/lib/jsse.jar");
|
2010-09-20 23:31:23 +00:00
|
|
|
sb.append(s->pathSeparator());
|
|
|
|
sb.append(javaHome);
|
2010-09-21 00:38:38 +00:00
|
|
|
sb.append("/lib/jce.jar");
|
2010-09-20 23:31:23 +00:00
|
|
|
sb.append(s->pathSeparator());
|
|
|
|
sb.append(javaHome);
|
2010-09-21 00:38:38 +00:00
|
|
|
sb.append("/lib/resources.jar");
|
2010-09-20 23:31:23 +00:00
|
|
|
sb.append('\0');
|
|
|
|
|
|
|
|
this->libraryPath = sb.pointer;
|
|
|
|
sb.append(javaHome);
|
2010-11-07 17:08:04 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
sb.append("/bin");
|
|
|
|
#elif defined ARCH_x86_64
|
2010-09-21 00:38:38 +00:00
|
|
|
sb.append("/lib/amd64");
|
2010-09-20 23:31:23 +00:00
|
|
|
#else
|
2010-10-24 02:40:48 +00:00
|
|
|
// todo: handle other architectures
|
|
|
|
sb.append("/lib/i386");
|
2010-09-20 23:31:23 +00:00
|
|
|
#endif
|
2010-11-04 17:02:09 +00:00
|
|
|
sb.append('\0');
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
this->tzMappings = sb.pointer;
|
|
|
|
sb.append(javaHome);
|
|
|
|
sb.append("/lib/tzmappings");
|
|
|
|
this->tzMappingsLength = sb.pointer - tzMappings;
|
|
|
|
sb.append('\0');
|
2010-11-05 19:18:28 +00:00
|
|
|
|
|
|
|
this->embedPrefix = sb.pointer;
|
|
|
|
sb.append(embedPrefix);
|
|
|
|
this->embedPrefixLength = sb.pointer - this->embedPrefix;
|
2010-09-20 23:31:23 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
virtual object
|
|
|
|
makeJclass(Thread* t, object class_)
|
|
|
|
{
|
2010-09-14 16:49:41 +00:00
|
|
|
PROTECT(t, class_);
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
object name = makeClassNameString(t, getClassName(t, class_));
|
|
|
|
|
|
|
|
return vm::makeJclass
|
|
|
|
(t, 0, 0, name, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, class_);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
|
|
|
makeString(Thread* t, object array, int32_t offset, int32_t length)
|
|
|
|
{
|
2010-09-14 16:49:41 +00:00
|
|
|
if (objectClass(t, array) == type(t, Machine::ByteArrayType)) {
|
2010-09-10 21:05:29 +00:00
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
object charArray = makeCharArray(t, length);
|
|
|
|
for (int i = 0; i < length; ++i) {
|
|
|
|
charArrayBody(t, charArray, i) = byteArrayBody(t, array, offset + i);
|
|
|
|
}
|
|
|
|
|
|
|
|
array = charArray;
|
|
|
|
}
|
|
|
|
return vm::makeString(t, array, offset, length, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
|
|
|
makeThread(Thread* t, Thread* parent)
|
|
|
|
{
|
|
|
|
const unsigned MaxPriority = 10;
|
|
|
|
const unsigned NormalPriority = 5;
|
|
|
|
|
|
|
|
object group;
|
|
|
|
if (parent) {
|
|
|
|
group = threadGroup(t, parent->javaThread);
|
|
|
|
} else {
|
2010-11-05 21:34:28 +00:00
|
|
|
group = allocate(t, FixedSizeOfThreadGroup, true);
|
|
|
|
setObjectClass(t, group, type(t, Machine::ThreadGroupType));
|
|
|
|
threadGroupMaxPriority(t, group) = MaxPriority;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
2010-11-27 23:27:30 +00:00
|
|
|
|
|
|
|
PROTECT(t, group);
|
2010-11-05 21:34:28 +00:00
|
|
|
|
|
|
|
object thread = allocate(t, FixedSizeOfThread, true);
|
|
|
|
setObjectClass(t, thread, type(t, Machine::ThreadType));
|
|
|
|
threadPriority(t, thread) = NormalPriority;
|
|
|
|
threadGroup(t, thread) = group;
|
|
|
|
threadContextClassLoader(t, thread) = root(t, Machine::BootLoader);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-27 23:27:30 +00:00
|
|
|
PROTECT(t, thread);
|
|
|
|
|
|
|
|
const unsigned BufferSize = 256;
|
|
|
|
char buffer[BufferSize];
|
|
|
|
unsigned length = vm::snprintf(buffer, BufferSize, "Thread-%p", thread);
|
|
|
|
object name = makeCharArray(t, length);
|
|
|
|
for (unsigned i = 0; i < length; ++i) {
|
|
|
|
charArrayBody(t, name, i) = buffer[i];
|
|
|
|
}
|
|
|
|
set(t, thread, ThreadName, name);
|
|
|
|
|
2010-11-05 21:34:28 +00:00
|
|
|
return thread;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
runThread(Thread* t)
|
|
|
|
{
|
|
|
|
object method = resolveMethod
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V");
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
t->m->processor->invoke(t, method, t->javaThread);
|
|
|
|
}
|
2010-09-14 16:49:41 +00:00
|
|
|
|
|
|
|
acquire(t, t->javaThread);
|
|
|
|
t->flags &= ~Thread::ActiveFlag;
|
|
|
|
notifyAll(t, t->javaThread);
|
|
|
|
release(t, t->javaThread);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
boot(Thread* t)
|
|
|
|
{
|
|
|
|
globalMachine = t->m;
|
|
|
|
|
2010-12-06 00:40:50 +00:00
|
|
|
resolveSystemClass(t, root(t, Machine::BootLoader),
|
|
|
|
className(t, type(t, Machine::ClassLoaderType)));
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
|
2010-11-04 17:02:09 +00:00
|
|
|
#ifdef AVIAN_OPENJDK_SRC
|
2010-11-07 17:08:04 +00:00
|
|
|
interceptFileOperations(t);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2010-11-04 17:02:09 +00:00
|
|
|
#else // not AVIAN_OPENJDK_SRC
|
2010-11-07 17:08:04 +00:00
|
|
|
if (loadLibrary(t, libraryPath, "verify", true, true) == 0
|
|
|
|
or loadLibrary(t, libraryPath, "java", true, true) == 0)
|
|
|
|
{
|
2010-09-10 21:05:29 +00:00
|
|
|
abort(t);
|
|
|
|
}
|
2010-11-04 17:02:09 +00:00
|
|
|
#endif // not AVIAN_OPENJDK_SRC
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
object constructor = resolveMethod
|
|
|
|
(t, type(t, Machine::ClassLoaderType), "<init>",
|
|
|
|
"(Ljava/lang/ClassLoader;)V");
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
PROTECT(t, constructor);
|
|
|
|
|
|
|
|
t->m->processor->invoke(t, constructor, root(t, Machine::BootLoader), 0);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, constructor, root(t, Machine::AppLoader),
|
|
|
|
root(t, Machine::BootLoader));
|
2010-09-15 00:52:57 +00:00
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
|
|
|
|
object scl = resolveField
|
|
|
|
(t, type(t, Machine::ClassLoaderType), "scl", "Ljava/lang/ClassLoader;");
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
PROTECT(t, scl);
|
|
|
|
|
|
|
|
object sclSet = resolveField
|
|
|
|
(t, type(t, Machine::ClassLoaderType), "sclSet", "Z");
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
|
|
|
|
set(t, classStaticTable(t, type(t, Machine::ClassLoaderType)),
|
|
|
|
fieldOffset(t, scl), root(t, Machine::AppLoader));
|
|
|
|
|
|
|
|
cast<uint8_t>(classStaticTable(t, type(t, Machine::ClassLoaderType)),
|
|
|
|
fieldOffset(t, sclSet)) = true;
|
2010-11-04 17:43:50 +00:00
|
|
|
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, root(t, Machine::BootLoader), "java/lang/System",
|
|
|
|
"initializeSystemClass", "()V", 0);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2010-09-20 23:31:23 +00:00
|
|
|
virtual const char*
|
|
|
|
bootClasspath()
|
|
|
|
{
|
|
|
|
return classpath;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
virtual void
|
|
|
|
dispose()
|
2010-11-05 19:18:28 +00:00
|
|
|
{
|
2010-09-10 21:05:29 +00:00
|
|
|
allocator->free(this, sizeof(*this));
|
|
|
|
}
|
|
|
|
|
|
|
|
Allocator* allocator;
|
2010-09-20 23:31:23 +00:00
|
|
|
const char* javaHome;
|
|
|
|
const char* classpath;
|
|
|
|
const char* libraryPath;
|
2010-11-07 19:24:40 +00:00
|
|
|
const char* tzMappings;
|
2010-11-05 19:18:28 +00:00
|
|
|
const char* embedPrefix;
|
2010-11-07 19:24:40 +00:00
|
|
|
unsigned tzMappingsLength;
|
2010-11-05 19:18:28 +00:00
|
|
|
unsigned embedPrefixLength;
|
2010-11-07 17:08:04 +00:00
|
|
|
unsigned filePathField;
|
|
|
|
unsigned fileDescriptorFdField;
|
|
|
|
unsigned fileInputStreamFdField;
|
2010-12-09 04:38:16 +00:00
|
|
|
bool ranNetOnLoad;
|
2010-09-20 23:31:23 +00:00
|
|
|
char buffer[BufferSize];
|
2010-09-10 21:05:29 +00:00
|
|
|
};
|
|
|
|
|
2010-11-05 19:18:28 +00:00
|
|
|
struct JVM_ExceptionTableEntryType {
|
|
|
|
jint start_pc;
|
|
|
|
jint end_pc;
|
|
|
|
jint handler_pc;
|
|
|
|
jint catchType;
|
2010-09-10 21:05:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct jvm_version_info {
|
2010-11-05 19:18:28 +00:00
|
|
|
unsigned jvm_version;
|
|
|
|
unsigned update_version: 8;
|
|
|
|
unsigned special_update_version: 8;
|
|
|
|
unsigned reserved1: 16;
|
|
|
|
unsigned reserved2;
|
|
|
|
unsigned is_attach_supported: 1;
|
|
|
|
unsigned is_kernel_jvm: 1;
|
|
|
|
unsigned: 30;
|
|
|
|
unsigned: 32;
|
|
|
|
unsigned: 32;
|
2010-09-10 21:05:29 +00:00
|
|
|
};
|
|
|
|
|
2010-11-05 19:18:28 +00:00
|
|
|
Finder*
|
|
|
|
getFinder(Thread* t, const char* name, unsigned nameLength)
|
2010-11-04 17:02:09 +00:00
|
|
|
{
|
2010-11-05 19:18:28 +00:00
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
for (object p = root(t, Machine::VirtualFileFinders);
|
|
|
|
p; p = finderNext(t, p))
|
|
|
|
{
|
|
|
|
if (byteArrayLength(t, finderName(t, p)) == nameLength
|
|
|
|
and strncmp(reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, finderName(t, p), 0)),
|
|
|
|
name, nameLength))
|
|
|
|
{
|
|
|
|
return static_cast<Finder*>(finderFinder(t, p));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object n = makeByteArray(t, nameLength + 1);
|
|
|
|
memcpy(&byteArrayBody(t, n, 0), name, nameLength);
|
|
|
|
|
|
|
|
void* p = t->m->libraries->resolve
|
|
|
|
(reinterpret_cast<const char*>(&byteArrayBody(t, n, 0)));
|
|
|
|
if (p) {
|
|
|
|
uint8_t* (*function)(unsigned*);
|
|
|
|
memcpy(&function, &p, BytesPerWord);
|
|
|
|
|
|
|
|
unsigned size;
|
|
|
|
uint8_t* data = function(&size);
|
|
|
|
if (data) {
|
|
|
|
Finder* f = makeFinder(t->m->system, t->m->heap, data, size);
|
|
|
|
object finder = makeFinder
|
|
|
|
(t, f, n, root(t, Machine::VirtualFileFinders));
|
|
|
|
|
|
|
|
setRoot(t, Machine::VirtualFileFinders, finder);
|
|
|
|
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-11-07 04:21:19 +00:00
|
|
|
bool
|
|
|
|
pathEqual(const char* a, const char* b, unsigned length)
|
|
|
|
{
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
return strncasecmp(a, b, length) == 0;
|
|
|
|
#else
|
|
|
|
return strncmp(a, b, length) == 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
pathEqual(const char* a, const char* b)
|
|
|
|
{
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
return strcasecmp(a, b) == 0;
|
|
|
|
#else
|
|
|
|
return strcmp(a, b) == 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-11-05 19:18:28 +00:00
|
|
|
class EmbeddedFile {
|
|
|
|
public:
|
|
|
|
EmbeddedFile(MyClasspath* cp, const char* path, unsigned pathLength) {
|
2010-11-07 04:21:19 +00:00
|
|
|
if (pathEqual(cp->embedPrefix, path, cp->embedPrefixLength)) {
|
2010-11-05 19:18:28 +00:00
|
|
|
const char* p = path + cp->embedPrefixLength;
|
|
|
|
while (*p == '/') ++ p;
|
|
|
|
|
|
|
|
this->jar = p;
|
|
|
|
|
|
|
|
if (*p == 0) {
|
|
|
|
this->jarLength = 0;
|
|
|
|
this->path = 0;
|
|
|
|
this->pathLength = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (*p and *p != '/') ++p;
|
|
|
|
|
|
|
|
this->jarLength = p - this->jar;
|
|
|
|
|
|
|
|
while (*p == '/') ++p;
|
|
|
|
|
|
|
|
this->path = p;
|
|
|
|
this->pathLength = pathLength - (p - path);
|
|
|
|
} else {
|
|
|
|
this->jar = 0;
|
|
|
|
this->jarLength =0;
|
|
|
|
this->path = 0;
|
|
|
|
this->pathLength = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* jar;
|
|
|
|
const char* path;
|
|
|
|
unsigned jarLength;
|
|
|
|
unsigned pathLength;
|
|
|
|
};
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
getFileAttributes
|
|
|
|
(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
const unsigned Exists = 1;
|
|
|
|
const unsigned Regular = 2;
|
|
|
|
const unsigned Directory = 4;
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
object file = reinterpret_cast<object>(arguments[1]);
|
2010-11-07 17:08:04 +00:00
|
|
|
object path = cast<object>(file, cp->filePathField);
|
2010-11-05 19:18:28 +00:00
|
|
|
|
|
|
|
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
|
|
|
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
2010-11-07 04:21:19 +00:00
|
|
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p));
|
2010-11-05 19:18:28 +00:00
|
|
|
|
2010-12-09 04:38:16 +00:00
|
|
|
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
|
|
|
if (ef.jar) {
|
|
|
|
if (ef.jarLength == 0) {
|
|
|
|
return Exists | Directory;
|
|
|
|
}
|
|
|
|
|
|
|
|
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
|
|
|
if (finder) {
|
|
|
|
if (ef.pathLength == 0) {
|
2010-11-05 19:18:28 +00:00
|
|
|
return Exists | Directory;
|
|
|
|
}
|
|
|
|
|
2010-12-09 04:38:16 +00:00
|
|
|
unsigned length;
|
|
|
|
System::FileType type = finder->stat(ef.path, &length, true);
|
|
|
|
switch (type) {
|
|
|
|
case System::TypeUnknown: return Exists;
|
|
|
|
case System::TypeDoesNotExist: return 0;
|
|
|
|
case System::TypeFile: return Exists | Regular;
|
|
|
|
case System::TypeDirectory: return Exists | Directory;
|
|
|
|
default: abort(t);
|
2010-11-05 19:18:28 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-12-09 04:38:16 +00:00
|
|
|
return 0;
|
2010-11-05 19:18:28 +00:00
|
|
|
}
|
2010-12-09 04:38:16 +00:00
|
|
|
} else {
|
|
|
|
object r = t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
reinterpret_cast<object>(arguments[0]), file);
|
|
|
|
|
|
|
|
return (r ? intValue(t, r) : 0);
|
2010-11-05 19:18:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-01 20:40:43 +00:00
|
|
|
int64_t JNICALL
|
|
|
|
checkFileAccess
|
|
|
|
(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
const unsigned Read = 4;
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
object file = reinterpret_cast<object>(arguments[1]);
|
|
|
|
unsigned mask = arguments[2];
|
|
|
|
object path = cast<object>(file, cp->filePathField);
|
|
|
|
|
|
|
|
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
|
|
|
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
|
|
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p));
|
|
|
|
|
2010-12-09 04:38:16 +00:00
|
|
|
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
|
|
|
if (ef.jar) {
|
|
|
|
if (ef.jarLength == 0) {
|
|
|
|
return mask == Read;
|
|
|
|
}
|
|
|
|
|
|
|
|
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
|
|
|
if (finder) {
|
|
|
|
if (ef.pathLength == 0) {
|
2010-12-01 20:40:43 +00:00
|
|
|
return mask == Read;
|
|
|
|
}
|
|
|
|
|
2010-12-09 04:38:16 +00:00
|
|
|
unsigned length;
|
|
|
|
System::FileType type = finder->stat(ef.path, &length, true);
|
|
|
|
switch (type) {
|
|
|
|
case System::TypeDoesNotExist: return false;
|
|
|
|
case System::TypeUnknown:
|
|
|
|
case System::TypeFile:
|
|
|
|
case System::TypeDirectory: return mask == Read;
|
|
|
|
default: abort(t);
|
2010-12-01 20:40:43 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-12-09 04:38:16 +00:00
|
|
|
return 0;
|
2010-12-01 20:40:43 +00:00
|
|
|
}
|
2010-12-09 04:38:16 +00:00
|
|
|
} else {
|
|
|
|
object r = t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
reinterpret_cast<object>(arguments[0]), file, mask);
|
|
|
|
|
|
|
|
return (r ? booleanValue(t, r) : false);
|
2010-12-01 20:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-05 19:18:28 +00:00
|
|
|
int64_t JNICALL
|
2010-12-06 00:40:50 +00:00
|
|
|
getFileLength
|
2010-11-05 19:18:28 +00:00
|
|
|
(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
object file = reinterpret_cast<object>(arguments[1]);
|
2010-11-07 17:08:04 +00:00
|
|
|
object path = cast<object>(file, cp->filePathField);
|
2010-11-05 19:18:28 +00:00
|
|
|
|
|
|
|
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
|
|
|
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
2010-11-07 04:21:19 +00:00
|
|
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p));
|
2010-11-05 19:18:28 +00:00
|
|
|
|
|
|
|
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
|
|
|
if (ef.jar) {
|
|
|
|
if (ef.jarLength == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
|
|
|
if (finder) {
|
|
|
|
if (ef.pathLength == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned fileLength;
|
|
|
|
finder->stat(ef.path, &fileLength);
|
|
|
|
return fileLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
object r = t->m->processor->invoke
|
2010-11-26 19:41:31 +00:00
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
2010-11-05 19:18:28 +00:00
|
|
|
reinterpret_cast<object>(arguments[0]), file);
|
|
|
|
|
|
|
|
return (r ? longValue(t, r) : 0);
|
|
|
|
}
|
2010-11-04 17:02:09 +00:00
|
|
|
}
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
void JNICALL
|
|
|
|
openFile(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
|
|
|
object path = reinterpret_cast<object>(arguments[1]);
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
|
|
|
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
|
|
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p));
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
2010-11-07 17:08:04 +00:00
|
|
|
if (ef.jar) {
|
|
|
|
if (ef.jarLength == 0 or ef.pathLength == 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->exception = makeThrowable(t, Machine::FileNotFoundExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
2010-11-07 17:08:04 +00:00
|
|
|
if (finder == 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->exception = makeThrowable(t, Machine::FileNotFoundExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
System::Region* r = finder->find(ef.path);
|
|
|
|
if (r == 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->exception = makeThrowable(t, Machine::FileNotFoundExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PROTECT(t, this_);
|
|
|
|
|
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
int index = -1;
|
|
|
|
unsigned oldLength = root(t, Machine::VirtualFiles)
|
|
|
|
? arrayLength(t, root(t, Machine::VirtualFiles)) : 0;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < oldLength; ++i) {
|
|
|
|
if (arrayBody(t, root(t, Machine::VirtualFiles), i) == 0) {
|
|
|
|
index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == -1) {
|
|
|
|
object newArray = growArray(t, root(t, Machine::VirtualFiles));
|
|
|
|
setRoot(t, Machine::VirtualFiles, newArray);
|
|
|
|
index = oldLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
object region = makeRegion(t, r, 0);
|
|
|
|
set(t, root(t, Machine::VirtualFiles), ArrayBody + (index * BytesPerWord),
|
|
|
|
region);
|
|
|
|
|
|
|
|
cast<int32_t>
|
|
|
|
(cast<object>
|
|
|
|
(this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField)
|
2010-11-07 19:24:40 +00:00
|
|
|
= index + VirtualFileBase;
|
2010-11-07 17:08:04 +00:00
|
|
|
} else {
|
|
|
|
t->m->processor->invoke
|
2010-11-26 19:41:31 +00:00
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_, path);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
readByteFromFile(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
int fd = cast<int32_t>
|
|
|
|
(cast<object>
|
|
|
|
(this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField);
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
if (fd >= VirtualFileBase) {
|
2010-11-07 17:08:04 +00:00
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
object region = arrayBody
|
|
|
|
(t, root(t, Machine::VirtualFiles), fd - VirtualFileBase);
|
|
|
|
|
|
|
|
if (region) {
|
|
|
|
System::Region* r = static_cast<System::Region*>
|
|
|
|
(regionRegion(t, region));
|
|
|
|
|
|
|
|
if (r->length() > regionPosition(t, region)) {
|
|
|
|
return r->start()[regionPosition(t, region)++];
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
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->exception = makeThrowable(t, Machine::IoExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
object r = t->m->processor->invoke
|
2010-11-26 19:41:31 +00:00
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
|
|
|
return r ? intValue(t, r) : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
readBytesFromFile(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
|
|
|
object dst = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int32_t offset = arguments[2];
|
|
|
|
int32_t length = arguments[3];
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
int fd = cast<int32_t>
|
|
|
|
(cast<object>
|
|
|
|
(this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField);
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
if (fd >= VirtualFileBase) {
|
2010-11-07 17:08:04 +00:00
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
object region = arrayBody
|
|
|
|
(t, root(t, Machine::VirtualFiles), fd - VirtualFileBase);
|
|
|
|
|
|
|
|
if (region) {
|
|
|
|
System::Region* r = static_cast<System::Region*>
|
|
|
|
(regionRegion(t, region));
|
|
|
|
|
|
|
|
int available = r->length() - regionPosition(t, region);
|
|
|
|
if (available == 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length > available) {
|
|
|
|
length = available;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&byteArrayBody(t, dst, offset),
|
|
|
|
r->start() + regionPosition(t, region),
|
|
|
|
length);
|
|
|
|
|
|
|
|
regionPosition(t, region) += length;
|
|
|
|
|
|
|
|
return length;
|
|
|
|
} else {
|
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->exception = makeThrowable(t, Machine::IoExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
object r = t->m->processor->invoke
|
2010-11-26 19:41:31 +00:00
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_, dst, offset, length);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
|
|
|
return r ? intValue(t, r) : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
skipBytesInFile(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
|
|
|
int64_t count; memcpy(&count, arguments + 1, 8);
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
int fd = cast<int32_t>
|
|
|
|
(cast<object>
|
|
|
|
(this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField);
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
if (fd >= VirtualFileBase) {
|
2010-11-07 17:08:04 +00:00
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
object region = arrayBody
|
|
|
|
(t, root(t, Machine::VirtualFiles), fd - VirtualFileBase);
|
|
|
|
|
|
|
|
if (region) {
|
|
|
|
System::Region* r = static_cast<System::Region*>
|
|
|
|
(regionRegion(t, region));
|
|
|
|
|
|
|
|
int available = r->length() - regionPosition(t, region);
|
|
|
|
if (count > available) {
|
|
|
|
count = available;
|
|
|
|
}
|
|
|
|
|
|
|
|
regionPosition(t, region) += count;
|
|
|
|
|
|
|
|
return count;
|
|
|
|
} else {
|
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->exception = makeThrowable(t, Machine::IoExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
object r = t->m->processor->invoke
|
2010-11-26 19:41:31 +00:00
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_, count);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
|
|
|
return r ? longValue(t, r) : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
availableBytesInFile(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
int fd = cast<int32_t>
|
|
|
|
(cast<object>
|
|
|
|
(this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField);
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
if (fd >= VirtualFileBase) {
|
2010-11-07 17:08:04 +00:00
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
object region = arrayBody
|
|
|
|
(t, root(t, Machine::VirtualFiles), fd - VirtualFileBase);
|
|
|
|
|
|
|
|
if (region) {
|
|
|
|
return static_cast<System::Region*>(regionRegion(t, region))->length()
|
|
|
|
- regionPosition(t, region);
|
|
|
|
} else {
|
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->exception = makeThrowable(t, Machine::IoExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
object r = t->m->processor->invoke
|
2010-11-26 19:41:31 +00:00
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
|
|
|
return r ? intValue(t, r) : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
closeFile(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
int fd = cast<int32_t>
|
|
|
|
(cast<object>
|
|
|
|
(this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField);
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
if (fd >= VirtualFileBase) {
|
2010-11-07 17:08:04 +00:00
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
int index = fd - VirtualFileBase;
|
|
|
|
object region = arrayBody(t, root(t, Machine::VirtualFiles), index);
|
|
|
|
|
|
|
|
if (region) {
|
|
|
|
static_cast<System::Region*>(regionRegion(t, region))->dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
set(t, root(t, Machine::VirtualFiles), ArrayBody + (index * BytesPerWord),
|
|
|
|
0);
|
|
|
|
} else {
|
|
|
|
t->m->processor->invoke
|
2010-11-26 19:41:31 +00:00
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-06 00:40:50 +00:00
|
|
|
int64_t JNICALL
|
|
|
|
getBootstrapResource(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object name = reinterpret_cast<object>(arguments[0]);
|
|
|
|
PROTECT(t, name);
|
|
|
|
|
|
|
|
object m = findMethodOrNull
|
|
|
|
(t, type(t, Machine::SystemClassLoaderType),
|
|
|
|
"findResource", "(Ljava/lang/String;)Ljava/net/URL;");
|
|
|
|
|
|
|
|
if (m) {
|
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(t->m->processor->invoke(t, m, root(t, Machine::BootLoader), name));
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
getBootstrapResources(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object name = reinterpret_cast<object>(arguments[0]);
|
|
|
|
PROTECT(t, name);
|
|
|
|
|
|
|
|
object m = findMethodOrNull
|
|
|
|
(t, type(t, Machine::SystemClassLoaderType),
|
|
|
|
"findResources", "(Ljava/lang/String;)Ljava/util/Enumeration;");
|
|
|
|
|
|
|
|
if (m) {
|
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(t->m->processor->invoke(t, m, root(t, Machine::BootLoader), name));
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-09 04:38:16 +00:00
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
|
|
|
net_JNI_OnLoad(JavaVM*, void*);
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
loadLibrary(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object name = reinterpret_cast<object>(arguments[1]);
|
|
|
|
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
|
|
|
|
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
|
|
|
|
|
|
|
bool absolute = arguments[2];
|
|
|
|
|
|
|
|
#ifdef AVIAN_OPENJDK_SRC
|
|
|
|
if (not absolute) {
|
|
|
|
if (strcmp(n, "net") == 0) {
|
|
|
|
bool ran;
|
|
|
|
|
|
|
|
{ ACQUIRE(t, t->m->classLock);
|
|
|
|
|
|
|
|
local::MyClasspath* c = static_cast<local::MyClasspath*>
|
|
|
|
(t->m->classpath);
|
|
|
|
|
|
|
|
ran = c->ranNetOnLoad;
|
|
|
|
c->ranNetOnLoad = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not ran) {
|
|
|
|
net_JNI_OnLoad(t->m, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
} else if (strcmp(n, "zip") == 0
|
|
|
|
or strcmp(n, "nio") == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // AVIAN_OPENJDK_SRC
|
|
|
|
|
|
|
|
loadLibrary
|
|
|
|
(t, static_cast<local::MyClasspath*>(t->m->classpath)->libraryPath,
|
|
|
|
RUNTIME_ARRAY_BODY(n), not absolute, false);
|
|
|
|
}
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
// only safe to call during bootstrap when there's only one thread
|
|
|
|
// running:
|
|
|
|
void
|
|
|
|
intercept(Thread* t, object c, const char* name, const char* spec,
|
|
|
|
void* function)
|
|
|
|
{
|
2010-12-06 00:40:50 +00:00
|
|
|
object m = findMethodOrNull(t, c, name, spec);
|
2010-11-07 17:08:04 +00:00
|
|
|
if (m) {
|
|
|
|
PROTECT(t, m);
|
|
|
|
|
|
|
|
object clone = methodClone(t, m);
|
|
|
|
|
|
|
|
// make clone private to prevent vtable updates at compilation
|
|
|
|
// time. Otherwise, our interception might be bypassed by calls
|
|
|
|
// through the vtable.
|
|
|
|
methodFlags(t, clone) |= ACC_PRIVATE;
|
|
|
|
|
|
|
|
methodFlags(t, m) |= ACC_NATIVE;
|
|
|
|
|
|
|
|
object native = makeNativeIntercept(t, function, true, clone);
|
|
|
|
|
2010-11-26 19:41:31 +00:00
|
|
|
PROTECT(t, native);
|
|
|
|
|
|
|
|
object runtimeData = getMethodRuntimeData(t, m);
|
|
|
|
|
|
|
|
set(t, runtimeData, MethodRuntimeDataNative, native);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
interceptFileOperations(Thread* t)
|
|
|
|
{
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
{ object fileClass = resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader), "java/io/File");
|
|
|
|
if (fileClass == 0) return;
|
|
|
|
|
|
|
|
object filePathField = findFieldInClass2
|
|
|
|
(t, fileClass, "path", "Ljava/lang/String;");
|
|
|
|
if (filePathField == 0) return;
|
|
|
|
|
|
|
|
cp->filePathField = fieldOffset(t, filePathField);
|
|
|
|
}
|
|
|
|
|
|
|
|
{ object fileDescriptorClass = resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader), "java/io/FileDescriptor");
|
|
|
|
if (fileDescriptorClass == 0) return;
|
|
|
|
|
|
|
|
object fileDescriptorFdField = findFieldInClass2
|
|
|
|
(t, fileDescriptorClass, "fd", "I");
|
|
|
|
if (fileDescriptorFdField == 0) return;
|
|
|
|
|
|
|
|
cp->fileDescriptorFdField = fieldOffset(t, fileDescriptorFdField);
|
|
|
|
}
|
|
|
|
|
|
|
|
{ object fileInputStreamClass = resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader), "java/io/FileInputStream");
|
|
|
|
if (fileInputStreamClass == 0) return;
|
|
|
|
|
2010-12-10 05:17:57 +00:00
|
|
|
PROTECT(t, fileInputStreamClass);
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
object fileInputStreamFdField = findFieldInClass2
|
|
|
|
(t, fileInputStreamClass, "fd", "Ljava/io/FileDescriptor;");
|
|
|
|
if (fileInputStreamFdField == 0) return;
|
|
|
|
|
|
|
|
cp->fileInputStreamFdField = fieldOffset(t, fileInputStreamFdField);
|
|
|
|
|
|
|
|
intercept(t, fileInputStreamClass, "open", "(Ljava/lang/String;)V",
|
|
|
|
voidPointer(openFile));
|
|
|
|
|
|
|
|
intercept(t, fileInputStreamClass, "read", "()I",
|
|
|
|
voidPointer(readByteFromFile));
|
|
|
|
|
|
|
|
intercept(t, fileInputStreamClass, "readBytes", "([BII)I",
|
|
|
|
voidPointer(readBytesFromFile));
|
|
|
|
|
|
|
|
intercept(t, fileInputStreamClass, "skip", "(J)J",
|
|
|
|
voidPointer(skipBytesInFile));
|
|
|
|
|
|
|
|
intercept(t, fileInputStreamClass, "available", "()I",
|
|
|
|
voidPointer(availableBytesInFile));
|
|
|
|
|
|
|
|
intercept(t, fileInputStreamClass, "close0", "()V",
|
|
|
|
voidPointer(closeFile));
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
const char* const fsClassName = "java/io/WinNTFileSystem";
|
|
|
|
const char* const gbaMethodName = "getBooleanAttributes";
|
|
|
|
#else
|
|
|
|
const char* const fsClassName = "java/io/UnixFileSystem";
|
|
|
|
const char* const gbaMethodName = "getBooleanAttributes0";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
object fsClass = resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader), fsClassName, false);
|
|
|
|
if (fsClass == 0) return;
|
|
|
|
|
|
|
|
PROTECT(t, fsClass);
|
|
|
|
|
|
|
|
intercept(t, fsClass, gbaMethodName, "(Ljava/io/File;)I",
|
|
|
|
voidPointer(getFileAttributes));
|
2010-12-01 20:40:43 +00:00
|
|
|
|
|
|
|
intercept(t, fsClass, "checkAccess", "(Ljava/io/File;I)Z",
|
|
|
|
voidPointer(checkFileAccess));
|
2010-11-07 17:08:04 +00:00
|
|
|
|
|
|
|
intercept(t, fsClass, "getLength", "(Ljava/io/File;)J",
|
2010-12-06 00:40:50 +00:00
|
|
|
voidPointer(getFileLength));
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
2010-12-06 00:40:50 +00:00
|
|
|
|
2010-12-09 04:38:16 +00:00
|
|
|
intercept(t, type(t, Machine::ClassLoaderType), "loadLibrary",
|
|
|
|
"(Ljava/lang/Class;Ljava/lang/String;Z)V",
|
|
|
|
voidPointer(loadLibrary));
|
|
|
|
|
2010-12-06 00:40:50 +00:00
|
|
|
intercept(t, type(t, Machine::ClassLoaderType), "getBootstrapResource",
|
|
|
|
"(Ljava/lang/String;)Ljava/net/URL;",
|
|
|
|
voidPointer(getBootstrapResource));
|
|
|
|
|
|
|
|
intercept(t, type(t, Machine::ClassLoaderType), "getBootstrapResources",
|
|
|
|
"(Ljava/lang/String;)Ljava/util/Enumeration;",
|
|
|
|
voidPointer(getBootstrapResources));
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
unsigned
|
|
|
|
countMethods(Thread* t, object c, bool publicOnly)
|
|
|
|
{
|
|
|
|
object table = classMethodTable(t, c);
|
|
|
|
unsigned count = 0;
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
object vmMethod = arrayBody(t, table, i);
|
|
|
|
if (((not publicOnly) or (methodFlags(t, vmMethod) & ACC_PUBLIC))
|
|
|
|
and byteArrayBody(t, methodName(t, vmMethod), 0) != '<')
|
|
|
|
{
|
|
|
|
++ count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
countFields(Thread* t, object c, bool publicOnly)
|
|
|
|
{
|
|
|
|
object table = classFieldTable(t, c);
|
|
|
|
if (publicOnly) {
|
|
|
|
unsigned count = 0;
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
object vmField = arrayBody(t, table, i);
|
2010-09-14 16:49:41 +00:00
|
|
|
if (fieldFlags(t, vmField) & ACC_PUBLIC) {
|
2010-09-10 21:05:29 +00:00
|
|
|
++ count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
2010-09-14 16:49:41 +00:00
|
|
|
} else {
|
|
|
|
return objectArrayLength(t, table);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
countConstructors(Thread* t, object c, bool publicOnly)
|
|
|
|
{
|
|
|
|
object table = classMethodTable(t, c);
|
|
|
|
unsigned count = 0;
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
object vmMethod = arrayBody(t, table, i);
|
|
|
|
if (((not publicOnly) or (methodFlags(t, vmMethod) & ACC_PUBLIC))
|
|
|
|
and strcmp(reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodName(t, vmMethod), 0)),
|
|
|
|
"<init>") == 0)
|
|
|
|
{
|
|
|
|
++ count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
resolveClassBySpec(Thread* t, object loader, const char* spec,
|
|
|
|
unsigned specLength)
|
|
|
|
{
|
|
|
|
switch (*spec) {
|
|
|
|
case 'L': {
|
|
|
|
RUNTIME_ARRAY(char, s, specLength - 1);
|
|
|
|
memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2);
|
|
|
|
RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0;
|
|
|
|
return resolveClass(t, loader, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
case '[': {
|
|
|
|
RUNTIME_ARRAY(char, s, specLength + 1);
|
|
|
|
memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength);
|
|
|
|
RUNTIME_ARRAY_BODY(s)[specLength] = 0;
|
|
|
|
return resolveClass(t, loader, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return primitiveClass(t, *spec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
resolveJType(Thread* t, object loader, const char* spec, unsigned specLength)
|
|
|
|
{
|
|
|
|
object c = resolveClassBySpec(t, loader, spec, specLength);
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
return getJClass(t, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
resolveParameterTypes(Thread* t, object loader, object spec,
|
|
|
|
unsigned* parameterCount, unsigned* returnTypeSpec)
|
|
|
|
{
|
|
|
|
PROTECT(t, loader);
|
|
|
|
PROTECT(t, spec);
|
|
|
|
|
|
|
|
object list = 0;
|
|
|
|
PROTECT(t, list);
|
|
|
|
|
|
|
|
unsigned offset = 1;
|
|
|
|
unsigned count = 0;
|
|
|
|
while (byteArrayBody(t, spec, offset) != ')') {
|
|
|
|
switch (byteArrayBody(t, spec, offset)) {
|
|
|
|
case 'L': {
|
|
|
|
unsigned start = offset;
|
|
|
|
++ offset;
|
|
|
|
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
|
|
|
|
++ offset;
|
|
|
|
|
|
|
|
object type = resolveClassBySpec
|
|
|
|
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
|
|
|
|
offset - start);
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
list = makePair(t, type, list);
|
|
|
|
|
|
|
|
++ count;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case '[': {
|
|
|
|
unsigned start = offset;
|
|
|
|
while (byteArrayBody(t, spec, offset) == '[') ++ offset;
|
|
|
|
switch (byteArrayBody(t, spec, offset)) {
|
|
|
|
case 'L':
|
|
|
|
++ offset;
|
|
|
|
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
|
|
|
|
++ offset;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
++ offset;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
object type = resolveClassBySpec
|
|
|
|
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
|
|
|
|
offset - start);
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
list = makePair(t, type, list);
|
|
|
|
++ count;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
list = makePair
|
|
|
|
(t, primitiveClass(t, byteArrayBody(t, spec, offset)), list);
|
|
|
|
++ offset;
|
|
|
|
++ count;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*parameterCount = count;
|
|
|
|
*returnTypeSpec = offset + 1;
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
resolveParameterJTypes(Thread* t, object loader, object spec,
|
|
|
|
unsigned* parameterCount, unsigned* returnTypeSpec)
|
|
|
|
{
|
|
|
|
object list = resolveParameterTypes
|
|
|
|
(t, loader, spec, parameterCount, returnTypeSpec);
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
PROTECT(t, list);
|
|
|
|
|
|
|
|
object array = makeObjectArray
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, type(t, Machine::JclassType), *parameterCount);
|
2010-09-10 21:05:29 +00:00
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
for (int i = *parameterCount - 1; i >= 0; --i) {
|
|
|
|
object c = getJClass(t, pairFirst(t, list));
|
|
|
|
set(t, array, ArrayBody + (i * BytesPerWord), c);
|
|
|
|
list = pairSecond(t, list);
|
|
|
|
}
|
|
|
|
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
resolveExceptionJTypes(Thread* t, object loader, object addendum)
|
|
|
|
{
|
2010-11-26 19:41:31 +00:00
|
|
|
if (addendum == 0 or methodAddendumExceptionTable(t, addendum) == 0) {
|
2010-09-14 16:49:41 +00:00
|
|
|
return makeObjectArray(t, type(t, Machine::JclassType), 0);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PROTECT(t, loader);
|
|
|
|
PROTECT(t, addendum);
|
|
|
|
|
|
|
|
object array = makeObjectArray
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, type(t, Machine::JclassType),
|
2010-09-10 21:05:29 +00:00
|
|
|
shortArrayLength(t, methodAddendumExceptionTable(t, addendum)));
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < shortArrayLength
|
|
|
|
(t, methodAddendumExceptionTable(t, addendum)); ++i)
|
|
|
|
{
|
|
|
|
uint16_t index = shortArrayBody
|
|
|
|
(t, methodAddendumExceptionTable(t, addendum), i) - 1;
|
|
|
|
|
|
|
|
object o = singletonObject(t, addendumPool(t, addendum), index);
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
|
2010-09-10 21:05:29 +00:00
|
|
|
o = resolveClass(t, loader, referenceName(t, o));
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord),
|
|
|
|
o);
|
|
|
|
}
|
|
|
|
|
|
|
|
o = getJClass(t, o);
|
|
|
|
|
|
|
|
set(t, array, ArrayBody + (i * BytesPerWord), o);
|
|
|
|
}
|
|
|
|
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setProperty(Thread* t, object method, object properties,
|
|
|
|
const char* name, const void* value, const char* format = "%s")
|
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
|
|
|
PROTECT(t, properties);
|
|
|
|
|
|
|
|
object n = makeString(t, "%s", name);
|
|
|
|
PROTECT(t, n);
|
|
|
|
|
|
|
|
object v = makeString(t, format, value);
|
|
|
|
|
|
|
|
t->m->processor->invoke(t, method, properties, n, v);
|
|
|
|
}
|
|
|
|
|
2010-09-17 01:43:27 +00:00
|
|
|
object
|
|
|
|
interruptLock(Thread* t, object thread)
|
|
|
|
{
|
|
|
|
if (threadInterruptLock(t, thread) == 0) {
|
|
|
|
PROTECT(t, thread);
|
|
|
|
ACQUIRE(t, t->m->referenceLock);
|
|
|
|
|
|
|
|
if (threadInterruptLock(t, thread) == 0) {
|
|
|
|
object head = makeMonitorNode(t, 0, 0);
|
|
|
|
object lock = makeMonitor(t, 0, 0, 0, head, head, 0);
|
|
|
|
set(t, thread, ThreadInterruptLock, lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return threadInterruptLock(t, thread);
|
|
|
|
}
|
|
|
|
|
2010-11-07 04:21:19 +00:00
|
|
|
bool
|
|
|
|
pipeAvailable(int fd, int* available)
|
|
|
|
{
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
|
|
|
if (h == INVALID_HANDLE_VALUE) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD n;
|
|
|
|
if (PeekNamedPipe(h, 0,0, 0, &n, 0)) {
|
|
|
|
*available = n;
|
|
|
|
} else {
|
|
|
|
if (GetLastError() != ERROR_BROKEN_PIPE) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*available = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return ioctl(fd, FIONREAD, available) >= 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
} // namespace local
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
|
|
|
Classpath*
|
2010-11-05 19:18:28 +00:00
|
|
|
makeClasspath(System* s, Allocator* allocator, const char* javaHome,
|
|
|
|
const char* embedPrefix)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
2010-11-05 19:18:28 +00:00
|
|
|
local::MyClasspath(s, allocator, javaHome, embedPrefix);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace vm
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_java_lang_Class_getSuperclass
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object super = classSuper
|
|
|
|
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0])));
|
|
|
|
|
|
|
|
return super ? reinterpret_cast<int64_t>(getJClass(t, super)) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void
|
|
|
|
Avian_sun_misc_Unsafe_registerNatives
|
|
|
|
(Thread*, object, uintptr_t*)
|
|
|
|
{
|
|
|
|
// ignore
|
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
extern "C" JNIEXPORT int64_t
|
|
|
|
Avian_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
//object name = reinterpret_cast<object>(arguments[1]);
|
|
|
|
object data = reinterpret_cast<object>(arguments[2]);
|
|
|
|
int32_t offset = arguments[3];
|
|
|
|
int32_t length = arguments[4];
|
|
|
|
object loader = reinterpret_cast<object>(arguments[5]);
|
|
|
|
//object domain = reinterpret_cast<object>(arguments[6]);
|
|
|
|
|
|
|
|
uint8_t* buffer = static_cast<uint8_t*>
|
|
|
|
(t->m->heap->allocate(length));
|
|
|
|
memcpy(buffer, &byteArrayBody(t, data, offset), length);
|
|
|
|
object c = defineClass(t, loader, buffer, length);
|
|
|
|
|
|
|
|
return c ? reinterpret_cast<int64_t>(getJClass(t, c)) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t
|
|
|
|
Avian_sun_misc_Unsafe_allocateInstance
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[1]));
|
|
|
|
PROTECT(t, c);
|
|
|
|
|
|
|
|
initClass(t, c);
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
return reinterpret_cast<int64_t>(make(t, c));
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_staticFieldOffset
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object jfield = reinterpret_cast<object>(arguments[1]);
|
|
|
|
return fieldOffset
|
|
|
|
(t, arrayBody
|
|
|
|
(t, classFieldTable
|
|
|
|
(t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield)));
|
|
|
|
}
|
|
|
|
|
2010-09-15 00:52:57 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_arrayBaseOffset
|
|
|
|
(Thread*, object, uintptr_t*)
|
|
|
|
{
|
|
|
|
return BytesPerWord * 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_arrayIndexScale
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object c = jclassVmClass(t, reinterpret_cast<object>(arguments[1]));
|
|
|
|
|
|
|
|
if (classVmFlags(t, c) & PrimitiveFlag) {
|
|
|
|
const char* name = reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, local::getClassName(t, c), 0));
|
|
|
|
|
|
|
|
switch (*name) {
|
|
|
|
case 'b': return 1;
|
|
|
|
case 's':
|
|
|
|
case 'c': return 2;
|
|
|
|
case 'l':
|
|
|
|
case 'd': return 8;
|
|
|
|
case 'i':
|
|
|
|
case 'f': return 4;
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return BytesPerWord;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_staticFieldBase
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(classStaticTable
|
|
|
|
(t, jclassVmClass
|
|
|
|
(t, jfieldClazz(t, reinterpret_cast<object>(arguments[1])))));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_objectFieldOffset
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object jfield = reinterpret_cast<object>(arguments[1]);
|
|
|
|
return fieldOffset
|
|
|
|
(t, arrayBody
|
|
|
|
(t, classFieldTable
|
|
|
|
(t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield)));
|
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getObject
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
|
|
|
return cast<uintptr_t>(o, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putObject
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
uintptr_t value = arguments[4];
|
|
|
|
|
|
|
|
set(t, o, offset, reinterpret_cast<object>(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
|
|
|
return cast<int32_t>(o, offset);
|
|
|
|
}
|
|
|
|
|
2010-09-15 00:52:57 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getIntVolatile
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
|
|
|
int32_t result = cast<int32_t>(o, offset);
|
|
|
|
loadMemoryBarrier();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
int32_t value = arguments[4];
|
|
|
|
|
|
|
|
cast<int32_t>(o, offset) = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getBoolean
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
|
|
|
return cast<uint8_t>(o, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putBoolean
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
uint8_t value = arguments[4];
|
|
|
|
|
|
|
|
cast<uint8_t>(o, offset) = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
int64_t value; memcpy(&value, arguments + 4, 8);
|
|
|
|
|
|
|
|
cast<int64_t>(o, offset) = value;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getObjectVolatile
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
2010-09-14 16:49:41 +00:00
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
|
|
|
uintptr_t value = cast<uintptr_t>(o, offset);
|
2010-09-10 21:05:29 +00:00
|
|
|
loadMemoryBarrier();
|
2010-09-14 16:49:41 +00:00
|
|
|
return value;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_compareAndSwapInt
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object target = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
2010-11-13 01:29:12 +00:00
|
|
|
uint32_t expect = arguments[4];
|
|
|
|
uint32_t update = arguments[5];
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-13 01:29:12 +00:00
|
|
|
return atomicCompareAndSwap32
|
|
|
|
(&cast<uint32_t>(target, offset), expect, update);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_compareAndSwapObject
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object target = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
2010-11-13 01:29:12 +00:00
|
|
|
uintptr_t expect = arguments[4];
|
|
|
|
uintptr_t update = arguments[5];
|
2010-09-14 16:49:41 +00:00
|
|
|
|
2010-11-13 01:29:12 +00:00
|
|
|
bool success = atomicCompareAndSwap
|
|
|
|
(&cast<uintptr_t>(target, offset), expect, update);
|
2010-09-14 16:49:41 +00:00
|
|
|
|
|
|
|
if (success) {
|
|
|
|
mark(t, target, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_compareAndSwapLong
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object target = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
2010-11-13 01:29:12 +00:00
|
|
|
uint64_t expect; memcpy(&expect, arguments + 4, 8);
|
|
|
|
uint64_t update; memcpy(&update, arguments + 6, 8);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-13 01:29:12 +00:00
|
|
|
return atomicCompareAndSwap64
|
|
|
|
(&cast<uint64_t>(target, offset), expect, update);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_allocateMemory
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
void* p = malloc(arguments[1]);
|
|
|
|
if (p) {
|
|
|
|
return reinterpret_cast<int64_t>(p);
|
|
|
|
} else {
|
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->exception = makeThrowable(t, Machine::OutOfMemoryErrorType);
|
2010-09-10 21:05:29 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_freeMemory
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
void* p = reinterpret_cast<void*>(arguments[1]);
|
|
|
|
if (p) {
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_setMemory
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t p; memcpy(&p, arguments + 1, 8);
|
|
|
|
int64_t count; memcpy(&count, arguments + 3, 8);
|
|
|
|
int8_t v = arguments[5];
|
|
|
|
|
|
|
|
memset(reinterpret_cast<int8_t*>(p), v, count);
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putLong__JJ
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t p; memcpy(&p, arguments + 1, 8);
|
|
|
|
int64_t v; memcpy(&v, arguments + 3, 8);
|
|
|
|
|
|
|
|
*reinterpret_cast<int64_t*>(p) = v;
|
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putInt__JI
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t p; memcpy(&p, arguments + 1, 8);
|
|
|
|
int32_t v = arguments[3];
|
|
|
|
|
|
|
|
*reinterpret_cast<int32_t*>(p) = v;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getByte__J
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t p; memcpy(&p, arguments + 1, 8);
|
|
|
|
|
|
|
|
return *reinterpret_cast<int8_t*>(p);
|
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getInt__J
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t p; memcpy(&p, arguments + 1, 8);
|
|
|
|
|
|
|
|
return *reinterpret_cast<int32_t*>(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_pageSize
|
|
|
|
(Thread*, object, uintptr_t*)
|
|
|
|
{
|
|
|
|
return local::PageSize;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_ensureClassInitialized
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
initClass(t, jclassVmClass(t, reinterpret_cast<object>(arguments[1])));
|
|
|
|
}
|
|
|
|
|
2010-11-27 18:25:02 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_unpark
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object thread = reinterpret_cast<object>(arguments[1]);
|
|
|
|
|
|
|
|
monitorAcquire(t, local::interruptLock(t, thread));
|
|
|
|
threadUnparked(t, thread) = true;
|
|
|
|
monitorNotify(t, local::interruptLock(t, thread));
|
|
|
|
monitorRelease(t, local::interruptLock(t, thread));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_park
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
bool absolute = arguments[1];
|
|
|
|
int64_t time; memcpy(&time, arguments + 2, 8);
|
|
|
|
|
|
|
|
if (absolute) {
|
|
|
|
time -= t->m->system->now();
|
2010-11-27 23:27:30 +00:00
|
|
|
if (time <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
2010-11-27 18:25:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
monitorAcquire(t, local::interruptLock(t, t->javaThread));
|
|
|
|
while (not (threadUnparked(t, t->javaThread)
|
|
|
|
or monitorWait(t, local::interruptLock(t, t->javaThread), time)))
|
|
|
|
{ }
|
|
|
|
threadUnparked(t, t->javaThread) = false;
|
|
|
|
monitorRelease(t, local::interruptLock(t, t->javaThread));
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetInterfaceVersion)()
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
return local::InterfaceVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IHashCode)(Thread* t, jobject o)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return objectHash(t, *o);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_MonitorWait)(Thread* t, jobject o, jlong milliseconds)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
vm::wait(t, *o, milliseconds);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_MonitorNotify)(Thread* t, jobject o)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
notify(t, *o);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_MonitorNotifyAll)(Thread* t, jobject o)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
notifyAll(t, *o);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Clone)(Thread* t, jobject o)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return makeLocalReference(t, clone(t, *o));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_InternString)(Thread* t, jstring s)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return makeLocalReference(t, intern(t, *s));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_CurrentTimeMillis)(Thread* t, jclass)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
return t->m->system->now();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_NanoTime)(Thread* t, jclass)
|
2010-09-10 23:47:23 +00:00
|
|
|
{
|
|
|
|
return t->m->system->now() * 1000 * 1000;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ArrayCopy)(Thread* t, jclass, jobject src, jint srcOffset,
|
|
|
|
jobject dst, jint dstOffset, jint length)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
arrayCopy(t, *src, srcOffset, *dst, dstOffset, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_InitProperties)(Thread* t, jobject properties)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object method = resolveMethod
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, root(t, Machine::BootLoader), "java/util/Properties", "setProperty",
|
2010-09-10 21:05:29 +00:00
|
|
|
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
local::setProperty(t, method, *properties, "line.separator", "\r\n");
|
|
|
|
local::setProperty(t, method, *properties, "file.separator", "\\");
|
|
|
|
local::setProperty(t, method, *properties, "path.separator", ";");
|
|
|
|
local::setProperty(t, method, *properties, "os.name", "Windows");
|
|
|
|
|
|
|
|
TCHAR buffer[MAX_PATH];
|
|
|
|
GetTempPath(MAX_PATH, buffer);
|
|
|
|
|
|
|
|
local::setProperty(t, method, *properties, "java.io.tmpdir", buffer);
|
|
|
|
local::setProperty(t, method, *properties, "java.home", buffer);
|
|
|
|
local::setProperty(t, method, *properties, "user.home",
|
|
|
|
_wgetenv(L"USERPROFILE"), "%ls");
|
|
|
|
|
|
|
|
GetCurrentDirectory(MAX_PATH, buffer);
|
|
|
|
|
|
|
|
local::setProperty(t, method, *properties, "user.dir", buffer);
|
|
|
|
#else
|
|
|
|
local::setProperty(t, method, *properties, "line.separator", "\n");
|
|
|
|
local::setProperty(t, method, *properties, "file.separator", "/");
|
|
|
|
local::setProperty(t, method, *properties, "path.separator", ":");
|
|
|
|
# ifdef __APPLE__
|
|
|
|
local::setProperty(t, method, *properties, "os.name", "Mac OS X");
|
|
|
|
# else
|
|
|
|
local::setProperty(t, method, *properties, "os.name", "Linux");
|
|
|
|
# endif
|
|
|
|
local::setProperty(t, method, *properties, "java.io.tmpdir", "/tmp");
|
|
|
|
local::setProperty(t, method, *properties, "user.home", getenv("HOME"));
|
|
|
|
local::setProperty(t, method, *properties, "user.dir", getenv("PWD"));
|
2010-12-01 03:25:48 +00:00
|
|
|
#endif
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
local::setProperty(t, method, *properties, "java.protocol.handler.pkgs",
|
|
|
|
"avian");
|
|
|
|
|
2010-09-20 23:31:23 +00:00
|
|
|
local::setProperty
|
|
|
|
(t, method, *properties, "java.home",
|
|
|
|
static_cast<local::MyClasspath*>(t->m->classpath)->javaHome);
|
|
|
|
|
|
|
|
local::setProperty
|
|
|
|
(t, method, *properties, "sun.boot.library.path",
|
|
|
|
static_cast<local::MyClasspath*>(t->m->classpath)->libraryPath);
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
local::setProperty(t, method, *properties, "file.encoding", "ASCII");
|
|
|
|
#ifdef ARCH_x86_32
|
|
|
|
local::setProperty(t, method, *properties, "os.arch", "x86");
|
|
|
|
#elif defined ARCH_x86_64
|
|
|
|
local::setProperty(t, method, *properties, "os.arch", "x86_64");
|
|
|
|
#elif defined ARCH_powerpc
|
|
|
|
local::setProperty(t, method, *properties, "os.arch", "ppc");
|
|
|
|
#elif defined ARCH_arm
|
|
|
|
local::setProperty(t, method, *properties, "os.arch", "arm");
|
|
|
|
#else
|
|
|
|
local::setProperty(t, method, *properties, "os.arch", "unknown");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < t->m->propertyCount; ++i) {
|
|
|
|
const char* start = t->m->properties[i];
|
|
|
|
const char* p = start;
|
|
|
|
while (*p and *p != '=') ++p;
|
|
|
|
|
|
|
|
if (*p == '=') {
|
|
|
|
RUNTIME_ARRAY(char, name, (p - start) + 1);
|
|
|
|
memcpy(name, start, p - start);
|
|
|
|
name[p - start] = 0;
|
|
|
|
local::setProperty
|
|
|
|
(t, method, *properties, RUNTIME_ARRAY_BODY(name), p + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return properties;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_OnExit)(void (*)(void)) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Exit)(jint code)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
exit(code);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Halt)(jint code)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
exit(code);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GC)()
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
|
|
|
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
collect(t, Heap::MajorCollection);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_MaxObjectInspectionAge)(void) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_TraceInstructions)(jboolean) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_TraceMethodCalls)(jboolean) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_TotalMemory)()
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_FreeMemory)()
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_MaxMemory)()
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-27 18:25:02 +00:00
|
|
|
EXPORT(JVM_ActiveProcessorCount)()
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT void* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_LoadLibrary)(const char* path)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
2010-11-04 17:02:09 +00:00
|
|
|
|
2010-11-07 04:21:19 +00:00
|
|
|
RUNTIME_ARRAY(char, p, strlen(path) + 1);
|
|
|
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p), path);
|
|
|
|
|
2010-09-20 23:31:23 +00:00
|
|
|
return loadLibrary
|
2010-11-07 04:21:19 +00:00
|
|
|
(t, static_cast<local::MyClasspath*>(t->m->classpath)->libraryPath,
|
|
|
|
RUNTIME_ARRAY_BODY(p), false, false);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_UnloadLibrary)(void*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_FindLibraryEntry)(void* library, const char* name)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
|
|
|
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-12-01 16:54:29 +00:00
|
|
|
if (library == RTLD_DEFAULT) {
|
2010-11-27 18:25:02 +00:00
|
|
|
library = t->m->libraries;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
return static_cast<System::Library*>(library)->resolve(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsSupportedJNIVersion)(jint version)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
return version <= JNI_VERSION_1_4;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsNaN)(jdouble) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_FillInStackTrace)(Thread* t, jobject throwable)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object trace = getTrace(t, 1);
|
|
|
|
set(t, *throwable, ThrowableTrace, trace);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_PrintStackTrace)(Thread*, jobject, jobject) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetStackTraceDepth)(Thread* t, jobject throwable)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
return objectArrayLength(t, throwableTrace(t, *throwable));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetStackTraceElement)(Thread* t, jobject throwable, jint index)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return makeLocalReference
|
|
|
|
(t, makeStackTraceElement
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, objectArrayBody(t, throwableTrace(t, *throwable), index)));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_InitializeCompiler) (Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsSilentCompiler)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_CompileClass)(Thread*, jclass, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_CompileClasses)(Thread*, jclass, jstring) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_CompilerCommand)(Thread*, jclass, jobject) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_EnableCompiler)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_DisableCompiler)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_StartThread)(Thread* t, jobject thread)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
startThread(t, *thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_StopThread)(Thread*, jobject, jobject) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsThreadAlive)(Thread* t, jobject thread)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, *thread));
|
2010-09-14 16:49:41 +00:00
|
|
|
return p and (p->flags & Thread::ActiveFlag) != 0;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SuspendThread)(Thread*, jobject) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ResumeThread)(Thread*, jobject) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SetThreadPriority)(Thread*, jobject, jint)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
// ignore
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Yield)(Thread*, jclass)
|
2010-09-17 22:10:01 +00:00
|
|
|
{
|
2010-11-07 04:21:19 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
SwitchToThread();
|
|
|
|
#else
|
2010-09-17 22:10:01 +00:00
|
|
|
sched_yield();
|
2010-11-07 04:21:19 +00:00
|
|
|
#endif
|
2010-09-17 22:10:01 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Sleep)(Thread* t, jclass, jlong milliseconds)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
if (threadSleepLock(t, t->javaThread) == 0) {
|
|
|
|
object lock = makeJobject(t);
|
|
|
|
set(t, t->javaThread, ThreadSleepLock, lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
acquire(t, threadSleepLock(t, t->javaThread));
|
|
|
|
vm::wait(t, threadSleepLock(t, t->javaThread), milliseconds);
|
|
|
|
release(t, threadSleepLock(t, t->javaThread));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_CurrentThread)(Thread* t, jclass)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return makeLocalReference(t, t->javaThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_CountStackFrames)(Thread*, jobject) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Interrupt)(Thread* t, jobject thread)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-09-17 01:43:27 +00:00
|
|
|
monitorAcquire(t, local::interruptLock(t, *thread));
|
2010-09-15 00:52:57 +00:00
|
|
|
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, *thread));
|
|
|
|
if (p) {
|
|
|
|
interrupt(t, p);
|
2010-09-17 01:43:27 +00:00
|
|
|
} else {
|
|
|
|
threadInterrupted(t, *thread) = true;
|
2010-09-15 00:52:57 +00:00
|
|
|
}
|
2010-09-17 01:43:27 +00:00
|
|
|
monitorRelease(t, local::interruptLock(t, *thread));
|
2010-09-15 00:52:57 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsInterrupted)(Thread* t, jobject thread, jboolean clear)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-09-17 01:43:27 +00:00
|
|
|
monitorAcquire(t, local::interruptLock(t, *thread));
|
2010-09-14 16:49:41 +00:00
|
|
|
bool v = threadInterrupted(t, *thread);
|
|
|
|
if (clear) {
|
|
|
|
threadInterrupted(t, *thread) = false;
|
|
|
|
}
|
2010-09-17 01:43:27 +00:00
|
|
|
monitorRelease(t, local::interruptLock(t, *thread));
|
2010-09-14 16:49:41 +00:00
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_HoldsLock)(Thread*, jclass, jobject) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_DumpAllStacks)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetAllThreads)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-27 23:27:30 +00:00
|
|
|
EXPORT(JVM_DumpThreads)(Thread* t, jclass, jobjectArray threads)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
unsigned threadsLength = objectArrayLength(t, *threads);
|
|
|
|
object arrayClass = resolveObjectArrayClass
|
|
|
|
(t, classLoader(t, type(t, Machine::StackTraceElementType)),
|
|
|
|
type(t, Machine::StackTraceElementType));
|
|
|
|
object result = makeObjectArray(t, arrayClass, threadsLength);
|
|
|
|
PROTECT(t, result);
|
|
|
|
|
|
|
|
for (unsigned threadsIndex = 0; threadsIndex < threadsLength;
|
|
|
|
++ threadsIndex)
|
|
|
|
{
|
|
|
|
Thread* peer = reinterpret_cast<Thread*>
|
|
|
|
(threadPeer(t, objectArrayBody(t, *threads, threadsIndex)));
|
|
|
|
|
|
|
|
if (peer) {
|
|
|
|
object trace = t->m->processor->getStackTrace(t, peer);
|
|
|
|
PROTECT(t, trace);
|
|
|
|
|
|
|
|
unsigned traceLength = objectArrayLength(t, trace);
|
|
|
|
object array = makeObjectArray
|
|
|
|
(t, type(t, Machine::StackTraceElementType), traceLength);
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
for (unsigned traceIndex = 0; traceIndex < traceLength; ++ traceIndex) {
|
|
|
|
object ste = makeStackTraceElement
|
|
|
|
(t, objectArrayBody(t, trace, traceIndex));
|
|
|
|
set(t, array, ArrayBody + (traceIndex * BytesPerWord), ste);
|
|
|
|
}
|
|
|
|
|
|
|
|
set(t, result, ArrayBody + (threadsIndex * BytesPerWord), array);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return makeLocalReference(t, result);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_CurrentLoadedClass)(Thread*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_CurrentClassLoader)(Thread*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassContext)(Thread* t)
|
2010-09-10 23:47:23 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object trace = getTrace(t, 1);
|
|
|
|
PROTECT(t, trace);
|
|
|
|
|
|
|
|
object context = makeObjectArray
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, type(t, Machine::JclassType), objectArrayLength(t, trace));
|
2010-09-10 23:47:23 +00:00
|
|
|
PROTECT(t, context);
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) {
|
2010-09-10 23:47:23 +00:00
|
|
|
object c = getJClass
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, methodClass(t, traceElementMethod(t, objectArrayBody(t, trace, i))));
|
2010-09-10 23:47:23 +00:00
|
|
|
|
|
|
|
set(t, context, ArrayBody + (i * BytesPerWord), c);
|
|
|
|
}
|
|
|
|
|
|
|
|
return makeLocalReference(t, context);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ClassDepth)(Thread*, jstring) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ClassLoaderDepth)(Thread*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetSystemPackage)(Thread*, jstring)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetSystemPackages)(Thread*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_AllocateNewObject)(Thread*, jobject, jclass,
|
2010-09-10 21:05:29 +00:00
|
|
|
jclass) { abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_AllocateNewArray)(Thread*, jobject, jclass,
|
2010-09-10 21:05:29 +00:00
|
|
|
jint) { abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_LatestUserDefinedLoader)(Thread*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_LoadClass0)(Thread*, jobject, jclass,
|
2010-09-10 21:05:29 +00:00
|
|
|
jstring) { abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetArrayLength)(Thread* t, jobject array)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return cast<uintptr_t>(*array, BytesPerWord);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetArrayElement)(Thread* t, jobject array, jint index)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return makeLocalReference(t, objectArrayBody(t, *array, index));
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jvalue JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetPrimitiveArrayElement)(Thread*, jobject, jint, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SetArrayElement)(Thread* t, jobject array, jint index,
|
|
|
|
jobject value)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
set(t, *array, ArrayBody + (index * BytesPerWord), (value ? *value : 0));
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SetPrimitiveArrayElement)(Thread*, jobject, jint, jvalue,
|
2010-09-10 21:05:29 +00:00
|
|
|
unsigned char) { abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_NewArray)(Thread* t, jclass elementClass, jint length)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object c = jclassVmClass(t, *elementClass);
|
|
|
|
|
|
|
|
if (classVmFlags(t, c) & PrimitiveFlag) {
|
|
|
|
const char* name = reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, local::getClassName(t, c), 0));
|
|
|
|
|
|
|
|
switch (*name) {
|
|
|
|
case 'b':
|
|
|
|
if (name[1] == 'o') {
|
|
|
|
return makeLocalReference(t, makeBooleanArray(t, length));
|
|
|
|
} else {
|
|
|
|
return makeLocalReference(t, makeByteArray(t, length));
|
|
|
|
}
|
|
|
|
case 'c': return makeLocalReference(t, makeCharArray(t, length));
|
|
|
|
case 'd': return makeLocalReference(t, makeDoubleArray(t, length));
|
|
|
|
case 'f': return makeLocalReference(t, makeFloatArray(t, length));
|
|
|
|
case 'i': return makeLocalReference(t, makeIntArray(t, length));
|
|
|
|
case 'l': return makeLocalReference(t, makeLongArray(t, length));
|
|
|
|
case 's': return makeLocalReference(t, makeShortArray(t, length));
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} else {
|
2010-09-14 16:49:41 +00:00
|
|
|
return makeLocalReference(t, makeObjectArray(t, c, length));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_NewMultiArray)(Thread*, jclass, jintArray) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCallerClass)(Thread* t, int target)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return makeLocalReference
|
|
|
|
(t, getJClass(t, methodClass(t, getCaller(t, target))));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_FindPrimitiveClass)(Thread* t, const char* name)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
switch (*name) {
|
|
|
|
case 'b':
|
|
|
|
if (name[1] == 'o') {
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, getJClass(t, type(t, Machine::JbooleanType)));
|
2010-09-10 21:05:29 +00:00
|
|
|
} else {
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, getJClass(t, type(t, Machine::JbyteType)));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
case 'c':
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, getJClass(t, type(t, Machine::JcharType)));
|
2010-09-10 21:05:29 +00:00
|
|
|
case 'd':
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, getJClass(t, type(t, Machine::JdoubleType)));
|
2010-09-10 21:05:29 +00:00
|
|
|
case 'f':
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, getJClass(t, type(t, Machine::JfloatType)));
|
2010-09-10 21:05:29 +00:00
|
|
|
case 'i':
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, getJClass(t, type(t, Machine::JintType)));
|
2010-09-10 21:05:29 +00:00
|
|
|
case 'l':
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, getJClass(t, type(t, Machine::JlongType)));
|
2010-09-10 21:05:29 +00:00
|
|
|
case 's':
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, getJClass(t, type(t, Machine::JshortType)));
|
2010-09-10 21:05:29 +00:00
|
|
|
case 'v':
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, getJClass(t, type(t, Machine::JvoidType)));
|
2010-09-10 21:05:29 +00:00
|
|
|
default:
|
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->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType);
|
2010-09-10 21:05:29 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ResolveClass)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name,
|
|
|
|
jboolean init, jobject loader,
|
|
|
|
jboolean throwError)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
object c = resolveClass
|
|
|
|
(t, loader ? *loader : root(t, Machine::BootLoader), name);
|
2010-09-10 21:05:29 +00:00
|
|
|
if (t->exception) {
|
|
|
|
if (throwError) {
|
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->exception = makeThrowable
|
2010-09-10 21:05:29 +00:00
|
|
|
(t, Machine::NoClassDefFoundErrorType,
|
|
|
|
throwableMessage(t, t->exception),
|
|
|
|
throwableTrace(t, t->exception),
|
|
|
|
throwableCause(t, t->exception));
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (init) {
|
|
|
|
PROTECT(t, c);
|
|
|
|
|
|
|
|
initClass(t, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
return makeLocalReference(t, getJClass(t, c));
|
|
|
|
}
|
|
|
|
|
2010-11-05 21:34:28 +00:00
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_FindClassFromBootLoader)(Thread* t, const char* name,
|
|
|
|
jboolean throwError)
|
2010-11-05 21:34:28 +00:00
|
|
|
{
|
2010-11-07 17:08:04 +00:00
|
|
|
return EXPORT(JVM_FindClassFromClassLoader)(t, name, false, 0, throwError);
|
2010-11-05 21:34:28 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_FindClassFromClass)(Thread*, const char*, jboolean,
|
2010-09-10 21:05:29 +00:00
|
|
|
jclass) { abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_FindLoadedClass)(Thread* t, jobject loader, jstring name)
|
2010-09-10 23:47:23 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object spec = makeByteArray(t, stringLength(t, *name) + 1);
|
2010-09-22 19:58:46 +00:00
|
|
|
|
2010-09-10 23:47:23 +00:00
|
|
|
{ char* s = reinterpret_cast<char*>(&byteArrayBody(t, spec, 0));
|
|
|
|
stringChars(t, *name, s);
|
|
|
|
replace('.', '/', s);
|
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
object c = findLoadedClass(t, *loader, spec);
|
2010-09-10 23:47:23 +00:00
|
|
|
|
|
|
|
return c ? makeLocalReference(t, getJClass(t, c)) : 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_DefineClass)(Thread* t, const char*, jobject loader,
|
|
|
|
const uint8_t* data, jsize length, jobject)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object c = defineClass(t, *loader, data, length);
|
|
|
|
|
|
|
|
return c ? makeLocalReference(t, getJClass(t, c)) : 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_DefineClassWithSource)(Thread* t, const char*, jobject loader,
|
2010-09-15 00:52:57 +00:00
|
|
|
const uint8_t* data, jsize length, jobject,
|
|
|
|
const char*)
|
|
|
|
{
|
2010-11-07 17:08:04 +00:00
|
|
|
return EXPORT(JVM_DefineClass)(t, 0, loader, data, length, 0);
|
2010-09-15 00:52:57 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassName)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return makeLocalReference(t, jclassName(t, *c));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassInterfaces)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object table = classInterfaceTable(t, jclassVmClass(t, *c));
|
|
|
|
if (table) {
|
|
|
|
unsigned stride =
|
|
|
|
(classFlags(t, jclassVmClass(t, *c)) & ACC_INTERFACE) == 0 ? 2 : 1;
|
|
|
|
|
|
|
|
object array = makeObjectArray
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, type(t, Machine::JclassType), arrayLength(t, table) / stride);
|
2010-09-10 21:05:29 +00:00
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < objectArrayLength(t, array); ++i) {
|
|
|
|
object interface = getJClass(t, arrayBody(t, table, i * stride));
|
|
|
|
set(t, array, ArrayBody + (i * BytesPerWord), interface);
|
|
|
|
}
|
|
|
|
|
|
|
|
return makeLocalReference(t, array);
|
|
|
|
} else {
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, makeObjectArray(t, type(t, Machine::JclassType), 0));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassLoader)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object loader = classLoader(t, jclassVmClass(t, *c));
|
2010-11-04 17:43:50 +00:00
|
|
|
|
|
|
|
if (loader == root(t, Machine::BootLoader)) {
|
|
|
|
// sun.misc.Unsafe.getUnsafe expects a null result if the class
|
|
|
|
// loader is the boot classloader and will throw a
|
|
|
|
// SecurityException otherwise.
|
|
|
|
object caller = getCaller(t, 2);
|
|
|
|
if (caller and strcmp
|
|
|
|
(reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, className(t, methodClass(t, caller)), 0)),
|
|
|
|
"sun/misc/Unsafe") == 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return makeLocalReference(t, root(t, Machine::BootLoader));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return makeLocalReference(t, loader);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsInterface)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return (classFlags(t, jclassVmClass(t, *c)) & ACC_INTERFACE) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-27 18:25:02 +00:00
|
|
|
EXPORT(JVM_GetClassSigners)(Thread* t, jclass c)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object runtimeData = getClassRuntimeDataIfExists(t, jclassVmClass(t, *c));
|
|
|
|
|
|
|
|
return runtimeData ? makeLocalReference
|
|
|
|
(t, classRuntimeDataSigners(t, runtimeData)) : 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-27 18:25:02 +00:00
|
|
|
EXPORT(JVM_SetClassSigners)(Thread* t, jclass c, jobjectArray signers)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c));
|
|
|
|
|
|
|
|
set(t, runtimeData, ClassRuntimeDataSigners, *signers);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetProtectionDomain)(Thread* t, jclass)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object openJDK = resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader), "avian/OpenJDK");
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
object method = resolveMethod
|
|
|
|
(t, openJDK, "getProtectionDomain", "()Ljava/security/ProtectionDomain;");
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
return makeLocalReference(t, t->m->processor->invoke(t, method, 0));
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SetProtectionDomain)(Thread*, jclass, jobject) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsArrayClass)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return classArrayDimensions(t, jclassVmClass(t, *c)) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsPrimitiveClass)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return (classVmFlags(t, jclassVmClass(t, *c)) & PrimitiveFlag) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetComponentType)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
uint8_t n = byteArrayBody(t, className(t, jclassVmClass(t, *c)), 1);
|
|
|
|
if (n != 'L' and n != '[') {
|
|
|
|
return makeLocalReference(t, getJClass(t, primitiveClass(t, n)));
|
|
|
|
} else {
|
|
|
|
return makeLocalReference
|
|
|
|
(t, getJClass(t, classStaticTable(t, jclassVmClass(t, *c))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassModifiers)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return classFlags(t, jclassVmClass(t, *c));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetDeclaredClasses)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetDeclaringClass)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassSignature)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jbyteArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassAnnotations)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-11-26 19:41:31 +00:00
|
|
|
object addendum = classAddendum(t, jclassVmClass(t, *c));
|
|
|
|
return addendum
|
|
|
|
? makeLocalReference(t, addendumAnnotationTable(t, addendum)) : 0;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassDeclaredMethods)(Thread* t, jclass c, jboolean publicOnly)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object table = classMethodTable(t, jclassVmClass(t, *c));
|
|
|
|
if (table) {
|
2010-09-14 16:49:41 +00:00
|
|
|
PROTECT(t, table);
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
object array = makeObjectArray
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, type(t, Machine::JmethodType),
|
2010-09-10 21:05:29 +00:00
|
|
|
local::countMethods(t, jclassVmClass(t, *c), publicOnly));
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
unsigned ai = 0;
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
object vmMethod = arrayBody(t, table, i);
|
|
|
|
PROTECT(t, vmMethod);
|
|
|
|
|
|
|
|
if (((not publicOnly) or (methodFlags(t, vmMethod) & ACC_PUBLIC))
|
|
|
|
and byteArrayBody(t, methodName(t, vmMethod), 0) != '<')
|
|
|
|
{
|
|
|
|
object name = intern
|
|
|
|
(t, t->m->classpath->makeString
|
|
|
|
(t, methodName(t, vmMethod), 0, byteArrayLength
|
|
|
|
(t, methodName(t, vmMethod)) - 1));
|
|
|
|
PROTECT(t, name);
|
|
|
|
|
|
|
|
unsigned parameterCount;
|
|
|
|
unsigned returnTypeSpec;
|
|
|
|
object parameterTypes = local::resolveParameterJTypes
|
|
|
|
(t, classLoader(t, jclassVmClass(t, *c)), methodSpec(t, vmMethod),
|
|
|
|
¶meterCount, &returnTypeSpec);
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
PROTECT(t, parameterTypes);
|
|
|
|
|
|
|
|
object returnType = local::resolveJType
|
|
|
|
(t, classLoader(t, jclassVmClass(t, *c)), reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, vmMethod), returnTypeSpec)),
|
|
|
|
byteArrayLength(t, methodSpec(t, vmMethod)) - 1 - returnTypeSpec);
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
PROTECT(t, returnType);
|
|
|
|
|
|
|
|
object exceptionTypes = local::resolveExceptionJTypes
|
|
|
|
(t, classLoader(t, jclassVmClass(t, *c)),
|
|
|
|
methodAddendum(t, vmMethod));
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
PROTECT(t, exceptionTypes);
|
|
|
|
|
|
|
|
object signature = t->m->classpath->makeString
|
|
|
|
(t, methodSpec(t, vmMethod), 0, byteArrayLength
|
|
|
|
(t, methodSpec(t, vmMethod)) - 1);
|
|
|
|
|
|
|
|
object annotationTable = methodAddendum(t, vmMethod) == 0
|
|
|
|
? 0 : addendumAnnotationTable(t, methodAddendum(t, vmMethod));
|
|
|
|
|
|
|
|
if (annotationTable) {
|
2010-11-26 19:41:31 +00:00
|
|
|
PROTECT(t, signature);
|
|
|
|
PROTECT(t, annotationTable);
|
|
|
|
|
|
|
|
object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c));
|
|
|
|
|
|
|
|
set(t, runtimeData, ClassRuntimeDataPool,
|
2010-09-10 21:05:29 +00:00
|
|
|
addendumPool(t, methodAddendum(t, vmMethod)));
|
|
|
|
}
|
|
|
|
|
|
|
|
object method = makeJmethod
|
|
|
|
(t, true, *c, i, name, returnType, parameterTypes, exceptionTypes,
|
|
|
|
methodFlags(t, vmMethod), signature, 0, annotationTable, 0, 0, 0, 0,
|
|
|
|
0, 0, 0);
|
|
|
|
|
|
|
|
assert(t, ai < objectArrayLength(t, array));
|
|
|
|
|
|
|
|
set(t, array, ArrayBody + ((ai++) * BytesPerWord), method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return makeLocalReference(t, array);
|
|
|
|
} else {
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, makeObjectArray(t, type(t, Machine::JmethodType), 0));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassDeclaredFields)(Thread* t, jclass c, jboolean publicOnly)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object table = classFieldTable(t, jclassVmClass(t, *c));
|
|
|
|
if (table) {
|
2010-09-14 16:49:41 +00:00
|
|
|
PROTECT(t, table);
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
object array = makeObjectArray
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, type(t, Machine::JfieldType),
|
2010-09-10 21:05:29 +00:00
|
|
|
local::countFields(t, jclassVmClass(t, *c), publicOnly));
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
unsigned ai = 0;
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
object vmField = arrayBody(t, table, i);
|
|
|
|
PROTECT(t, vmField);
|
|
|
|
|
|
|
|
if ((not publicOnly) or (fieldFlags(t, vmField) & ACC_PUBLIC)) {
|
|
|
|
object name = intern
|
|
|
|
(t, t->m->classpath->makeString
|
|
|
|
(t, fieldName(t, vmField), 0, byteArrayLength
|
|
|
|
(t, fieldName(t, vmField)) - 1));
|
|
|
|
PROTECT(t, name);
|
|
|
|
|
|
|
|
object type = local::resolveClassBySpec
|
|
|
|
(t, classLoader(t, jclassVmClass(t, *c)),
|
|
|
|
reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, fieldSpec(t, vmField), 0)),
|
|
|
|
byteArrayLength(t, fieldSpec(t, vmField)) - 1);
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
PROTECT(t, type);
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
type = getJClass(t, type);
|
|
|
|
|
|
|
|
object signature = t->m->classpath->makeString
|
|
|
|
(t, fieldSpec(t, vmField), 0, byteArrayLength
|
|
|
|
(t, fieldSpec(t, vmField)) - 1);
|
|
|
|
|
|
|
|
object annotationTable = fieldAddendum(t, vmField) == 0
|
|
|
|
? 0 : addendumAnnotationTable(t, fieldAddendum(t, vmField));
|
|
|
|
|
|
|
|
if (annotationTable) {
|
2010-11-26 19:41:31 +00:00
|
|
|
PROTECT(t, signature);
|
|
|
|
PROTECT(t, annotationTable);
|
|
|
|
|
|
|
|
object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c));
|
|
|
|
|
|
|
|
set(t, runtimeData, ClassRuntimeDataPool,
|
2010-12-01 03:25:48 +00:00
|
|
|
addendumPool(t, fieldAddendum(t, vmField)));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
object field = makeJfield
|
|
|
|
(t, true, *c, i, name, type, fieldFlags
|
|
|
|
(t, vmField), signature, 0, annotationTable, 0, 0, 0, 0, 0, 0);
|
|
|
|
|
|
|
|
assert(t, ai < objectArrayLength(t, array));
|
|
|
|
|
|
|
|
set(t, array, ArrayBody + ((ai++) * BytesPerWord), field);
|
|
|
|
}
|
|
|
|
}
|
2010-09-14 16:49:41 +00:00
|
|
|
assert(t, ai == objectArrayLength(t, array));
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
return makeLocalReference(t, array);
|
|
|
|
} else {
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, makeObjectArray(t, type(t, Machine::JfieldType), 0));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassDeclaredConstructors)(Thread* t, jclass c,
|
|
|
|
jboolean publicOnly)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object table = classMethodTable(t, jclassVmClass(t, *c));
|
|
|
|
if (table) {
|
2010-09-14 16:49:41 +00:00
|
|
|
PROTECT(t, table);
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
object array = makeObjectArray
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, type(t, Machine::JconstructorType),
|
2010-09-10 21:05:29 +00:00
|
|
|
local::countConstructors(t, jclassVmClass(t, *c), publicOnly));
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
unsigned ai = 0;
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
object vmMethod = arrayBody(t, table, i);
|
|
|
|
PROTECT(t, vmMethod);
|
|
|
|
|
|
|
|
if (((not publicOnly) or (methodFlags(t, vmMethod) & ACC_PUBLIC))
|
|
|
|
and strcmp(reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodName(t, vmMethod), 0)),
|
|
|
|
"<init>") == 0)
|
|
|
|
{
|
|
|
|
unsigned parameterCount;
|
|
|
|
unsigned returnTypeSpec;
|
|
|
|
object parameterTypes = local::resolveParameterJTypes
|
|
|
|
(t, classLoader(t, jclassVmClass(t, *c)), methodSpec(t, vmMethod),
|
|
|
|
¶meterCount, &returnTypeSpec);
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
PROTECT(t, parameterTypes);
|
|
|
|
|
|
|
|
object exceptionTypes = local::resolveExceptionJTypes
|
|
|
|
(t, classLoader(t, jclassVmClass(t, *c)),
|
|
|
|
methodAddendum(t, vmMethod));
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
PROTECT(t, exceptionTypes);
|
|
|
|
|
|
|
|
object signature = t->m->classpath->makeString
|
|
|
|
(t, methodSpec(t, vmMethod), 0, byteArrayLength
|
|
|
|
(t, methodSpec(t, vmMethod)) - 1);
|
|
|
|
|
|
|
|
object annotationTable = methodAddendum(t, vmMethod) == 0
|
|
|
|
? 0 : addendumAnnotationTable(t, methodAddendum(t, vmMethod));
|
|
|
|
|
|
|
|
if (annotationTable) {
|
2010-11-26 19:41:31 +00:00
|
|
|
PROTECT(t, signature);
|
|
|
|
PROTECT(t, annotationTable);
|
|
|
|
|
|
|
|
object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c));
|
|
|
|
|
|
|
|
set(t, runtimeData, ClassRuntimeDataPool,
|
2010-09-10 21:05:29 +00:00
|
|
|
addendumPool(t, methodAddendum(t, vmMethod)));
|
|
|
|
}
|
|
|
|
|
|
|
|
object method = makeJconstructor
|
|
|
|
(t, true, *c, i, parameterTypes, exceptionTypes, methodFlags
|
|
|
|
(t, vmMethod), signature, 0, annotationTable, 0, 0, 0, 0, 0);
|
|
|
|
|
|
|
|
assert(t, ai < objectArrayLength(t, array));
|
|
|
|
|
|
|
|
set(t, array, ArrayBody + ((ai++) * BytesPerWord), method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return makeLocalReference(t, array);
|
|
|
|
} else {
|
|
|
|
return makeLocalReference
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, makeObjectArray(t, type(t, Machine::JconstructorType), 0));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassAccessFlags)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-11-07 17:08:04 +00:00
|
|
|
return EXPORT(JVM_GetClassModifiers)(t, c);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_InvokeMethod)(Thread* t, jobject method, jobject instance,
|
2010-09-10 21:05:29 +00:00
|
|
|
jobjectArray arguments)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object vmMethod = arrayBody
|
|
|
|
(t, classMethodTable
|
|
|
|
(t, jclassVmClass(t, jmethodClazz(t, *method))),
|
|
|
|
jmethodSlot(t, *method));
|
|
|
|
|
2010-09-15 00:52:57 +00:00
|
|
|
if (methodFlags(t, vmMethod) & ACC_STATIC) {
|
|
|
|
instance = 0;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
object result;
|
|
|
|
if (arguments) {
|
|
|
|
result = t->m->processor->invokeArray
|
|
|
|
(t, vmMethod, instance ? *instance : 0, *arguments);
|
|
|
|
} else {
|
|
|
|
result = t->m->processor->invoke(t, vmMethod, instance ? *instance : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result ? makeLocalReference(t, result) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_NewInstanceFromConstructor)(Thread* t, jobject constructor,
|
2010-09-10 21:05:29 +00:00
|
|
|
jobjectArray arguments)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object instance = make
|
|
|
|
(t, jclassVmClass(t, jconstructorClazz(t, *constructor)));
|
|
|
|
PROTECT(t, instance);
|
|
|
|
|
|
|
|
object method = arrayBody
|
|
|
|
(t, classMethodTable
|
|
|
|
(t, jclassVmClass(t, jconstructorClazz(t, *constructor))),
|
|
|
|
jconstructorSlot(t, *constructor));
|
|
|
|
|
|
|
|
if (arguments) {
|
|
|
|
t->m->processor->invokeArray(t, method, instance, *arguments);
|
|
|
|
} else {
|
|
|
|
t->m->processor->invoke(t, method, instance);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return makeLocalReference(t, instance);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassConstantPool)(Thread* t, jclass c)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-11-26 19:41:31 +00:00
|
|
|
object vmClass = jclassVmClass(t, *c);
|
|
|
|
object addendum = classAddendum(t, vmClass);
|
|
|
|
object pool;
|
|
|
|
if (addendum) {
|
|
|
|
pool = addendumPool(t, addendum);
|
|
|
|
} else {
|
|
|
|
pool = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pool == 0) {
|
|
|
|
pool = classRuntimeDataPool(t, getClassRuntimeData(t, vmClass));
|
|
|
|
}
|
|
|
|
|
|
|
|
return makeLocalReference(t, makeConstantPool(t, pool));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetSize)(Thread* t, jobject, jobject pool)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
if (pool == 0) return 0;
|
|
|
|
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return singletonCount(t, *pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetClassAt)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetClassAtIfLoaded)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetMethodAt)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetMethodAtIfLoaded)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetFieldAt)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetFieldAtIfLoaded)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetMemberRefInfoAt)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetIntAt)(Thread* t, jobject, jobject pool, jint index)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
return singletonValue(t, *pool, index - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetLongAt)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jfloat JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetFloatAt)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jdouble JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetDoubleAt)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetStringAt)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetUTF8At)(Thread* t, jobject, jobject pool, jint index)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
object array = singletonObject(t, *pool, index - 1);
|
|
|
|
|
|
|
|
return makeLocalReference
|
|
|
|
(t, t->m->classpath->makeString
|
|
|
|
(t, array, 0, cast<uintptr_t>(array, BytesPerWord) - 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_DoPrivileged)
|
2010-09-10 21:05:29 +00:00
|
|
|
(Thread* t, jclass, jobject action, jobject, jboolean wrapException)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
// todo: cache these class and method lookups in the t->m->classpath
|
|
|
|
// object:
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
object privilegedAction = resolveClass
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, root(t, Machine::BootLoader), "java/security/PrivilegedAction");
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
object method;
|
|
|
|
if (instanceOf(t, privilegedAction, *action)) {
|
|
|
|
method = resolveMethod
|
|
|
|
(t, privilegedAction, "run", "()Ljava/lang/Object;");
|
|
|
|
} else {
|
|
|
|
object privilegedExceptionAction = resolveClass
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, root(t, Machine::BootLoader),
|
|
|
|
"java/security/PrivilegedExceptionAction");
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
method = resolveMethod
|
|
|
|
(t, privilegedExceptionAction, "run", "()Ljava/lang/Object;");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
object result = t->m->processor->invoke(t, method, *action);
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
return makeLocalReference(t, result);
|
|
|
|
} else {
|
|
|
|
if (wrapException and not
|
2010-09-14 16:49:41 +00:00
|
|
|
(instanceOf(t, type(t, Machine::ErrorType), t->exception)
|
|
|
|
or instanceOf(t, type(t, Machine::RuntimeExceptionType),
|
2010-09-10 21:05:29 +00:00
|
|
|
t->exception)))
|
|
|
|
{
|
|
|
|
object cause = t->exception;
|
|
|
|
PROTECT(t, cause);
|
|
|
|
|
|
|
|
t->exception = 0;
|
|
|
|
|
|
|
|
object paeClass = resolveClass
|
2010-09-14 16:49:41 +00:00
|
|
|
(t, root(t, Machine::BootLoader),
|
|
|
|
"java/security/PrivilegedActionException");
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
PROTECT(t, paeClass);
|
|
|
|
|
|
|
|
object paeConstructor = resolveMethod
|
|
|
|
(t, paeClass, "<init>", "(Ljava/lang/Exception;)V");
|
|
|
|
PROTECT(t, paeConstructor);
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
object result = make(t, paeClass);
|
|
|
|
PROTECT(t, result);
|
|
|
|
|
|
|
|
t->m->processor->invoke(t, paeConstructor, result, cause);
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
t->exception = result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetInheritedAccessControlContext)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetStackAccessControlContext)(Thread*, jclass)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_RegisterSignal)(jint, void*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_RaiseSignal)(jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_FindSignal)(const char*)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_DesiredAssertionStatus)(Thread*, jclass, jclass)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_AssertionStatusDirectives)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SupportsCX8)()
|
2010-09-10 23:47:23 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassNameUTF)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassCPTypes)(Thread*, jclass, unsigned char*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassCPEntriesCount)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassFieldsCount)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetClassMethodsCount)(Thread*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxExceptionIndexes)(Thread*, jclass, jint,
|
2010-09-10 21:05:29 +00:00
|
|
|
unsigned short*) { abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxExceptionsCount)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxByteCode)(Thread*, jclass, jint,
|
2010-09-10 21:05:29 +00:00
|
|
|
unsigned char*) { abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxByteCodeLength)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxExceptionTableEntry)(Thread*, jclass, jint,
|
2010-09-10 21:05:29 +00:00
|
|
|
jint,
|
2010-10-24 02:40:48 +00:00
|
|
|
local::JVM_ExceptionTableEntryType*)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxExceptionTableLength)(Thread*, jclass, int) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetFieldIxModifiers)(Thread*, jclass, int) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxModifiers)(Thread*, jclass, int) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxLocalsCount)(Thread*, jclass, int) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxArgsSize)(Thread*, jclass, int) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxMaxStack)(Thread*, jclass, int) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsConstructorIx)(Thread*, jclass, int) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxNameUTF)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetMethodIxSignatureUTF)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCPFieldNameUTF)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCPMethodNameUTF)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCPMethodSignatureUTF)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCPFieldSignatureUTF)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCPClassNameUTF)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCPFieldClassNameUTF)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT const char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCPMethodClassNameUTF)(Thread*, jclass, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCPFieldModifiers)(Thread*, jclass, int, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetCPMethodModifiers)(Thread*, jclass, int, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_ReleaseUTF)(const char*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_IsSameClassPackage)(Thread*, jclass, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetLastErrorString)(char* dst, int length)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
strncpy(dst, strerror(errno), length);
|
|
|
|
return strlen(dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT char* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_NativePath)(char* path)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Open)(const char* path, jint flags, jint mode)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-11-07 17:08:04 +00:00
|
|
|
return OPEN(path, flags, mode);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Close)(jint fd)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-11-07 17:08:04 +00:00
|
|
|
return CLOSE(fd);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Read)(jint fd, char* dst, jint length)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-11-07 17:08:04 +00:00
|
|
|
return READ(fd, dst, length);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Write)(jint fd, char* src, jint length)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
return WRITE(fd, src, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Available)(jint fd, jlong* result)
|
|
|
|
{
|
|
|
|
struct STAT buffer;
|
|
|
|
int n;
|
|
|
|
if (FSTAT(fd, &buffer) >= 0
|
|
|
|
and (S_ISCHR(buffer.st_mode)
|
|
|
|
or S_ISFIFO(buffer.st_mode)
|
|
|
|
or S_ISSOCK(buffer.st_mode))
|
|
|
|
and local::pipeAvailable(fd, &n))
|
|
|
|
{
|
|
|
|
*result = n;
|
|
|
|
return 1;
|
|
|
|
}
|
2010-09-23 14:49:36 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
int current = LSEEK(fd, 0, SEEK_CUR);
|
|
|
|
if (current == -1) return 0;
|
2010-09-10 23:47:23 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
int end = LSEEK(fd, 0, SEEK_END);
|
|
|
|
if (end == -1) return 0;
|
2010-09-10 23:47:23 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
if (LSEEK(fd, current, SEEK_SET) == -1) return 0;
|
2010-09-10 23:47:23 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
*result = end - current;
|
|
|
|
return 1;
|
2010-09-10 23:47:23 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Lseek)(jint fd, jlong offset, jint seek)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-11-07 17:08:04 +00:00
|
|
|
return LSEEK(fd, offset, seek);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SetLength)(jint, jlong) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Sync)(jint fd)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
2010-11-07 04:21:19 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
|
|
|
if (h == INVALID_HANDLE_VALUE) {
|
|
|
|
errno = EBADF;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FlushFileBuffers(h)) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
errno = EIO;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#else
|
2010-09-15 00:52:57 +00:00
|
|
|
return fsync(fd);
|
2010-11-07 04:21:19 +00:00
|
|
|
#endif
|
2010-09-15 00:52:57 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_InitializeSocketLibrary)()
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
static bool wsaInitialized = false;
|
|
|
|
if (not wsaInitialized) {
|
|
|
|
WSADATA data;
|
|
|
|
int r = WSAStartup(MAKEWORD(2, 2), &data);
|
|
|
|
if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
wsaInitialized = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Socket)(jint domain, jint type, jint protocol)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
return socket(domain, type, protocol);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SocketClose)(jint socket)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
return closesocket(socket);
|
|
|
|
#else
|
|
|
|
return close(socket);
|
|
|
|
#endif
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SocketShutdown)(jint socket, jint how)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
return shutdown(socket, how);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Recv)(jint socket, char* dst, jint count, jint flags)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
return recv(socket, dst, count, flags);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Send)(jint socket, char* src, jint count, jint flags)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
return send(socket, src, count, flags);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Timeout)(int, long) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Listen)(jint socket, jint count)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
return listen(socket, count);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Connect)(jint socket, sockaddr* address, jint addressLength)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
return connect(socket, address, addressLength);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Bind)(jint, struct sockaddr*, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_Accept)(jint socket, struct sockaddr* address, jint* addressLength)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
socklen_t length = *addressLength;
|
|
|
|
int r = accept(socket, address, &length);
|
|
|
|
*addressLength = length;
|
|
|
|
return r;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_RecvFrom)(jint, char*, int,
|
2010-09-10 21:05:29 +00:00
|
|
|
int, struct sockaddr*, int*) { abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SendTo)(jint, char*, int,
|
2010-09-10 21:05:29 +00:00
|
|
|
int, struct sockaddr*, int) { abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SocketAvailable)(jint, jint*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetSockName)(jint socket, struct sockaddr* address,
|
|
|
|
int* addressLength)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
|
|
|
socklen_t length = *addressLength;
|
|
|
|
int r = getsockname(socket, address, &length);
|
|
|
|
*addressLength = length;
|
|
|
|
return r;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetSockOpt)(jint, int, int, char*, int*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_SetSockOpt)(jint, int, int, const char*, int) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT struct protoent* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetProtoByName)(char*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT struct hostent* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetHostByAddr)(const char*, int, int) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT struct hostent* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetHostByName)(char*) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT int JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetHostName)(char* name, int length)
|
2010-09-17 01:43:27 +00:00
|
|
|
{
|
|
|
|
return gethostname(name, length);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_RawMonitorCreate)(void)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
System* s = local::globalMachine->system;
|
|
|
|
System::Monitor* lock;
|
|
|
|
if (s->success(s->make(&lock))) {
|
|
|
|
return lock;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_RawMonitorDestroy)(void* lock)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
static_cast<System::Monitor*>(lock)->dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_RawMonitorEnter)(void* lock)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
static_cast<System::Monitor*>(lock)->acquire
|
|
|
|
(static_cast<Thread*>
|
|
|
|
(local::globalMachine->localThread->get())->systemThread);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_RawMonitorExit)(void* lock)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
static_cast<System::Monitor*>(lock)->release
|
|
|
|
(static_cast<Thread*>
|
|
|
|
(local::globalMachine->localThread->get())->systemThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void* JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetManagement)(jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_InitAgentProperties)(Thread*, jobject) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetEnclosingMethodInfo)(JNIEnv*, jclass) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jintArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetThreadStateValues)(JNIEnv*, jint) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetThreadStateNames)(JNIEnv*, jint, jintArray) { abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2010-11-07 17:08:04 +00:00
|
|
|
EXPORT(JVM_GetVersionInfo)(JNIEnv*, local::jvm_version_info*, size_t)
|
|
|
|
{ abort(); }
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
EXPORT(JVM_CX8Field)(JNIEnv*, jobject*, jfieldID*, jlong, jlong)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT int
|
|
|
|
jio_vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
|
|
|
{
|
|
|
|
return vm::vsnprintf(dst, size, format, a);
|
|
|
|
}
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
extern "C" JNIEXPORT int
|
|
|
|
jio_vfprintf(FILE* stream, const char* format, va_list a)
|
|
|
|
{
|
|
|
|
return vfprintf(stream, format, a);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
2010-11-07 19:24:40 +00:00
|
|
|
extern "C" JNIEXPORT void* JNICALL
|
|
|
|
EXPORT(JVM_GetThreadInterruptEvent)()
|
|
|
|
{ abort(); }
|
|
|
|
|
|
|
|
namespace { HMODULE jvmHandle = 0; }
|
|
|
|
|
|
|
|
extern "C" int JDK_InitJvmHandle()
|
|
|
|
{
|
|
|
|
jvmHandle = GetModuleHandle(0);
|
|
|
|
return jvmHandle != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void* JDK_FindJvmEntry(const char* name)
|
|
|
|
{
|
|
|
|
return voidPointer(GetProcAddress(jvmHandle, name));
|
|
|
|
}
|
|
|
|
|
|
|
|
# ifdef AVIAN_OPENJDK_SRC
|
|
|
|
|
|
|
|
extern "C" char* findJavaTZ_md(const char*, const char*);
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_java_util_TimeZone_getSystemTimeZoneID
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
// On Windows, findJavaTZ_md loads tzmappings from the filesystem
|
|
|
|
// using fopen, so we have no opportunity to make it read straight
|
|
|
|
// from the embedded JAR file as with files read from Java code.
|
|
|
|
// Therefore, we must extract tzmappings to a temporary location
|
|
|
|
// before calling findJavaTZ_md. We could avoid this by
|
|
|
|
// implementing findJavaTZ_md ourselves from scratch, but that would
|
|
|
|
// be a lot of code to implement and maintain.
|
|
|
|
|
|
|
|
object country = reinterpret_cast<object>(arguments[1]);
|
|
|
|
|
|
|
|
RUNTIME_ARRAY(char, countryChars, stringLength(t, country) + 1);
|
|
|
|
stringChars(t, country, RUNTIME_ARRAY_BODY(countryChars));
|
|
|
|
|
|
|
|
local::MyClasspath* cp = static_cast<local::MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
local::EmbeddedFile ef(cp, cp->tzMappings, cp->tzMappingsLength);
|
|
|
|
if (ef.jar == 0 or ef.jarLength == 0 or ef.pathLength == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Finder* finder = local::getFinder(t, ef.jar, ef.jarLength);
|
|
|
|
if (finder == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
System::Region* r = finder->find(ef.path);
|
|
|
|
if (r == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RESOURCE(System::Region*, r, r->dispose());
|
|
|
|
|
|
|
|
char tmpPath[MAX_PATH + 1];
|
|
|
|
GetTempPathA(MAX_PATH, tmpPath);
|
|
|
|
|
|
|
|
char tmpDir[MAX_PATH + 1];
|
|
|
|
vm::snprintf(tmpDir, MAX_PATH, "%s/avian-tmp", tmpPath);
|
|
|
|
if (_mkdir(tmpDir) != 0 and errno != EEXIST) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RESOURCE(char*, tmpDir, rmdir(tmpDir));
|
|
|
|
|
|
|
|
char libDir[MAX_PATH + 1];
|
|
|
|
vm::snprintf(libDir, MAX_PATH, "%s/lib", tmpDir);
|
|
|
|
if (mkdir(libDir) != 0 and errno != EEXIST) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RESOURCE(char*, libDir, rmdir(libDir));
|
|
|
|
|
|
|
|
char file[MAX_PATH + 1];
|
|
|
|
vm::snprintf(file, MAX_PATH, "%s/tzmappings", libDir);
|
|
|
|
FILE* out = vm::fopen(file, "wb");
|
|
|
|
if (out == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RESOURCE(char*, file, unlink(file));
|
|
|
|
RESOURCE(FILE*, out, fclose(out));
|
|
|
|
|
|
|
|
if (fwrite(r->start(), 1, r->length(), out) != r->length()
|
|
|
|
or fflush(out) != 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* javaTZ = findJavaTZ_md(tmpDir, RUNTIME_ARRAY_BODY(countryChars));
|
|
|
|
if (javaTZ) {
|
|
|
|
object result = makeString(t, "%s", javaTZ);
|
|
|
|
free(javaTZ);
|
|
|
|
return reinterpret_cast<int64_t>(result);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# else // not AVIAN_OPENJDK_SRC
|
2010-11-07 17:08:04 +00:00
|
|
|
extern "C" JNIEXPORT int
|
|
|
|
jio_snprintf(char* dst, size_t size, const char* format, ...)
|
|
|
|
{
|
|
|
|
va_list a;
|
|
|
|
va_start(a, format);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
int r = jio_vsnprintf(dst, size, format, a);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
va_end(a);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT int
|
2010-11-07 17:08:04 +00:00
|
|
|
jio_fprintf(FILE* stream, const char* format, ...)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-11-07 17:08:04 +00:00
|
|
|
va_list a;
|
|
|
|
va_start(a, format);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
int r = jio_vfprintf(stream, format, a);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
va_end(a);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
return r;
|
|
|
|
}
|
2010-11-07 19:24:40 +00:00
|
|
|
# endif // not AVIAN_OPENJDK_SRC
|
|
|
|
#endif // PLATFORM_WINDOWS
|