2012-05-11 23:43:27 +00:00
|
|
|
/* Copyright (c) 2010-2012, Avian Contributors
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
|
|
for any purpose with or without fee is hereby granted, provided
|
|
|
|
that the above copyright notice and this permission notice appear
|
|
|
|
in all copies.
|
|
|
|
|
|
|
|
There is NO WARRANTY for this software. See license.txt for
|
|
|
|
details. */
|
|
|
|
|
2013-02-27 20:25:50 +00:00
|
|
|
#include "avian/machine.h"
|
|
|
|
#include "avian/classpath-common.h"
|
|
|
|
#include "avian/util.h"
|
|
|
|
#include "avian/process.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
|
2010-09-10 21:05:29 +00:00
|
|
|
# endif
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
# define O_RDONLY _O_RDONLY
|
|
|
|
|
2013-01-25 15:07:47 +00:00
|
|
|
# if (defined AVIAN_OPENJDK_SRC) \
|
|
|
|
|| ((defined __x86_64__) && (defined __MINGW32__))
|
2010-11-07 19:24:40 +00:00
|
|
|
# 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>
|
2011-03-15 19:27:36 +00:00
|
|
|
# include <limits.h>
|
2010-09-10 21:05:29 +00:00
|
|
|
# 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
|
|
|
|
|
2012-03-13 14:26:51 +00:00
|
|
|
#define JVM_EEXIST -100
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace local {
|
|
|
|
|
2011-04-10 03:17:15 +00:00
|
|
|
const int JMM_VERSION_1_0 = 0x20010000;
|
|
|
|
|
|
|
|
struct jmmOptionalSupport {
|
|
|
|
unsigned isLowMemoryDetectionSupported : 1;
|
|
|
|
unsigned isCompilationTimeMonitoringSupported : 1;
|
|
|
|
unsigned isThreadContentionMonitoringSupported : 1;
|
|
|
|
unsigned isCurrentThreadCpuTimeSupported : 1;
|
|
|
|
unsigned isOtherThreadCpuTimeSupported : 1;
|
|
|
|
unsigned isBootClassPathSupported : 1;
|
|
|
|
unsigned isObjectMonitorUsageSupported : 1;
|
|
|
|
unsigned isSynchronizerUsageSupported : 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef unsigned jmmLongAttribute;
|
|
|
|
typedef unsigned jmmBoolAttribute;
|
|
|
|
typedef unsigned jmmStatisticType;
|
|
|
|
typedef unsigned jmmThresholdType;
|
|
|
|
typedef unsigned jmmVMGlobalType;
|
|
|
|
typedef unsigned jmmVMGlobalOrigin;
|
|
|
|
|
|
|
|
struct jmmVMGlobal {
|
|
|
|
jstring name;
|
|
|
|
jvalue value;
|
|
|
|
jmmVMGlobalType type;
|
|
|
|
jmmVMGlobalOrigin origin;
|
|
|
|
unsigned writeable : 1;
|
|
|
|
unsigned external : 1;
|
|
|
|
unsigned reserved : 30;
|
|
|
|
void* reserved1;
|
|
|
|
void* reserved2;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct jmmExtAttributeInfo {
|
|
|
|
const char* name;
|
|
|
|
char type;
|
|
|
|
const char* description;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct jmmGCStat {
|
|
|
|
jlong gc_index;
|
|
|
|
jlong start_time;
|
|
|
|
jlong end_time;
|
|
|
|
jobjectArray usage_before_gc;
|
|
|
|
jobjectArray usage_after_gc;
|
|
|
|
jint gc_ext_attribute_values_size;
|
|
|
|
jvalue* gc_ext_attribute_values;
|
|
|
|
jint num_gc_ext_attributes;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct JmmInterface {
|
|
|
|
void* reserved1;
|
|
|
|
void* reserved2;
|
|
|
|
|
|
|
|
jint
|
|
|
|
(JNICALL *GetVersion)
|
|
|
|
(JNIEnv*);
|
|
|
|
|
|
|
|
jint
|
|
|
|
(JNICALL *GetOptionalSupport)
|
|
|
|
(JNIEnv*, jmmOptionalSupport*);
|
|
|
|
|
|
|
|
jobject
|
|
|
|
(JNICALL *GetInputArguments)
|
|
|
|
(JNIEnv*);
|
|
|
|
|
|
|
|
jint
|
|
|
|
(JNICALL *GetThreadInfo)
|
|
|
|
(JNIEnv*, jlongArray, jint, jobjectArray);
|
|
|
|
|
|
|
|
jobjectArray
|
|
|
|
(JNICALL *GetInputArgumentArray)
|
|
|
|
(JNIEnv*);
|
|
|
|
|
|
|
|
jobjectArray
|
|
|
|
(JNICALL *GetMemoryPools)
|
|
|
|
(JNIEnv*, jobject);
|
|
|
|
|
|
|
|
jobjectArray
|
|
|
|
(JNICALL *GetMemoryManagers)
|
|
|
|
(JNIEnv*, jobject);
|
|
|
|
|
|
|
|
jobject
|
|
|
|
(JNICALL *GetMemoryPoolUsage)
|
|
|
|
(JNIEnv*, jobject);
|
|
|
|
|
|
|
|
jobject
|
|
|
|
(JNICALL *GetPeakMemoryPoolUsage)
|
|
|
|
(JNIEnv*, jobject);
|
|
|
|
|
|
|
|
void* reserved4;
|
|
|
|
|
|
|
|
jobject
|
|
|
|
(JNICALL *GetMemoryUsage)
|
|
|
|
(JNIEnv*, jboolean);
|
|
|
|
|
|
|
|
jlong
|
|
|
|
(JNICALL *GetLongAttribute)
|
|
|
|
(JNIEnv*, jobject, jmmLongAttribute);
|
|
|
|
|
|
|
|
jboolean (JNICALL *GetBoolAttribute)
|
|
|
|
(JNIEnv*, jmmBoolAttribute);
|
|
|
|
|
|
|
|
jboolean
|
|
|
|
(JNICALL *SetBoolAttribute)
|
|
|
|
(JNIEnv*, jmmBoolAttribute, jboolean);
|
|
|
|
|
|
|
|
jint
|
|
|
|
(JNICALL *GetLongAttributes)
|
|
|
|
(JNIEnv*, jobject, jmmLongAttribute*, jint, jlong*);
|
|
|
|
|
|
|
|
jobjectArray
|
|
|
|
(JNICALL *FindCircularBlockedThreads)
|
|
|
|
(JNIEnv*);
|
|
|
|
|
|
|
|
jlong
|
|
|
|
(JNICALL *GetThreadCpuTime)
|
|
|
|
(JNIEnv*, jlong);
|
|
|
|
|
|
|
|
jobjectArray
|
|
|
|
(JNICALL *GetVMGlobalNames)
|
|
|
|
(JNIEnv*);
|
|
|
|
|
|
|
|
jint
|
|
|
|
(JNICALL *GetVMGlobals)
|
|
|
|
(JNIEnv*, jobjectArray, jmmVMGlobal*, jint);
|
|
|
|
|
|
|
|
jint
|
|
|
|
(JNICALL *GetInternalThreadTimes)
|
|
|
|
(JNIEnv*, jobjectArray, jlongArray);
|
|
|
|
|
|
|
|
jboolean
|
|
|
|
(JNICALL *ResetStatistic)
|
|
|
|
(JNIEnv*, jvalue, jmmStatisticType);
|
|
|
|
|
|
|
|
void
|
|
|
|
(JNICALL *SetPoolSensor)
|
|
|
|
(JNIEnv*, jobject, jmmThresholdType, jobject);
|
|
|
|
|
|
|
|
jlong
|
|
|
|
(JNICALL *SetPoolThreshold)
|
|
|
|
(JNIEnv*, jobject, jmmThresholdType, jlong);
|
|
|
|
|
|
|
|
jobject
|
|
|
|
(JNICALL *GetPoolCollectionUsage)
|
|
|
|
(JNIEnv*, jobject);
|
|
|
|
|
|
|
|
jint
|
|
|
|
(JNICALL *GetGCExtAttributeInfo)
|
|
|
|
(JNIEnv*, jobject, jmmExtAttributeInfo*, jint);
|
|
|
|
|
|
|
|
void
|
|
|
|
(JNICALL *GetLastGCStat)
|
|
|
|
(JNIEnv*, jobject, jmmGCStat*);
|
|
|
|
|
|
|
|
jlong
|
|
|
|
(JNICALL *GetThreadCpuTimeWithKind)
|
|
|
|
(JNIEnv*, jlong, jboolean);
|
|
|
|
|
|
|
|
void* reserved5;
|
|
|
|
|
|
|
|
jint
|
|
|
|
(JNICALL *DumpHeap0)
|
|
|
|
(JNIEnv*, jstring, jboolean);
|
|
|
|
|
|
|
|
jobjectArray
|
|
|
|
(JNICALL *FindDeadlocks)
|
|
|
|
(JNIEnv*, jboolean);
|
|
|
|
|
|
|
|
void
|
|
|
|
(JNICALL *SetVMGlobal)
|
|
|
|
(JNIEnv*, jstring, jvalue );
|
|
|
|
|
|
|
|
void* reserved6;
|
|
|
|
|
|
|
|
jobjectArray
|
|
|
|
(JNICALL *DumpThreads)
|
|
|
|
(JNIEnv*, jlongArray, jboolean, jboolean);
|
|
|
|
};
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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)
|
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, name));
|
2010-09-10 21:05:29 +00:00
|
|
|
replace('/', '.', RUNTIME_ARRAY_BODY(s),
|
|
|
|
reinterpret_cast<char*>(&byteArrayBody(t, name, 0)));
|
|
|
|
|
2013-02-22 21:20:09 +00:00
|
|
|
return makeString(t, "%s", RUNTIME_ARRAY_BODY(s));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2012-12-19 19:39:33 +00:00
|
|
|
object
|
|
|
|
makeJmethod(Thread* t, object vmMethod, int index = -1);
|
|
|
|
|
|
|
|
object
|
|
|
|
makeJconstructor(Thread* t, object vmMethod, int index = -1);
|
|
|
|
|
|
|
|
object
|
|
|
|
makeJfield(Thread* t, object vmField, int index = -1);
|
|
|
|
|
2010-11-04 17:02:09 +00:00
|
|
|
void
|
2013-03-15 19:28:01 +00:00
|
|
|
interceptFileOperations(Thread*, bool);
|
2010-11-04 17:02:09 +00:00
|
|
|
|
2012-05-02 17:41:36 +00:00
|
|
|
void
|
|
|
|
clearInterrupted(Thread*);
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
class MyClasspath : public Classpath {
|
|
|
|
public:
|
2010-11-05 19:18:28 +00:00
|
|
|
MyClasspath(System* s, Allocator* allocator, const char* javaHome,
|
|
|
|
const char* embedPrefix):
|
2011-08-06 00:06:29 +00:00
|
|
|
allocator(allocator), ranNetOnLoad(0), ranManagementOnLoad(0)
|
2010-09-20 23:31:23 +00:00
|
|
|
{
|
|
|
|
class StringBuilder {
|
|
|
|
public:
|
2012-10-03 15:43:51 +00:00
|
|
|
StringBuilder(System* s, Allocator* allocator):
|
|
|
|
s(s),
|
|
|
|
allocator(allocator),
|
|
|
|
bufferSize(1024),
|
|
|
|
buffer(static_cast<char*>(allocator->allocate(bufferSize))),
|
|
|
|
offset(0)
|
2010-09-20 23:31:23 +00:00
|
|
|
{ }
|
|
|
|
|
2012-10-03 15:43:51 +00:00
|
|
|
void ensure(unsigned capacity) {
|
|
|
|
if (capacity > bufferSize) {
|
|
|
|
unsigned size = max(bufferSize * 2, capacity);
|
|
|
|
char* b = static_cast<char*>(allocator->allocate(size));
|
|
|
|
|
|
|
|
if (offset) {
|
|
|
|
memcpy(b, buffer, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
allocator->free(buffer, bufferSize);
|
|
|
|
|
|
|
|
buffer = b;
|
|
|
|
bufferSize = size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-20 23:31:23 +00:00
|
|
|
void append(const char* append) {
|
|
|
|
unsigned length = strlen(append);
|
2012-10-03 15:43:51 +00:00
|
|
|
ensure(offset + length + 1);
|
2010-09-20 23:31:23 +00:00
|
|
|
|
2012-10-03 15:43:51 +00:00
|
|
|
strncpy(buffer + offset, append, length + 1);
|
2010-09-20 23:31:23 +00:00
|
|
|
|
2012-10-03 15:43:51 +00:00
|
|
|
offset += length;
|
2010-09-20 23:31:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void append(char c) {
|
2012-10-03 15:43:51 +00:00
|
|
|
ensure(2);
|
2010-09-20 23:31:23 +00:00
|
|
|
|
2012-10-03 15:43:51 +00:00
|
|
|
buffer[offset] = c;
|
|
|
|
buffer[offset + 1] = 0;
|
2010-09-20 23:31:23 +00:00
|
|
|
|
2012-10-03 15:43:51 +00:00
|
|
|
++ offset;
|
2010-09-20 23:31:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
System* s;
|
2012-10-03 15:43:51 +00:00
|
|
|
Allocator* allocator;
|
|
|
|
unsigned bufferSize;
|
|
|
|
char* buffer;
|
|
|
|
unsigned offset;
|
|
|
|
} sb(s, allocator);
|
2010-09-20 23:31:23 +00:00
|
|
|
|
2012-10-03 15:43:51 +00:00
|
|
|
unsigned javaHomeOffset = sb.offset;
|
2010-09-20 23:31:23 +00:00
|
|
|
sb.append(javaHome);
|
|
|
|
sb.append('\0');
|
|
|
|
|
2012-10-03 15:43:51 +00:00
|
|
|
unsigned classpathOffset = sb.offset;
|
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);
|
2011-03-04 23:55:31 +00:00
|
|
|
sb.append("/lib/ext/sunjce_provider.jar");
|
|
|
|
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');
|
|
|
|
|
2012-10-03 15:43:51 +00:00
|
|
|
unsigned libraryPathOffset = sb.offset;
|
2010-09-20 23:31:23 +00:00
|
|
|
sb.append(javaHome);
|
2010-11-07 17:08:04 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
2012-12-20 19:25:13 +00:00
|
|
|
# define LIB_DIR "/bin"
|
2012-03-16 17:01:20 +00:00
|
|
|
#elif defined __APPLE__
|
2012-12-20 19:25:13 +00:00
|
|
|
# define LIB_DIR "/lib"
|
2010-11-07 17:08:04 +00:00
|
|
|
#elif defined ARCH_x86_64
|
2012-12-20 19:25:13 +00:00
|
|
|
# define LIB_DIR "/lib/amd64"
|
2012-08-04 13:31:54 +00:00
|
|
|
#elif defined ARCH_arm
|
2012-12-20 19:25:13 +00:00
|
|
|
# define LIB_DIR "/lib/arm"
|
2010-09-20 23:31:23 +00:00
|
|
|
#else
|
2010-10-24 02:40:48 +00:00
|
|
|
// todo: handle other architectures
|
2012-12-20 19:25:13 +00:00
|
|
|
# define LIB_DIR "/lib/i386"
|
2010-09-20 23:31:23 +00:00
|
|
|
#endif
|
2013-01-25 15:07:47 +00:00
|
|
|
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
sb.append(LIB_DIR);
|
|
|
|
#else
|
2012-12-20 19:25:13 +00:00
|
|
|
sb.append(LIB_DIR ":");
|
|
|
|
sb.append(javaHome);
|
|
|
|
sb.append(LIB_DIR "/xawt");
|
2013-01-25 15:07:47 +00:00
|
|
|
#endif
|
2010-11-04 17:02:09 +00:00
|
|
|
sb.append('\0');
|
2012-10-03 15:43:51 +00:00
|
|
|
|
|
|
|
unsigned tzMappingsOffset = sb.offset;
|
2010-11-07 19:24:40 +00:00
|
|
|
sb.append(javaHome);
|
|
|
|
sb.append("/lib/tzmappings");
|
2012-10-03 15:43:51 +00:00
|
|
|
this->tzMappingsLength = sb.offset - tzMappingsOffset;
|
2010-11-07 19:24:40 +00:00
|
|
|
sb.append('\0');
|
2010-11-05 19:18:28 +00:00
|
|
|
|
2012-10-03 15:43:51 +00:00
|
|
|
unsigned embedPrefixOffset = sb.offset;
|
2010-11-05 19:18:28 +00:00
|
|
|
sb.append(embedPrefix);
|
2012-10-03 15:43:51 +00:00
|
|
|
this->embedPrefixLength = sb.offset - embedPrefixOffset;
|
|
|
|
|
|
|
|
this->javaHome = sb.buffer + javaHomeOffset;
|
|
|
|
this->classpath = sb.buffer + classpathOffset;
|
|
|
|
this->libraryPath = sb.buffer + libraryPathOffset;
|
|
|
|
this->tzMappings = sb.buffer + tzMappingsOffset;
|
|
|
|
this->embedPrefix = sb.buffer + embedPrefixOffset;
|
|
|
|
this->buffer = sb.buffer;
|
|
|
|
this->bufferSize = sb.bufferSize;
|
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_));
|
2012-03-11 22:26:46 +00:00
|
|
|
PROTECT(t, name);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2012-03-11 22:26:46 +00:00
|
|
|
object c = allocate(t, FixedSizeOfJclass, true);
|
|
|
|
setObjectClass(t, c, type(t, Machine::JclassType));
|
|
|
|
set(t, c, JclassName, name);
|
|
|
|
set(t, c, JclassVmClass, class_);
|
|
|
|
|
|
|
|
return c;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2013-04-10 00:44:54 +00:00
|
|
|
if (byteArrayBody(t, array, offset + i) & 0x80) {
|
|
|
|
object constructor = resolveMethod
|
|
|
|
(t, type(t, Machine::StringType), "<init>",
|
|
|
|
"([BIILjava/lang/String;)V");
|
|
|
|
PROTECT(t, constructor);
|
|
|
|
|
|
|
|
object utf8 = vm::makeString(t, "UTF8");
|
|
|
|
PROTECT(t, utf8);
|
|
|
|
|
|
|
|
object s = makeNew(t, type(t, Machine::StringType));
|
|
|
|
PROTECT(t, s);
|
|
|
|
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, constructor, s, array, offset, length, utf8);
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
2013-02-03 21:09:29 +00:00
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
charArrayBody(t, charArray, i) = byteArrayBody(t, array, offset + i);
|
|
|
|
}
|
|
|
|
|
|
|
|
array = charArray;
|
2011-03-18 03:42:15 +00:00
|
|
|
} else {
|
|
|
|
expect(t, objectClass(t, array) == type(t, Machine::CharArrayType));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
2011-03-18 03:42:15 +00:00
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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;
|
2011-03-27 01:01:48 +00:00
|
|
|
threadContextClassLoader(t, thread) = root(t, Machine::AppLoader);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-11-27 23:27:30 +00:00
|
|
|
PROTECT(t, thread);
|
|
|
|
|
2011-04-01 00:58:59 +00:00
|
|
|
object blockerLock = makeJobject(t);
|
|
|
|
set(t, thread, ThreadBlockerLock, blockerLock);
|
|
|
|
|
2010-11-27 23:27:30 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-12-19 19:39:33 +00:00
|
|
|
virtual object
|
|
|
|
makeJMethod(Thread* t, object vmMethod)
|
|
|
|
{
|
|
|
|
PROTECT(t, vmMethod);
|
|
|
|
|
|
|
|
return byteArrayBody(t, methodName(t, vmMethod), 0) == '<'
|
|
|
|
? makeJconstructor(t, vmMethod)
|
|
|
|
: makeJmethod(t, vmMethod);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
|
|
|
getVMMethod(Thread* t, object jmethod)
|
|
|
|
{
|
|
|
|
return objectClass(t, jmethod) == type(t, Machine::JmethodType)
|
|
|
|
? arrayBody
|
|
|
|
(t, classMethodTable
|
|
|
|
(t, jclassVmClass(t, jmethodClazz(t, jmethod))),
|
|
|
|
jmethodSlot(t, jmethod))
|
|
|
|
: arrayBody
|
|
|
|
(t, classMethodTable
|
|
|
|
(t, jclassVmClass(t, jconstructorClazz(t, jmethod))),
|
|
|
|
jconstructorSlot(t, jmethod));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
|
|
|
makeJField(Thread* t, object vmField)
|
|
|
|
{
|
|
|
|
return makeJfield(t, vmField);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
|
|
|
getVMField(Thread* t, object jfield)
|
|
|
|
{
|
|
|
|
return arrayBody
|
|
|
|
(t, classFieldTable
|
|
|
|
(t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield));
|
|
|
|
}
|
|
|
|
|
2012-05-02 17:41:36 +00:00
|
|
|
virtual void
|
|
|
|
clearInterrupted(Thread* t)
|
|
|
|
{
|
|
|
|
local::clearInterrupted(t);
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
virtual void
|
|
|
|
runThread(Thread* t)
|
|
|
|
{
|
2013-02-03 22:18:32 +00:00
|
|
|
// force monitor creation so we don't get an OutOfMemory error
|
|
|
|
// later when we try to acquire it:
|
|
|
|
objectMonitor(t, t->javaThread, true);
|
|
|
|
|
|
|
|
THREAD_RESOURCE0(t, {
|
|
|
|
vm::acquire(t, t->javaThread);
|
|
|
|
t->flags &= ~Thread::ActiveFlag;
|
|
|
|
vm::notifyAll(t, t->javaThread);
|
|
|
|
vm::release(t, t->javaThread);
|
2013-03-05 16:06:19 +00:00
|
|
|
|
2013-03-15 19:28:01 +00:00
|
|
|
object e = t->exception;
|
|
|
|
PROTECT(t, e);
|
|
|
|
|
|
|
|
t->exception = 0;
|
|
|
|
|
2013-03-05 16:06:19 +00:00
|
|
|
t->m->processor->invoke
|
|
|
|
(t, root(t, Machine::ThreadTerminated),
|
|
|
|
threadGroup(t, t->javaThread), t->javaThread);
|
2013-03-15 19:28:01 +00:00
|
|
|
|
|
|
|
t->exception = e;
|
2013-02-03 22:18:32 +00:00
|
|
|
});
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
t->m->processor->invoke(t, method, t->javaThread);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2011-04-10 17:26:44 +00:00
|
|
|
virtual void
|
|
|
|
resolveNative(Thread* t, object method)
|
|
|
|
{
|
2012-08-06 01:31:20 +00:00
|
|
|
if (strcmp(reinterpret_cast<const int8_t*>("sun/font/SunFontManager"),
|
2011-04-10 17:26:44 +00:00
|
|
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0)) == 0
|
|
|
|
and strcmp(reinterpret_cast<const int8_t*>("initIDs"),
|
|
|
|
&byteArrayBody(t, methodName(t, method), 0)) == 0
|
|
|
|
and strcmp(reinterpret_cast<const int8_t*>("()V"),
|
|
|
|
&byteArrayBody(t, methodSpec(t, method), 0)) == 0)
|
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
expect(t, loadLibrary(t, libraryPath, "fontmanager", true, true));
|
|
|
|
}
|
|
|
|
|
|
|
|
vm::resolveNative(t, method);
|
|
|
|
}
|
|
|
|
|
2013-03-15 19:28:01 +00:00
|
|
|
virtual void
|
|
|
|
interceptMethods(Thread* t UNUSED)
|
|
|
|
{
|
|
|
|
#ifdef AVIAN_OPENJDK_SRC
|
|
|
|
interceptFileOperations(t, false);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-02-22 21:41:24 +00:00
|
|
|
virtual void
|
2013-02-27 19:10:10 +00:00
|
|
|
preBoot(Thread*)
|
2013-02-22 21:41:24 +00:00
|
|
|
{
|
|
|
|
// ignore
|
|
|
|
}
|
|
|
|
|
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)));
|
|
|
|
|
2013-03-05 16:06:19 +00:00
|
|
|
setRoot(t, Machine::ThreadTerminated, resolveMethod
|
|
|
|
(t, root(t, Machine::BootLoader), "java/lang/ThreadGroup",
|
|
|
|
"threadTerminated", "(Ljava/lang/Thread;)V"));
|
|
|
|
|
2010-11-04 17:02:09 +00:00
|
|
|
#ifdef AVIAN_OPENJDK_SRC
|
2013-03-15 19:28:01 +00:00
|
|
|
interceptFileOperations(t, true);
|
2010-11-04 17:02:09 +00:00
|
|
|
#else // not AVIAN_OPENJDK_SRC
|
2011-04-10 17:26:44 +00:00
|
|
|
expect(t, loadLibrary(t, libraryPath, "verify", true, true));
|
|
|
|
expect(t, loadLibrary(t, libraryPath, "java", true, true));
|
2013-01-25 15:07:47 +00:00
|
|
|
# ifndef PLATFORM_WINDOWS
|
2013-02-27 18:34:43 +00:00
|
|
|
loadLibrary(t, libraryPath, "mawt", true, true, false);
|
2013-01-25 15:07:47 +00:00
|
|
|
# endif
|
2010-11-04 17:02:09 +00:00
|
|
|
#endif // not AVIAN_OPENJDK_SRC
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2012-06-11 23:30:22 +00:00
|
|
|
{ object assertionLock = resolveField
|
|
|
|
(t, type(t, Machine::ClassLoaderType), "assertionLock",
|
|
|
|
"Ljava/lang/Object;");
|
|
|
|
|
|
|
|
set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock),
|
|
|
|
root(t, Machine::BootLoader));
|
|
|
|
}
|
|
|
|
|
2012-02-21 00:38:41 +00:00
|
|
|
{ object class_ = resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader), "java/util/Properties", true,
|
|
|
|
Machine::NoClassDefFoundErrorType);
|
2010-12-27 22:55:23 +00:00
|
|
|
|
2012-02-21 00:38:41 +00:00
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
object instance = makeNew(t, class_);
|
|
|
|
|
|
|
|
PROTECT(t, instance);
|
|
|
|
|
|
|
|
object constructor = resolveMethod(t, class_, "<init>", "()V");
|
|
|
|
|
|
|
|
t->m->processor->invoke(t, constructor, instance);
|
|
|
|
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, root(t, Machine::BootLoader), "java/lang/System",
|
|
|
|
"setProperties", "(Ljava/util/Properties;)V", 0, instance);
|
|
|
|
}
|
|
|
|
|
|
|
|
{ object constructor = resolveMethod
|
|
|
|
(t, type(t, Machine::ClassLoaderType), "<init>",
|
|
|
|
"(Ljava/lang/ClassLoader;)V");
|
|
|
|
|
|
|
|
PROTECT(t, constructor);
|
|
|
|
|
|
|
|
t->m->processor->invoke(t, constructor, root(t, Machine::BootLoader), 0);
|
|
|
|
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, constructor, root(t, Machine::AppLoader),
|
|
|
|
root(t, Machine::BootLoader));
|
|
|
|
}
|
|
|
|
|
|
|
|
{ object scl = resolveField
|
|
|
|
(t, type(t, Machine::ClassLoaderType), "scl",
|
|
|
|
"Ljava/lang/ClassLoader;");
|
|
|
|
|
|
|
|
PROTECT(t, scl);
|
|
|
|
|
|
|
|
object sclSet = resolveField
|
|
|
|
(t, type(t, Machine::ClassLoaderType), "sclSet", "Z");
|
|
|
|
|
|
|
|
set(t, classStaticTable(t, type(t, Machine::ClassLoaderType)),
|
|
|
|
fieldOffset(t, scl), root(t, Machine::AppLoader));
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<uint8_t>(classStaticTable(t, type(t, Machine::ClassLoaderType)),
|
2012-02-21 00:38:41 +00:00
|
|
|
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);
|
2012-08-30 00:27:37 +00:00
|
|
|
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, root(t, Machine::BootLoader), "sun/misc/Launcher",
|
|
|
|
"getLauncher", "()Lsun/misc/Launcher;", 0);
|
|
|
|
|
|
|
|
set(t, t->javaThread, ThreadContextClassLoader,
|
|
|
|
root(t, Machine::AppLoader));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2010-09-20 23:31:23 +00:00
|
|
|
virtual const char*
|
|
|
|
bootClasspath()
|
|
|
|
{
|
|
|
|
return classpath;
|
|
|
|
}
|
|
|
|
|
2012-09-24 23:43:34 +00:00
|
|
|
virtual void
|
|
|
|
updatePackageMap(Thread* t, object class_)
|
|
|
|
{
|
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
if (root(t, Machine::PackageMap) == 0) {
|
|
|
|
setRoot(t, Machine::PackageMap, makeHashMap(t, 0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
object className = vm::className(t, class_);
|
|
|
|
if ('[' != byteArrayBody(t, className, 0)) {
|
|
|
|
THREAD_RUNTIME_ARRAY
|
|
|
|
(t, char, packageName, byteArrayLength(t, className));
|
|
|
|
|
|
|
|
char* s = reinterpret_cast<char*>(&byteArrayBody(t, className, 0));
|
|
|
|
char* p = strrchr(s, '/');
|
|
|
|
|
|
|
|
if (p) {
|
|
|
|
int length = (p - s) + 1;
|
|
|
|
memcpy(RUNTIME_ARRAY_BODY(packageName),
|
|
|
|
&byteArrayBody(t, className, 0),
|
|
|
|
length);
|
|
|
|
RUNTIME_ARRAY_BODY(packageName)[length] = 0;
|
|
|
|
|
2013-02-22 21:20:09 +00:00
|
|
|
object key = vm::makeByteArray
|
|
|
|
(t, "%s", RUNTIME_ARRAY_BODY(packageName));
|
2013-02-04 03:29:24 +00:00
|
|
|
PROTECT(t, key);
|
2012-09-24 23:43:34 +00:00
|
|
|
|
|
|
|
hashMapRemove
|
|
|
|
(t, root(t, Machine::PackageMap), key, byteArrayHash,
|
|
|
|
byteArrayEqual);
|
|
|
|
|
|
|
|
object source = classSource(t, class_);
|
2013-01-24 19:12:00 +00:00
|
|
|
if (source) {
|
|
|
|
// note that we strip the "file:" prefix, since
|
|
|
|
// Package.defineSystemPackage expects an unadorned
|
|
|
|
// filename:
|
|
|
|
const unsigned PrefixLength = 5;
|
|
|
|
unsigned sourceNameLength = byteArrayLength(t, source)
|
|
|
|
- PrefixLength;
|
|
|
|
THREAD_RUNTIME_ARRAY(t, char, sourceName, sourceNameLength);
|
|
|
|
memcpy(RUNTIME_ARRAY_BODY(sourceName),
|
|
|
|
&byteArrayBody(t, source, PrefixLength),
|
|
|
|
sourceNameLength);
|
|
|
|
|
2013-02-22 21:20:09 +00:00
|
|
|
source = vm::makeByteArray(t, "%s", RUNTIME_ARRAY_BODY(sourceName));
|
2013-01-24 19:12:00 +00:00
|
|
|
} else {
|
2012-09-24 23:43:34 +00:00
|
|
|
source = vm::makeByteArray(t, "avian-dummy-package-source");
|
|
|
|
}
|
|
|
|
|
|
|
|
hashMapInsert
|
|
|
|
(t, root(t, Machine::PackageMap), key, source, byteArrayHash);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-22 21:41:24 +00:00
|
|
|
virtual object
|
|
|
|
makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
|
|
|
{
|
|
|
|
object c = resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader), "java/nio/DirectByteBuffer");
|
|
|
|
PROTECT(t, c);
|
|
|
|
|
|
|
|
object instance = makeNew(t, c);
|
|
|
|
PROTECT(t, instance);
|
|
|
|
|
|
|
|
object constructor = resolveMethod(t, c, "<init>", "(JI)V");
|
|
|
|
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, constructor, instance, reinterpret_cast<int64_t>(p),
|
|
|
|
static_cast<int32_t>(capacity));
|
|
|
|
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void*
|
|
|
|
getDirectBufferAddress(Thread* t, object b)
|
|
|
|
{
|
|
|
|
PROTECT(t, b);
|
|
|
|
|
|
|
|
object field = resolveField(t, objectClass(t, b), "address", "J");
|
|
|
|
|
|
|
|
return reinterpret_cast<void*>
|
|
|
|
(fieldAtOffset<int64_t>(b, fieldOffset(t, field)));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual int64_t
|
|
|
|
getDirectBufferCapacity(Thread* t, object b)
|
|
|
|
{
|
|
|
|
PROTECT(t, b);
|
|
|
|
|
|
|
|
object field = resolveField
|
|
|
|
(t, objectClass(t, b), "capacity", "I");
|
|
|
|
|
|
|
|
return fieldAtOffset<int32_t>(b, fieldOffset(t, field));
|
|
|
|
}
|
|
|
|
|
2013-03-05 22:43:49 +00:00
|
|
|
virtual bool
|
|
|
|
canTailCall(Thread* t, object, object calleeClassName,
|
|
|
|
object calleeMethodName, object)
|
|
|
|
{
|
|
|
|
// we can't tail call System.loadLibrary or Runtime.loadLibrary
|
|
|
|
// due to their use of System.getCallerClass, which gets confused
|
|
|
|
// if we elide stack frames.
|
|
|
|
|
|
|
|
return (strcmp("loadLibrary", reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, calleeMethodName, 0)))
|
|
|
|
or (strcmp("java/lang/System", reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, calleeClassName, 0)))
|
|
|
|
and strcmp("java/lang/Runtime", reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, calleeClassName, 0)))))
|
|
|
|
|
|
|
|
// and we can't tail call Reflection.getCallerClass because the
|
|
|
|
// number of stack frames will be wrong
|
|
|
|
|
|
|
|
and (strcmp("getCallerClass", reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, calleeMethodName, 0)))
|
|
|
|
or strcmp("sun/reflect/Reflection", reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, calleeClassName, 0))));
|
|
|
|
}
|
|
|
|
|
2013-04-19 19:00:47 +00:00
|
|
|
virtual void
|
|
|
|
shutDown(Thread* t)
|
|
|
|
{
|
|
|
|
object c = resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader), "java/lang/Shutdown", false);
|
|
|
|
|
|
|
|
if (c) {
|
|
|
|
object m = findMethodOrNull(t, c, "shutdown", "()V");
|
|
|
|
|
|
|
|
if (m) {
|
|
|
|
t->m->processor->invoke(t, m, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
virtual void
|
|
|
|
dispose()
|
2010-11-05 19:18:28 +00:00
|
|
|
{
|
2012-10-03 15:43:51 +00:00
|
|
|
allocator->free(buffer, bufferSize);
|
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;
|
2012-10-03 15:43:51 +00:00
|
|
|
char* buffer;
|
|
|
|
unsigned bufferSize;
|
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;
|
2011-03-04 23:55:31 +00:00
|
|
|
unsigned zipFileJzfileField;
|
|
|
|
unsigned zipEntryNameField;
|
|
|
|
unsigned zipEntryTimeField;
|
|
|
|
unsigned zipEntryCrcField;
|
|
|
|
unsigned zipEntrySizeField;
|
|
|
|
unsigned zipEntryCsizeField;
|
|
|
|
unsigned zipEntryMethodField;
|
2010-12-09 04:38:16 +00:00
|
|
|
bool ranNetOnLoad;
|
2011-08-06 00:06:29 +00:00
|
|
|
bool ranManagementOnLoad;
|
2011-04-10 03:17:15 +00:00
|
|
|
JmmInterface jmmInterface;
|
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-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]);
|
2013-02-11 00:38:51 +00:00
|
|
|
object path = fieldAtOffset<object>(file, cp->filePathField);
|
2010-11-05 19:18:28 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1);
|
2010-11-05 19:18:28 +00:00
|
|
|
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 {
|
2010-12-27 22:55:23 +00:00
|
|
|
return intValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
reinterpret_cast<object>(arguments[0]), file));
|
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];
|
2013-02-11 00:38:51 +00:00
|
|
|
object path = fieldAtOffset<object>(file, cp->filePathField);
|
2010-12-01 20:40:43 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1);
|
2010-12-01 20:40:43 +00:00
|
|
|
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 {
|
2011-02-12 04:13:11 +00:00
|
|
|
return intValue
|
2010-12-27 22:55:23 +00:00
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
2011-02-12 04:13:11 +00:00
|
|
|
reinterpret_cast<object>(arguments[0]), file, mask)) != 0;
|
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]);
|
2013-02-11 00:38:51 +00:00
|
|
|
object path = fieldAtOffset<object>(file, cp->filePathField);
|
2010-11-05 19:18:28 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1);
|
2010-11-05 19:18:28 +00:00
|
|
|
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 {
|
2010-12-27 22:55:23 +00:00
|
|
|
return longValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
reinterpret_cast<object>(arguments[0]), file));
|
2010-11-05 19:18:28 +00:00
|
|
|
}
|
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);
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1);
|
2010-11-07 17:08:04 +00:00
|
|
|
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) {
|
2010-12-27 22:55:23 +00:00
|
|
|
throwNew(t, Machine::FileNotFoundExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
|
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) {
|
2010-12-27 22:55:23 +00:00
|
|
|
throwNew(t, Machine::FileNotFoundExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
System::Region* r = finder->find(ef.path);
|
|
|
|
if (r == 0) {
|
2010-12-27 22:55:23 +00:00
|
|
|
throwNew(t, Machine::FileNotFoundExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int32_t>
|
|
|
|
(fieldAtOffset<object>
|
2010-11-07 17:08:04 +00:00
|
|
|
(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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
int fd = fieldAtOffset<int32_t>
|
|
|
|
(fieldAtOffset<object>
|
2010-11-07 17:08:04 +00:00
|
|
|
(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 {
|
2010-12-27 22:55:23 +00:00
|
|
|
throwNew(t, Machine::IoExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-12-27 22:55:23 +00:00
|
|
|
return intValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_));
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
int fd = fieldAtOffset<int32_t>
|
|
|
|
(fieldAtOffset<object>
|
2010-11-07 17:08:04 +00:00
|
|
|
(this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField);
|
|
|
|
|
2010-11-07 19:24:40 +00:00
|
|
|
if (fd >= VirtualFileBase) {
|
2011-03-17 14:43:01 +00:00
|
|
|
PROTECT(t, dst);
|
|
|
|
|
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 {
|
2010-12-27 22:55:23 +00:00
|
|
|
throwNew(t, Machine::IoExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-12-27 22:55:23 +00:00
|
|
|
return intValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_, dst, offset, length));
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
int fd = fieldAtOffset<int32_t>
|
|
|
|
(fieldAtOffset<object>
|
2010-11-07 17:08:04 +00:00
|
|
|
(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 {
|
2010-12-27 22:55:23 +00:00
|
|
|
throwNew(t, Machine::IoExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-12-27 22:55:23 +00:00
|
|
|
return longValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_, count));
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
int fd = fieldAtOffset<int32_t>
|
|
|
|
(fieldAtOffset<object>
|
2010-11-07 17:08:04 +00:00
|
|
|
(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 {
|
2010-12-27 22:55:23 +00:00
|
|
|
throwNew(t, Machine::IoExceptionType);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
} 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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
int fd = fieldAtOffset<int32_t>
|
|
|
|
(fieldAtOffset<object>
|
2010-11-07 17:08:04 +00:00
|
|
|
(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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-04 23:55:31 +00:00
|
|
|
class ZipFile {
|
|
|
|
public:
|
|
|
|
class Entry {
|
|
|
|
public:
|
|
|
|
Entry(unsigned hash, const uint8_t* start, Entry* next):
|
|
|
|
hash(hash), start(start), next(next), entry(0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
Entry(int64_t entry):
|
|
|
|
hash(0), start(0), next(0), entry(entry)
|
|
|
|
{ }
|
2011-03-26 17:45:33 +00:00
|
|
|
|
|
|
|
Entry():
|
|
|
|
hash(0), start(0), next(0), entry(0)
|
|
|
|
{ }
|
2011-03-04 23:55:31 +00:00
|
|
|
|
|
|
|
unsigned hash;
|
|
|
|
const uint8_t* start;
|
|
|
|
Entry* next;
|
|
|
|
int64_t entry;
|
|
|
|
};
|
|
|
|
|
|
|
|
ZipFile(Thread* t, System::Region* region, unsigned entryCount):
|
|
|
|
region(region),
|
|
|
|
entryCount(entryCount),
|
|
|
|
indexSize(nextPowerOfTwo(entryCount)),
|
|
|
|
index(reinterpret_cast<ZipFile::Entry**>
|
|
|
|
(t->m->heap->allocate(sizeof(ZipFile::Entry*) * indexSize))),
|
|
|
|
file(0)
|
|
|
|
{
|
|
|
|
memset(index, 0, sizeof(ZipFile::Entry*) * indexSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
ZipFile(int64_t file):
|
|
|
|
region(0), entryCount(0), indexSize(0), index(0), file(file)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
System::Region* region;
|
|
|
|
unsigned entryCount;
|
|
|
|
unsigned indexSize;
|
|
|
|
Entry** index;
|
|
|
|
int64_t file;
|
|
|
|
Entry entries[0];
|
|
|
|
};
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
openZipFile(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object path = reinterpret_cast<object>(arguments[0]);
|
|
|
|
int mode = arguments[1];
|
|
|
|
int64_t lastModified; memcpy(&lastModified, arguments + 2, 8);
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1);
|
|
|
|
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
|
|
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p));
|
|
|
|
|
|
|
|
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
|
|
|
if (ef.jar) {
|
|
|
|
if (ef.jarLength == 0 or ef.pathLength == 0) {
|
|
|
|
throwNew(t, Machine::FileNotFoundExceptionType);
|
|
|
|
}
|
|
|
|
|
|
|
|
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
|
|
|
if (finder == 0) {
|
|
|
|
throwNew(t, Machine::FileNotFoundExceptionType);
|
|
|
|
}
|
|
|
|
|
|
|
|
System::Region* r = finder->find(ef.path);
|
|
|
|
if (r == 0) {
|
|
|
|
throwNew(t, Machine::FileNotFoundExceptionType);
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t* start = r->start();
|
|
|
|
const uint8_t* end = start + r->length();
|
|
|
|
unsigned entryCount = 0;
|
|
|
|
for (const uint8_t* p = end - CentralDirectorySearchStart; p > start;) {
|
|
|
|
if (get4(p) == CentralDirectorySignature) {
|
|
|
|
p = start + centralDirectoryOffset(p);
|
|
|
|
|
|
|
|
while (p < end) {
|
|
|
|
if (get4(p) == EntrySignature) {
|
|
|
|
++ entryCount;
|
|
|
|
|
|
|
|
p = endOfEntry(p);
|
|
|
|
} else {
|
|
|
|
goto make;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
-- p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
make:
|
|
|
|
ZipFile* file = new
|
|
|
|
(t->m->heap->allocate
|
|
|
|
(sizeof(ZipFile) + (sizeof(ZipFile::Entry) * entryCount)))
|
|
|
|
ZipFile(t, r, entryCount);
|
|
|
|
|
|
|
|
{ unsigned position = 0;
|
|
|
|
for (const uint8_t* p = end - CentralDirectorySearchStart; p > start;) {
|
|
|
|
if (get4(p) == CentralDirectorySignature) {
|
|
|
|
p = start + centralDirectoryOffset(p);
|
|
|
|
|
|
|
|
while (p < end) {
|
|
|
|
if (get4(p) == EntrySignature) {
|
|
|
|
unsigned h = hash(fileName(p), fileNameLength(p));
|
|
|
|
unsigned i = h & (file->indexSize - 1);
|
|
|
|
|
|
|
|
file->index[i] = new (file->entries + (position++))
|
|
|
|
ZipFile::Entry(h, p, file->index[i]);
|
|
|
|
|
|
|
|
p = endOfEntry(p);
|
|
|
|
} else {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
-- p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
return reinterpret_cast<int64_t>(file);
|
|
|
|
} else {
|
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(new (t->m->heap->allocate(sizeof(ZipFile))) ZipFile
|
|
|
|
(longValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, path, mode, lastModified))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
getZipFileEntryCount(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t peer; memcpy(&peer, arguments, 8);
|
|
|
|
|
|
|
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
|
|
|
if (file->region) {
|
|
|
|
return file->entryCount;
|
|
|
|
} else {
|
|
|
|
return intValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, file->file));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ZipFile::Entry*
|
|
|
|
find(ZipFile* file, const char* path, unsigned pathLength)
|
|
|
|
{
|
|
|
|
unsigned i = hash(path) & (file->indexSize - 1);
|
|
|
|
for (ZipFile::Entry* e = file->index[i]; e; e = e->next) {
|
|
|
|
const uint8_t* p = e->start;
|
|
|
|
if (equal(path, pathLength, fileName(p), fileNameLength(p))) {
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
getZipFileEntry(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t peer; memcpy(&peer, arguments, 8);
|
|
|
|
object path = reinterpret_cast<object>(arguments[2]);
|
|
|
|
bool addSlash = arguments[3];
|
|
|
|
|
|
|
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
|
|
|
if (file->region) {
|
2012-02-18 22:17:10 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, char, p, byteArrayLength(t, path) + 2);
|
|
|
|
memcpy(RUNTIME_ARRAY_BODY(p), &byteArrayBody(t, path, 0),
|
|
|
|
byteArrayLength(t, path));
|
|
|
|
RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path)] = 0;
|
2011-03-04 23:55:31 +00:00
|
|
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p));
|
|
|
|
if (addSlash) {
|
2012-02-18 22:17:10 +00:00
|
|
|
RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path)] = '/';
|
|
|
|
RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path) + 1] = 0;
|
2011-03-04 23:55:31 +00:00
|
|
|
}
|
|
|
|
|
2013-02-22 21:20:09 +00:00
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(find(file, RUNTIME_ARRAY_BODY(p), byteArrayLength(t, path)));
|
2011-03-04 23:55:31 +00:00
|
|
|
} else {
|
|
|
|
int64_t entry = longValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, file->file, path, addSlash));
|
|
|
|
|
|
|
|
return entry ? reinterpret_cast<int64_t>
|
|
|
|
(new (t->m->heap->allocate(sizeof(ZipFile::Entry)))
|
|
|
|
ZipFile::Entry(entry)) : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-18 22:17:10 +00:00
|
|
|
int64_t JNICALL
|
|
|
|
getZipFileEntryBytes(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t peer; memcpy(&peer, arguments, 8);
|
|
|
|
int type = arguments[2];
|
|
|
|
|
|
|
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(peer);
|
|
|
|
if (entry->start) {
|
|
|
|
switch (type) {
|
|
|
|
case 0: { // name
|
|
|
|
unsigned nameLength = fileNameLength(entry->start);
|
|
|
|
object array = makeByteArray(t, nameLength + 1);
|
|
|
|
memcpy(&byteArrayBody(t, array, 0), fileName(entry->start), nameLength);
|
|
|
|
byteArrayBody(t, array, nameLength) = 0;
|
|
|
|
return reinterpret_cast<int64_t>(array);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case 1: { // extra
|
|
|
|
return 0;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case 2: { // comment
|
|
|
|
return 0;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
return compressedSize(entry->start);
|
|
|
|
} else {
|
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, entry->entry, type));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-04 23:55:31 +00:00
|
|
|
int64_t JNICALL
|
|
|
|
getNextZipFileEntry(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t peer; memcpy(&peer, arguments, 8);
|
|
|
|
int index = arguments[2];
|
|
|
|
|
|
|
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
|
|
|
if (file->region) {
|
|
|
|
return reinterpret_cast<int64_t>(file->entries + index);
|
|
|
|
} else {
|
|
|
|
int64_t entry = longValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, file->file, index));
|
|
|
|
|
|
|
|
return entry ? reinterpret_cast<int64_t>
|
|
|
|
(new (t->m->heap->allocate(sizeof(ZipFile::Entry)))
|
|
|
|
ZipFile::Entry(entry)) : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
initializeZipEntryFields(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
|
|
|
int64_t peer; memcpy(&peer, arguments + 1, 8);
|
|
|
|
|
|
|
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(peer);
|
|
|
|
if (entry->start) {
|
|
|
|
PROTECT(t, this_);
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
unsigned nameLength = fileNameLength(entry->start);
|
|
|
|
object array = makeByteArray(t, nameLength + 1);
|
|
|
|
memcpy(&byteArrayBody(t, array, 0), fileName(entry->start), nameLength);
|
|
|
|
byteArrayBody(t, array, nameLength) = 0;
|
|
|
|
|
|
|
|
object name = t->m->classpath->makeString
|
|
|
|
(t, array, 0, byteArrayLength(t, array) - 1);
|
|
|
|
|
|
|
|
set(t, this_, cp->zipEntryNameField, name);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int64_t>(this_, cp->zipEntryTimeField)
|
2011-03-04 23:55:31 +00:00
|
|
|
= fileTime(entry->start);
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int64_t>(this_, cp->zipEntryCrcField)
|
2011-03-04 23:55:31 +00:00
|
|
|
= fileCRC(entry->start);
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int64_t>(this_, cp->zipEntrySizeField)
|
2011-03-04 23:55:31 +00:00
|
|
|
= uncompressedSize(entry->start);
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int64_t>(this_, cp->zipEntryCsizeField)
|
2011-03-04 23:55:31 +00:00
|
|
|
= compressedSize(entry->start);
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int64_t>(this_, cp->zipEntryMethodField)
|
2011-03-04 23:55:31 +00:00
|
|
|
= compressionMethod(entry->start);
|
|
|
|
} else {
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
this_, entry->entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
getZipFileEntryMethod(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t peer; memcpy(&peer, arguments, 8);
|
|
|
|
|
|
|
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(peer);
|
|
|
|
if (entry->start) {
|
|
|
|
return compressionMethod(entry->start);
|
|
|
|
} else {
|
|
|
|
return intValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, entry->entry));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
getZipFileEntryCompressedSize(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t peer; memcpy(&peer, arguments, 8);
|
|
|
|
|
|
|
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(peer);
|
|
|
|
if (entry->start) {
|
|
|
|
return compressedSize(entry->start);
|
|
|
|
} else {
|
|
|
|
return longValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, entry->entry));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
getZipFileEntryUncompressedSize(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t peer; memcpy(&peer, arguments, 8);
|
|
|
|
|
|
|
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(peer);
|
|
|
|
if (entry->start) {
|
|
|
|
return uncompressedSize(entry->start);
|
|
|
|
} else {
|
|
|
|
return longValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, entry->entry));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
freeZipFileEntry(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t filePeer; memcpy(&filePeer, arguments, 8);
|
|
|
|
int64_t entryPeer; memcpy(&entryPeer, arguments + 2, 8);
|
|
|
|
|
|
|
|
ZipFile* file = reinterpret_cast<ZipFile*>(filePeer);
|
|
|
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(entryPeer);
|
|
|
|
if (file->region == 0) {
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, file->file, entry->entry);
|
|
|
|
}
|
2012-03-17 18:58:41 +00:00
|
|
|
|
|
|
|
t->m->heap->free(entry, sizeof(ZipFile::Entry));
|
2011-03-04 23:55:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
readZipFileEntry(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t filePeer; memcpy(&filePeer, arguments, 8);
|
|
|
|
int64_t entryPeer; memcpy(&entryPeer, arguments + 2, 8);
|
|
|
|
int64_t position; memcpy(&position, arguments + 4, 8);
|
|
|
|
object buffer = reinterpret_cast<object>(arguments[6]);
|
|
|
|
int offset = arguments[7];
|
|
|
|
int length = arguments[8];
|
|
|
|
|
|
|
|
ZipFile* file = reinterpret_cast<ZipFile*>(filePeer);
|
|
|
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(entryPeer);
|
|
|
|
if (file->region) {
|
|
|
|
unsigned size = uncompressedSize(entry->start);
|
|
|
|
if (position >= size) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (position + length > size) {
|
|
|
|
length = size - position;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&byteArrayBody(t, buffer, offset),
|
|
|
|
fileData(file->region->start() + localHeaderOffset(entry->start))
|
|
|
|
+ position,
|
|
|
|
length);
|
|
|
|
|
|
|
|
return length;
|
|
|
|
} else {
|
|
|
|
return intValue
|
|
|
|
(t, t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, file->file, entry->entry, position, buffer, offset, length));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
getZipMessage(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t peer; memcpy(&peer, arguments, 8);
|
|
|
|
|
|
|
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
|
|
|
if (file->region) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, file->file));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t JNICALL
|
|
|
|
getJarFileMetaInfEntryNames(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
|
|
|
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
int64_t peer = fieldAtOffset<int64_t>(this_, cp->zipFileJzfileField);
|
2011-03-04 23:55:31 +00:00
|
|
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
|
|
|
if (file->region) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
// OpenJDK's Java_java_util_jar_JarFile_getMetaInfEntryNames
|
|
|
|
// implementation expects to find a pointer to an instance of its
|
|
|
|
// jzfile structure in the ZipFile.jzfile field of the object we
|
|
|
|
// pass in. However, we can't pass this_ in, because its
|
|
|
|
// ZipFile.jzfile field points to a ZipFile instance, not a
|
|
|
|
// jzfile. So we pass in a temporary object instead which has the
|
|
|
|
// desired pointer at the same offset. We assume here that
|
|
|
|
// ZipFile.jzfile is the first field in that class and that
|
|
|
|
// Java_java_util_jar_JarFile_getMetaInfEntryNames will not look
|
|
|
|
// for any other fields in the object.
|
|
|
|
object pseudoThis = makeLong(t, file->file);
|
|
|
|
|
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
pseudoThis));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void JNICALL
|
|
|
|
closeZipFile(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int64_t peer; memcpy(&peer, arguments, 8);
|
|
|
|
|
|
|
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
|
|
|
if (file->region) {
|
|
|
|
file->region->dispose();
|
|
|
|
t->m->heap->free(file, sizeof(ZipFile)
|
|
|
|
+ (sizeof(ZipFile::Entry) * file->entryCount));
|
|
|
|
} else {
|
|
|
|
t->m->processor->invoke
|
|
|
|
(t, nativeInterceptOriginal
|
|
|
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
|
|
|
0, file->file);
|
|
|
|
|
|
|
|
t->m->heap->free(file, sizeof(ZipFile));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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*);
|
|
|
|
|
2011-08-06 00:06:29 +00:00
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
|
|
|
management_JNI_OnLoad(JavaVM*, void*);
|
|
|
|
|
2010-12-09 04:38:16 +00:00
|
|
|
void JNICALL
|
|
|
|
loadLibrary(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object name = reinterpret_cast<object>(arguments[1]);
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, char, n, stringLength(t, name) + 1);
|
2010-12-09 04:38:16 +00:00
|
|
|
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
|
|
|
|
|
|
|
bool absolute = arguments[2];
|
|
|
|
|
|
|
|
#ifdef AVIAN_OPENJDK_SRC
|
|
|
|
if (not absolute) {
|
2013-02-25 17:38:06 +00:00
|
|
|
if (strcmp(RUNTIME_ARRAY_BODY(n), "net") == 0) {
|
2010-12-09 04:38:16 +00:00
|
|
|
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;
|
2013-02-25 17:38:06 +00:00
|
|
|
} else if (strcmp(RUNTIME_ARRAY_BODY(n), "management") == 0) {
|
2011-08-06 00:06:29 +00:00
|
|
|
bool ran;
|
|
|
|
|
|
|
|
{ ACQUIRE(t, t->m->classLock);
|
|
|
|
|
|
|
|
local::MyClasspath* c = static_cast<local::MyClasspath*>
|
|
|
|
(t->m->classpath);
|
|
|
|
|
|
|
|
ran = c->ranManagementOnLoad;
|
|
|
|
c->ranManagementOnLoad = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not ran) {
|
|
|
|
management_JNI_OnLoad(t->m, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2013-02-25 17:38:06 +00:00
|
|
|
} else if (strcmp(RUNTIME_ARRAY_BODY(n), "zip") == 0
|
|
|
|
or strcmp(RUNTIME_ARRAY_BODY(n), "nio") == 0)
|
2010-12-09 04:38:16 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // AVIAN_OPENJDK_SRC
|
|
|
|
|
|
|
|
loadLibrary
|
|
|
|
(t, static_cast<local::MyClasspath*>(t->m->classpath)->libraryPath,
|
2012-03-19 02:10:42 +00:00
|
|
|
RUNTIME_ARRAY_BODY(n), not absolute, true);
|
2010-12-09 04:38:16 +00:00
|
|
|
}
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
void
|
2013-03-15 19:28:01 +00:00
|
|
|
interceptFileOperations(Thread* t, bool updateRuntimeData)
|
2010-11-07 17:08:04 +00:00
|
|
|
{
|
|
|
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
|
|
|
|
|
|
|
{ object fileClass = resolveClass
|
2011-04-10 23:01:38 +00:00
|
|
|
(t, root(t, Machine::BootLoader), "java/io/File", false);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
if (fileClass) {
|
|
|
|
object filePathField = findFieldInClass2
|
|
|
|
(t, fileClass, "path", "Ljava/lang/String;");
|
|
|
|
|
|
|
|
if (filePathField) {
|
|
|
|
cp->filePathField = fieldOffset(t, filePathField);
|
|
|
|
}
|
|
|
|
}
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{ object fileDescriptorClass = resolveClass
|
2011-04-10 23:01:38 +00:00
|
|
|
(t, root(t, Machine::BootLoader), "java/io/FileDescriptor", false);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
if (fileDescriptorClass) {
|
|
|
|
object fileDescriptorFdField = findFieldInClass2
|
|
|
|
(t, fileDescriptorClass, "fd", "I");
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
if (fileDescriptorFdField) {
|
|
|
|
cp->fileDescriptorFdField = fieldOffset(t, fileDescriptorFdField);
|
|
|
|
}
|
|
|
|
}
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{ object fileInputStreamClass = resolveClass
|
2011-04-10 23:01:38 +00:00
|
|
|
(t, root(t, Machine::BootLoader), "java/io/FileInputStream", false);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
if (fileInputStreamClass) {
|
|
|
|
PROTECT(t, fileInputStreamClass);
|
2010-12-10 05:17:57 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
object fileInputStreamFdField = findFieldInClass2
|
|
|
|
(t, fileInputStreamClass, "fd", "Ljava/io/FileDescriptor;");
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
if (fileInputStreamFdField) {
|
|
|
|
cp->fileInputStreamFdField = fieldOffset(t, fileInputStreamFdField);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, fileInputStreamClass, "open", "(Ljava/lang/String;)V",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(openFile), updateRuntimeData);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, fileInputStreamClass, "read", "()I",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(readByteFromFile), updateRuntimeData);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, fileInputStreamClass, "readBytes", "([BII)I",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(readBytesFromFile), updateRuntimeData);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, fileInputStreamClass, "skip", "(J)J",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(skipBytesInFile), updateRuntimeData);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, fileInputStreamClass, "available", "()I",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(availableBytesInFile), updateRuntimeData);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, fileInputStreamClass, "close0", "()V",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(closeFile), updateRuntimeData);
|
2011-04-10 23:01:38 +00:00
|
|
|
}
|
|
|
|
}
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
|
2011-03-04 23:55:31 +00:00
|
|
|
{ object zipFileClass = resolveClass
|
2011-04-10 23:01:38 +00:00
|
|
|
(t, root(t, Machine::BootLoader), "java/util/zip/ZipFile", false);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
if (zipFileClass) {
|
|
|
|
PROTECT(t, zipFileClass);
|
2011-03-17 14:43:01 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
object zipFileJzfileField = findFieldInClass2
|
|
|
|
(t, zipFileClass, "jzfile", "J");
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
if (zipFileJzfileField) {
|
|
|
|
cp->zipFileJzfileField = fieldOffset(t, zipFileJzfileField);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2012-02-18 22:17:10 +00:00
|
|
|
intercept(t, zipFileClass, "open", "(Ljava/lang/String;IJZ)J",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(openZipFile), updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, zipFileClass, "getTotal", "(J)I",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getZipFileEntryCount), updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2012-02-18 22:17:10 +00:00
|
|
|
intercept(t, zipFileClass, "getEntry", "(J[BZ)J",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getZipFileEntry), updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2012-02-18 22:17:10 +00:00
|
|
|
intercept(t, zipFileClass, "getEntryBytes", "(JI)[B",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getZipFileEntryBytes), updateRuntimeData);
|
2012-02-18 22:17:10 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, zipFileClass, "getNextEntry", "(JI)J",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getNextZipFileEntry), updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2012-02-18 22:17:10 +00:00
|
|
|
intercept(t, zipFileClass, "getEntryMethod", "(J)I",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getZipFileEntryMethod), updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, zipFileClass, "freeEntry", "(JJ)V",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(freeZipFileEntry), updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, zipFileClass, "read", "(JJJ[BII)I",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(readZipFileEntry), updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2012-02-18 22:17:10 +00:00
|
|
|
intercept(t, zipFileClass, "getEntryCSize", "(J)J",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getZipFileEntryCompressedSize),
|
|
|
|
updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2012-02-18 22:17:10 +00:00
|
|
|
intercept(t, zipFileClass, "getEntrySize", "(J)J",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getZipFileEntryUncompressedSize),
|
|
|
|
updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, zipFileClass, "getZipMessage", "(J)Ljava/lang/String;",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getZipMessage), updateRuntimeData);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, zipFileClass, "close", "(J)V",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(closeZipFile), updateRuntimeData);
|
2011-04-10 23:01:38 +00:00
|
|
|
}
|
|
|
|
}
|
2011-03-04 23:55:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{ object jarFileClass = resolveClass
|
2011-04-10 23:01:38 +00:00
|
|
|
(t, root(t, Machine::BootLoader), "java/util/jar/JarFile", false);
|
2011-03-04 23:55:31 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
if (jarFileClass) {
|
|
|
|
intercept(t, jarFileClass, "getMetaInfEntryNames",
|
|
|
|
"()[Ljava/lang/String;",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getJarFileMetaInfEntryNames), updateRuntimeData);
|
2011-04-10 23:01:38 +00:00
|
|
|
}
|
2011-03-04 23:55:31 +00:00
|
|
|
}
|
|
|
|
|
2010-11-07 17:08:04 +00:00
|
|
|
{
|
|
|
|
#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);
|
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
if (fsClass) {
|
|
|
|
PROTECT(t, fsClass);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, fsClass, gbaMethodName, "(Ljava/io/File;)I",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getFileAttributes), updateRuntimeData);
|
2010-12-01 20:40:43 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, fsClass, "checkAccess", "(Ljava/io/File;I)Z",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(checkFileAccess), updateRuntimeData);
|
2010-11-07 17:08:04 +00:00
|
|
|
|
2011-04-10 23:01:38 +00:00
|
|
|
intercept(t, fsClass, "getLength", "(Ljava/io/File;)J",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getFileLength), updateRuntimeData);
|
2011-04-10 23:01:38 +00:00
|
|
|
}
|
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",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(loadLibrary), updateRuntimeData);
|
2010-12-09 04:38:16 +00:00
|
|
|
|
2010-12-06 00:40:50 +00:00
|
|
|
intercept(t, type(t, Machine::ClassLoaderType), "getBootstrapResource",
|
|
|
|
"(Ljava/lang/String;)Ljava/net/URL;",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getBootstrapResource), updateRuntimeData);
|
2010-12-06 00:40:50 +00:00
|
|
|
|
|
|
|
intercept(t, type(t, Machine::ClassLoaderType), "getBootstrapResources",
|
|
|
|
"(Ljava/lang/String;)Ljava/util/Enumeration;",
|
2013-03-15 19:28:01 +00:00
|
|
|
voidPointer(getBootstrapResources), updateRuntimeData);
|
2010-11-07 17:08:04 +00:00
|
|
|
}
|
|
|
|
|
2011-04-10 03:20:56 +00:00
|
|
|
object
|
|
|
|
getClassMethodTable(Thread* t, object c)
|
|
|
|
{
|
|
|
|
object addendum = classAddendum(t, c);
|
|
|
|
if (addendum) {
|
|
|
|
object table = classAddendumMethodTable(t, addendum);
|
|
|
|
if (table) {
|
|
|
|
return table;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return classMethodTable(t, c);
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
unsigned
|
|
|
|
countMethods(Thread* t, object c, bool publicOnly)
|
|
|
|
{
|
2011-04-10 03:20:56 +00:00
|
|
|
object table = getClassMethodTable(t, c);
|
2010-09-10 21:05:29 +00:00
|
|
|
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)
|
|
|
|
{
|
2011-04-10 03:20:56 +00:00
|
|
|
object table = getClassMethodTable(t, c);
|
2010-09-10 21:05:29 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-12-19 19:39:33 +00:00
|
|
|
object
|
|
|
|
makeJmethod(Thread* t, object vmMethod, int index)
|
|
|
|
{
|
|
|
|
PROTECT(t, vmMethod);
|
|
|
|
|
|
|
|
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;
|
2013-02-21 22:37:17 +00:00
|
|
|
object parameterTypes = resolveParameterJTypes
|
2012-12-19 19:39:33 +00:00
|
|
|
(t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod),
|
|
|
|
¶meterCount, &returnTypeSpec);
|
|
|
|
PROTECT(t, parameterTypes);
|
|
|
|
|
2013-02-21 22:37:17 +00:00
|
|
|
object returnType = resolveJType
|
2012-12-19 19:39:33 +00:00
|
|
|
(t, classLoader(t, methodClass(t, vmMethod)), reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, vmMethod), returnTypeSpec)),
|
|
|
|
byteArrayLength(t, methodSpec(t, vmMethod)) - 1 - returnTypeSpec);
|
|
|
|
PROTECT(t, returnType);
|
|
|
|
|
2013-02-21 22:37:17 +00:00
|
|
|
object exceptionTypes = resolveExceptionJTypes
|
2012-12-19 19:39:33 +00:00
|
|
|
(t, classLoader(t, methodClass(t, vmMethod)),
|
|
|
|
methodAddendum(t, vmMethod));
|
|
|
|
PROTECT(t, exceptionTypes);
|
|
|
|
|
|
|
|
object signature;
|
|
|
|
object annotationTable;
|
|
|
|
object annotationDefault;
|
|
|
|
object addendum = methodAddendum(t, vmMethod);
|
|
|
|
if (addendum) {
|
|
|
|
signature = addendumSignature(t, addendum);
|
|
|
|
if (signature) {
|
2013-02-03 22:19:35 +00:00
|
|
|
PROTECT(t, addendum);
|
|
|
|
|
2012-12-19 19:39:33 +00:00
|
|
|
signature = t->m->classpath->makeString
|
|
|
|
(t, signature, 0, byteArrayLength(t, signature) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
annotationTable = addendumAnnotationTable(t, addendum);
|
|
|
|
|
|
|
|
annotationDefault = methodAddendumAnnotationDefault(t, addendum);
|
|
|
|
} else {
|
|
|
|
signature = 0;
|
|
|
|
annotationTable = 0;
|
|
|
|
annotationDefault = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PROTECT(t, signature);
|
|
|
|
PROTECT(t, annotationTable);
|
|
|
|
PROTECT(t, annotationDefault);
|
|
|
|
|
|
|
|
if (annotationTable or annotationDefault) {
|
|
|
|
object runtimeData = getClassRuntimeData(t, methodClass(t, vmMethod));
|
|
|
|
|
|
|
|
set(t, runtimeData, ClassRuntimeDataPool,
|
|
|
|
addendumPool(t, methodAddendum(t, vmMethod)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == -1) {
|
|
|
|
object table = classMethodTable(t, methodClass(t, vmMethod));
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
if (vmMethod == arrayBody(t, table, i)) {
|
|
|
|
index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(t, index != -1);
|
|
|
|
|
|
|
|
object jclass = getJClass(t, methodClass(t, vmMethod));
|
|
|
|
|
|
|
|
return makeJmethod
|
|
|
|
(t, true, 0, jclass, index, name, returnType, parameterTypes,
|
|
|
|
exceptionTypes, methodFlags(t, vmMethod), signature, 0, annotationTable,
|
|
|
|
0, annotationDefault, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeJconstructor(Thread* t, object vmMethod, int index)
|
|
|
|
{
|
|
|
|
PROTECT(t, vmMethod);
|
|
|
|
|
|
|
|
unsigned parameterCount;
|
|
|
|
unsigned returnTypeSpec;
|
2013-02-21 22:37:17 +00:00
|
|
|
object parameterTypes = resolveParameterJTypes
|
2012-12-19 19:39:33 +00:00
|
|
|
(t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod),
|
|
|
|
¶meterCount, &returnTypeSpec);
|
|
|
|
PROTECT(t, parameterTypes);
|
|
|
|
|
2013-02-21 22:37:17 +00:00
|
|
|
object exceptionTypes = resolveExceptionJTypes
|
2012-12-19 19:39:33 +00:00
|
|
|
(t, classLoader(t, methodClass(t, vmMethod)),
|
|
|
|
methodAddendum(t, vmMethod));
|
|
|
|
PROTECT(t, exceptionTypes);
|
|
|
|
|
|
|
|
object signature;
|
|
|
|
object annotationTable;
|
|
|
|
object addendum = methodAddendum(t, vmMethod);
|
|
|
|
if (addendum) {
|
|
|
|
signature = addendumSignature(t, addendum);
|
|
|
|
if (signature) {
|
2013-02-03 22:19:35 +00:00
|
|
|
PROTECT(t, addendum);
|
|
|
|
|
2012-12-19 19:39:33 +00:00
|
|
|
signature = t->m->classpath->makeString
|
|
|
|
(t, signature, 0, byteArrayLength(t, signature) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
annotationTable = addendumAnnotationTable(t, addendum);
|
|
|
|
} else {
|
|
|
|
signature = 0;
|
|
|
|
annotationTable = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PROTECT(t, signature);
|
|
|
|
PROTECT(t, annotationTable);
|
|
|
|
|
|
|
|
if (annotationTable) {
|
|
|
|
object runtimeData = getClassRuntimeData(t, methodClass(t, vmMethod));
|
|
|
|
|
|
|
|
set(t, runtimeData, ClassRuntimeDataPool,
|
|
|
|
addendumPool(t, methodAddendum(t, vmMethod)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == -1) {
|
|
|
|
object table = classMethodTable(t, methodClass(t, vmMethod));
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
if (vmMethod == arrayBody(t, table, i)) {
|
|
|
|
index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(t, index != -1);
|
|
|
|
|
|
|
|
object jclass = getJClass(t, methodClass(t, vmMethod));
|
|
|
|
|
|
|
|
return makeJconstructor
|
|
|
|
(t, true, 0, jclass, index, parameterTypes, exceptionTypes, methodFlags
|
|
|
|
(t, vmMethod), signature, 0, annotationTable, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeJfield(Thread* t, object vmField, int index)
|
|
|
|
{
|
|
|
|
PROTECT(t, vmField);
|
|
|
|
|
|
|
|
object name = intern
|
|
|
|
(t, t->m->classpath->makeString
|
|
|
|
(t, fieldName(t, vmField), 0, byteArrayLength
|
|
|
|
(t, fieldName(t, vmField)) - 1));
|
|
|
|
PROTECT(t, name);
|
|
|
|
|
2013-02-20 17:22:40 +00:00
|
|
|
object type = resolveClassBySpec
|
2012-12-19 19:39:33 +00:00
|
|
|
(t, classLoader(t, fieldClass(t, vmField)),
|
|
|
|
reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, fieldSpec(t, vmField), 0)),
|
|
|
|
byteArrayLength(t, fieldSpec(t, vmField)) - 1);
|
|
|
|
PROTECT(t, type);
|
|
|
|
|
|
|
|
type = getJClass(t, type);
|
|
|
|
|
|
|
|
object signature;
|
|
|
|
object annotationTable;
|
|
|
|
object addendum = fieldAddendum(t, vmField);
|
|
|
|
if (addendum) {
|
|
|
|
signature = addendumSignature(t, addendum);
|
|
|
|
if (signature) {
|
2013-02-03 22:19:35 +00:00
|
|
|
PROTECT(t, addendum);
|
|
|
|
|
2012-12-19 19:39:33 +00:00
|
|
|
signature = t->m->classpath->makeString
|
|
|
|
(t, signature, 0, byteArrayLength(t, signature) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
annotationTable = addendumAnnotationTable(t, addendum);
|
|
|
|
} else {
|
|
|
|
signature = 0;
|
|
|
|
annotationTable = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PROTECT(t, signature);
|
|
|
|
PROTECT(t, annotationTable);
|
|
|
|
|
|
|
|
if (annotationTable) {
|
|
|
|
object runtimeData = getClassRuntimeData(t, fieldClass(t, vmField));
|
|
|
|
|
|
|
|
set(t, runtimeData, ClassRuntimeDataPool,
|
|
|
|
addendumPool(t, fieldAddendum(t, vmField)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == -1) {
|
|
|
|
object table = classFieldTable(t, fieldClass(t, vmField));
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
if (vmField == arrayBody(t, table, i)) {
|
|
|
|
index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(t, index != -1);
|
|
|
|
|
|
|
|
object jclass = getJClass(t, fieldClass(t, vmField));
|
|
|
|
|
|
|
|
return makeJfield
|
|
|
|
(t, true, 0, jclass, index, name, type, fieldFlags
|
|
|
|
(t, vmField), signature, 0, annotationTable, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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-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
|
|
|
|
}
|
|
|
|
|
2011-02-23 01:37:42 +00:00
|
|
|
object
|
2012-03-11 11:04:12 +00:00
|
|
|
fieldForOffsetInClass(Thread* t, object c, unsigned offset)
|
2011-02-23 01:37:42 +00:00
|
|
|
{
|
2012-03-11 11:04:12 +00:00
|
|
|
object super = classSuper(t, c);
|
|
|
|
if (super) {
|
|
|
|
object field = fieldForOffsetInClass(t, super, offset);
|
|
|
|
if (field) {
|
2011-02-23 01:37:42 +00:00
|
|
|
return field;
|
|
|
|
}
|
|
|
|
}
|
2012-03-11 11:04:12 +00:00
|
|
|
|
|
|
|
object table = classFieldTable(t, c);
|
|
|
|
if (table) {
|
|
|
|
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
|
|
|
object field = objectArrayBody(t, table, i);
|
|
|
|
if ((fieldFlags(t, field) & ACC_STATIC) == 0
|
|
|
|
and fieldOffset(t, field) == offset)
|
|
|
|
{
|
|
|
|
return field;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
fieldForOffset(Thread* t, object o, unsigned offset)
|
|
|
|
{
|
2012-09-12 01:21:51 +00:00
|
|
|
object c = objectClass(t, o);
|
|
|
|
if (classVmFlags(t, c) & SingletonFlag) {
|
|
|
|
c = singletonObject(t, o, 0);
|
|
|
|
object table = classFieldTable(t, c);
|
|
|
|
if (table) {
|
|
|
|
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
|
|
|
object field = objectArrayBody(t, table, i);
|
|
|
|
if ((fieldFlags(t, field) & ACC_STATIC)
|
|
|
|
and fieldOffset(t, field) == offset)
|
|
|
|
{
|
|
|
|
return field;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-11 11:04:12 +00:00
|
|
|
abort(t);
|
2012-09-12 01:21:51 +00:00
|
|
|
} else {
|
|
|
|
object field = fieldForOffsetInClass(t, c, offset);
|
|
|
|
if (field) {
|
|
|
|
return field;
|
|
|
|
} else {
|
|
|
|
abort(t);
|
|
|
|
}
|
2012-03-11 11:04:12 +00:00
|
|
|
}
|
2011-02-23 01:37:42 +00:00
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2012-09-28 21:03:14 +00:00
|
|
|
object class_ = jclassVmClass(t, reinterpret_cast<object>(arguments[0]));
|
|
|
|
if (classFlags(t, class_) & ACC_INTERFACE) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
object super = classSuper(t, class_);
|
|
|
|
return super ? reinterpret_cast<int64_t>(getJClass(t, super)) : 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void
|
|
|
|
Avian_sun_misc_Unsafe_registerNatives
|
|
|
|
(Thread*, object, uintptr_t*)
|
|
|
|
{
|
|
|
|
// ignore
|
|
|
|
}
|
|
|
|
|
2012-03-11 22:26:46 +00:00
|
|
|
extern "C" JNIEXPORT void
|
|
|
|
Avian_sun_misc_Perf_registerNatives
|
|
|
|
(Thread*, object, uintptr_t*)
|
|
|
|
{
|
|
|
|
// ignore
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t
|
|
|
|
Avian_sun_misc_Perf_createLong
|
|
|
|
(Thread* t, object, uintptr_t*)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(t->m->processor->invoke
|
|
|
|
(t, resolveMethod
|
|
|
|
(t, root(t, Machine::BootLoader), "java/nio/ByteBuffer", "allocate",
|
|
|
|
"(I)Ljava/nio/ByteBuffer;"), 0, 8));
|
|
|
|
}
|
|
|
|
|
2011-04-10 03:19:49 +00:00
|
|
|
extern "C" JNIEXPORT int64_t
|
|
|
|
Avian_sun_misc_Unsafe_addressSize
|
|
|
|
(Thread*, object, uintptr_t*)
|
|
|
|
{
|
|
|
|
return BytesPerWord;
|
|
|
|
}
|
|
|
|
|
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]);
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint8_t* buffer = static_cast<uint8_t*>(t->m->heap->allocate(length));
|
|
|
|
|
|
|
|
THREAD_RESOURCE2(t, uint8_t*, buffer, int, length,
|
|
|
|
t->m->heap->free(buffer, length));
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
memcpy(buffer, &byteArrayBody(t, data, offset), length);
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<int64_t>
|
|
|
|
(getJClass(t, defineClass(t, loader, buffer, length)));
|
2010-09-14 16:49:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
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_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)));
|
|
|
|
}
|
|
|
|
|
2011-03-27 20:12:41 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
return fieldAtOffset<int16_t>(o, offset);
|
2011-03-27 20:12:41 +00:00
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
return fieldAtOffset<int32_t>(o, offset);
|
2010-09-14 16:49:41 +00:00
|
|
|
}
|
|
|
|
|
2011-03-18 03:42:15 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
return fieldAtOffset<int32_t>(o, offset);
|
2011-03-18 03:42:15 +00:00
|
|
|
}
|
|
|
|
|
2010-09-15 00:52:57 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getIntVolatile
|
briefly enter idle state in get*Volatile
In order for a thread to enter the "exclusive" state such that no
other threads are active in the VM, it must wait for all active
threads to enter the "idle" state. In order for this to happen in a
timely manner, threads must check frequently to see if a thread is
waiting to enter the exclusive state. These checks happen at every
memory allocation, wait, sleep, native call, etc. However, if a
thread is in a busy loop that does none of those things, it will block
any other thread from entering that state.
The proper way to address this is to detect such loops (or tail
recursion in tail-call-optimized builds) at compile or interpret time
and insert explicit checks. This hasn't been a high priority thus
far, though, since we had yet to encounter such code in the wild.
Now, however, we find that scala.concurrent.forkjoin.ForkJoinPool.scan
(and possibly some versions of java.util.concurrent.ForkJoinPool.scan,
on which we assume the former is based) has just such a loop.
Fortunately, that loop calls Unsafe.getObjectVolatile, which the VM
implements and thus can treat as a checkpoint. That's the workaround
we use in this patch.
2013-03-09 01:21:12 +00:00
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
briefly enter idle state in get*Volatile
In order for a thread to enter the "exclusive" state such that no
other threads are active in the VM, it must wait for all active
threads to enter the "idle" state. In order for this to happen in a
timely manner, threads must check frequently to see if a thread is
waiting to enter the exclusive state. These checks happen at every
memory allocation, wait, sleep, native call, etc. However, if a
thread is in a busy loop that does none of those things, it will block
any other thread from entering that state.
The proper way to address this is to detect such loops (or tail
recursion in tail-call-optimized builds) at compile or interpret time
and insert explicit checks. This hasn't been a high priority thus
far, though, since we had yet to encounter such code in the wild.
Now, however, we find that scala.concurrent.forkjoin.ForkJoinPool.scan
(and possibly some versions of java.util.concurrent.ForkJoinPool.scan,
on which we assume the former is based) has just such a loop.
Fortunately, that loop calls Unsafe.getObjectVolatile, which the VM
implements and thus can treat as a checkpoint. That's the workaround
we use in this patch.
2013-03-09 01:21:12 +00:00
|
|
|
// avoid blocking the VM if this is being called in a busy loop
|
|
|
|
PROTECT(t, o);
|
|
|
|
{ ENTER(t, Thread::IdleState); }
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
int32_t result = fieldAtOffset<int32_t>(o, offset);
|
2010-09-15 00:52:57 +00:00
|
|
|
loadMemoryBarrier();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-03-02 15:35:45 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
return fieldAtOffset<int64_t>(o, offset);
|
2011-03-02 15:35:45 +00:00
|
|
|
}
|
|
|
|
|
2012-08-11 12:56:19 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J
|
|
|
|
(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
return Avian_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J
|
|
|
|
(t, method, arguments);
|
|
|
|
}
|
|
|
|
|
2011-02-23 01:37:42 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getLongVolatile
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
briefly enter idle state in get*Volatile
In order for a thread to enter the "exclusive" state such that no
other threads are active in the VM, it must wait for all active
threads to enter the "idle" state. In order for this to happen in a
timely manner, threads must check frequently to see if a thread is
waiting to enter the exclusive state. These checks happen at every
memory allocation, wait, sleep, native call, etc. However, if a
thread is in a busy loop that does none of those things, it will block
any other thread from entering that state.
The proper way to address this is to detect such loops (or tail
recursion in tail-call-optimized builds) at compile or interpret time
and insert explicit checks. This hasn't been a high priority thus
far, though, since we had yet to encounter such code in the wild.
Now, however, we find that scala.concurrent.forkjoin.ForkJoinPool.scan
(and possibly some versions of java.util.concurrent.ForkJoinPool.scan,
on which we assume the former is based) has just such a loop.
Fortunately, that loop calls Unsafe.getObjectVolatile, which the VM
implements and thus can treat as a checkpoint. That's the workaround
we use in this patch.
2013-03-09 01:21:12 +00:00
|
|
|
// avoid blocking the VM if this is being called in a busy loop
|
|
|
|
PROTECT(t, o);
|
|
|
|
{ ENTER(t, Thread::IdleState); }
|
|
|
|
|
2011-02-23 01:37:42 +00:00
|
|
|
object field;
|
|
|
|
if (BytesPerWord < 8) {
|
|
|
|
field = local::fieldForOffset(t, o, offset);
|
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
acquire(t, field);
|
|
|
|
}
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
int64_t result = fieldAtOffset<int64_t>(o, offset);
|
2011-02-23 01:37:42 +00:00
|
|
|
|
|
|
|
if (BytesPerWord < 8) {
|
|
|
|
release(t, field);
|
|
|
|
} else {
|
|
|
|
loadMemoryBarrier();
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-03-28 14:55:20 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
int8_t value = arguments[4];
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int8_t>(o, offset) = value;
|
2011-03-28 14:55:20 +00:00
|
|
|
}
|
|
|
|
|
2011-04-10 03:20:21 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS
|
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
int16_t value = arguments[4];
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int16_t>(o, offset) = value;
|
2011-04-10 03:20:21 +00:00
|
|
|
}
|
|
|
|
|
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];
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int32_t>(o, offset) = value;
|
2010-09-14 16:49:41 +00:00
|
|
|
}
|
|
|
|
|
2011-03-18 03:42:15 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF
|
|
|
|
(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];
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int32_t>(o, offset) = value;
|
2011-03-18 03:42:15 +00:00
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
2012-06-12 22:33:31 +00:00
|
|
|
Avian_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J
|
2010-09-14 16:49:41 +00:00
|
|
|
(Thread*, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
return fieldAtOffset<int8_t>(o, offset);
|
2012-03-14 18:35:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
2012-06-12 22:33:31 +00:00
|
|
|
Avian_sun_misc_Unsafe_getBoolean__Ljava_lang_Object_2J
|
2012-03-14 18:35:22 +00:00
|
|
|
(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
2012-06-12 22:33:31 +00:00
|
|
|
return Avian_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J
|
|
|
|
(t, method, arguments);
|
2010-09-14 16:49:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2012-06-12 22:33:31 +00:00
|
|
|
Avian_sun_misc_Unsafe_putBoolean__Ljava_lang_Object_2JZ
|
2010-09-14 16:49:41 +00:00
|
|
|
(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];
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<uint8_t>(o, offset) = value;
|
2010-09-14 16:49:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int64_t>(o, offset) = value;
|
2010-09-14 16:49:41 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_getObjectVolatile
|
briefly enter idle state in get*Volatile
In order for a thread to enter the "exclusive" state such that no
other threads are active in the VM, it must wait for all active
threads to enter the "idle" state. In order for this to happen in a
timely manner, threads must check frequently to see if a thread is
waiting to enter the exclusive state. These checks happen at every
memory allocation, wait, sleep, native call, etc. However, if a
thread is in a busy loop that does none of those things, it will block
any other thread from entering that state.
The proper way to address this is to detect such loops (or tail
recursion in tail-call-optimized builds) at compile or interpret time
and insert explicit checks. This hasn't been a high priority thus
far, though, since we had yet to encounter such code in the wild.
Now, however, we find that scala.concurrent.forkjoin.ForkJoinPool.scan
(and possibly some versions of java.util.concurrent.ForkJoinPool.scan,
on which we assume the former is based) has just such a loop.
Fortunately, that loop calls Unsafe.getObjectVolatile, which the VM
implements and thus can treat as a checkpoint. That's the workaround
we use in this patch.
2013-03-09 01:21:12 +00:00
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
2010-09-14 16:49:41 +00:00
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
briefly enter idle state in get*Volatile
In order for a thread to enter the "exclusive" state such that no
other threads are active in the VM, it must wait for all active
threads to enter the "idle" state. In order for this to happen in a
timely manner, threads must check frequently to see if a thread is
waiting to enter the exclusive state. These checks happen at every
memory allocation, wait, sleep, native call, etc. However, if a
thread is in a busy loop that does none of those things, it will block
any other thread from entering that state.
The proper way to address this is to detect such loops (or tail
recursion in tail-call-optimized builds) at compile or interpret time
and insert explicit checks. This hasn't been a high priority thus
far, though, since we had yet to encounter such code in the wild.
Now, however, we find that scala.concurrent.forkjoin.ForkJoinPool.scan
(and possibly some versions of java.util.concurrent.ForkJoinPool.scan,
on which we assume the former is based) has just such a loop.
Fortunately, that loop calls Unsafe.getObjectVolatile, which the VM
implements and thus can treat as a checkpoint. That's the workaround
we use in this patch.
2013-03-09 01:21:12 +00:00
|
|
|
|
|
|
|
// avoid blocking the VM if this is being called in a busy loop
|
|
|
|
PROTECT(t, o);
|
|
|
|
{ ENTER(t, Thread::IdleState); }
|
2010-09-14 16:49:41 +00:00
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
uintptr_t value = fieldAtOffset<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
|
|
|
}
|
|
|
|
|
2011-03-02 15:35:45 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putObjectVolatile
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object o = reinterpret_cast<object>(arguments[1]);
|
|
|
|
int64_t offset; memcpy(&offset, arguments + 2, 8);
|
|
|
|
object value = reinterpret_cast<object>(arguments[4]);
|
|
|
|
|
|
|
|
storeStoreMemoryBarrier();
|
|
|
|
set(t, o, offset, reinterpret_cast<object>(value));
|
|
|
|
storeLoadMemoryBarrier();
|
|
|
|
}
|
|
|
|
|
2012-02-18 22:17:10 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_putOrderedObject
|
|
|
|
(Thread* t, object method, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
Avian_sun_misc_Unsafe_putObjectVolatile(t, method, arguments);
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT int64_t JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_compareAndSwapLong
|
2012-01-15 17:02:36 +00:00
|
|
|
(Thread* t UNUSED, object, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
|
2012-01-15 17:02:36 +00:00
|
|
|
#ifdef AVIAN_HAS_CAS64
|
2010-11-13 01:29:12 +00:00
|
|
|
return atomicCompareAndSwap64
|
2013-02-11 00:38:51 +00:00
|
|
|
(&fieldAtOffset<uint64_t>(target, offset), expect, update);
|
2012-01-15 17:02:36 +00:00
|
|
|
#else
|
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, local::fieldForOffset(t, target, offset));
|
2013-02-11 00:38:51 +00:00
|
|
|
if (fieldAtOffset<uint64_t>(target, offset) == expect) {
|
|
|
|
fieldAtOffset<uint64_t>(target, offset) = update;
|
2012-01-15 17:02:36 +00:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
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_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])));
|
|
|
|
}
|
|
|
|
|
2012-03-11 22:26:46 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2012-03-11 11:05:14 +00:00
|
|
|
Avian_sun_misc_Unsafe_monitorEnter
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
acquire(t, reinterpret_cast<object>(arguments[1]));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Avian_sun_misc_Unsafe_monitorExit
|
|
|
|
(Thread* t, object, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
release(t, reinterpret_cast<object>(arguments[1]));
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
namespace local {
|
|
|
|
|
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);
|
|
|
|
|
2011-02-25 15:17:15 +00:00
|
|
|
return o ? objectHash(t, *o) : 0;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2011-02-15 01:55:11 +00:00
|
|
|
uint64_t
|
|
|
|
jvmWait(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jlong milliseconds; memcpy(&milliseconds, arguments + 1, sizeof(jlong));
|
|
|
|
|
|
|
|
vm::wait(t, *o, milliseconds);
|
|
|
|
|
|
|
|
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_MonitorWait)(Thread* t, jobject o, jlong milliseconds)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2011-02-15 01:55:11 +00:00
|
|
|
uintptr_t arguments[1 + (sizeof(jlong) / BytesPerWord)];
|
|
|
|
arguments[0] = reinterpret_cast<uintptr_t>(o);
|
|
|
|
memcpy(arguments + 1, &milliseconds, sizeof(jlong));
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-02-15 01:55:11 +00:00
|
|
|
run(t, jvmWait, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
jvmNotify(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
|
|
|
|
notify(t, *o);
|
|
|
|
|
|
|
|
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_MonitorNotify)(Thread* t, jobject o)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2011-02-15 01:55:11 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-02-15 01:55:11 +00:00
|
|
|
run(t, jvmNotify, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
jvmNotifyAll(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
|
|
|
|
notifyAll(t, *o);
|
|
|
|
|
|
|
|
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_MonitorNotifyAll)(Thread* t, jobject o)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2011-02-15 01:55:11 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-02-15 01:55:11 +00:00
|
|
|
run(t, jvmNotifyAll, arguments);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmClone(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, clone(t, *o)));
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jobject>(run(t, jvmClone, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
jvmInternString(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, intern(t, *o)));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(s) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jobject>(run(t, jvmInternString, arguments));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmArrayCopy(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject src = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jint srcOffset = arguments[1];
|
|
|
|
jobject dst = reinterpret_cast<jobject>(arguments[2]);
|
|
|
|
jint dstOffset = arguments[3];
|
|
|
|
jint length = arguments[4];
|
|
|
|
|
|
|
|
arrayCopy(t, *src, srcOffset, *dst, dstOffset, length);
|
|
|
|
|
|
|
|
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_ArrayCopy)(Thread* t, jclass, jobject src, jint srcOffset,
|
|
|
|
jobject dst, jint dstOffset, jint length)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(src),
|
2012-06-14 01:10:28 +00:00
|
|
|
static_cast<uintptr_t>(srcOffset),
|
2010-12-27 22:55:23 +00:00
|
|
|
reinterpret_cast<uintptr_t>(dst),
|
2012-06-14 01:10:28 +00:00
|
|
|
static_cast<uintptr_t>(dstOffset),
|
|
|
|
static_cast<uintptr_t>(length) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
run(t, jvmArrayCopy, arguments);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmInitProperties(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jobject properties = reinterpret_cast<jobject>(arguments[0]);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
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;");
|
|
|
|
|
|
|
|
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);
|
2012-02-29 18:46:50 +00:00
|
|
|
#else // not PLATFORM_WINDOWS
|
2010-09-10 21:05:29 +00:00
|
|
|
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");
|
2012-08-02 16:36:16 +00:00
|
|
|
# elif defined __FreeBSD__
|
|
|
|
local::setProperty(t, method, *properties, "os.name", "FreeBSD");
|
2012-02-29 18:46:50 +00:00
|
|
|
# else // not __APPLE__
|
2010-09-10 21:05:29 +00:00
|
|
|
local::setProperty(t, method, *properties, "os.name", "Linux");
|
2012-02-29 18:46:50 +00:00
|
|
|
# endif // not __APPLE__
|
2010-09-10 21:05:29 +00:00
|
|
|
local::setProperty(t, method, *properties, "java.io.tmpdir", "/tmp");
|
|
|
|
local::setProperty(t, method, *properties, "user.home", getenv("HOME"));
|
2011-03-15 19:27:36 +00:00
|
|
|
|
|
|
|
char buffer[PATH_MAX];
|
|
|
|
local::setProperty(t, method, *properties, "user.dir",
|
|
|
|
getcwd(buffer, PATH_MAX));
|
2012-02-29 18:46:50 +00:00
|
|
|
#endif // not PLATFORM_WINDOWS
|
2010-12-01 03:25:48 +00:00
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
local::setProperty(t, method, *properties, "java.protocol.handler.pkgs",
|
|
|
|
"avian");
|
|
|
|
|
2011-03-27 05:24:05 +00:00
|
|
|
local::setProperty(t, method, *properties, "java.vm.vendor",
|
|
|
|
"Avian Contributors");
|
|
|
|
|
2012-08-11 12:56:19 +00:00
|
|
|
local::setProperty(t, method, *properties, "java.vm.name","Avian");
|
2012-09-05 12:31:30 +00:00
|
|
|
#ifdef AVIAN_VERSION
|
|
|
|
local::setProperty(t, method, *properties, "java.vm.version",AVIAN_VERSION);
|
|
|
|
#endif
|
|
|
|
#ifdef AVIAN_INFO
|
|
|
|
local::setProperty(t, method, *properties, "java.vm.info",AVIAN_INFO);
|
|
|
|
#endif
|
2012-08-11 12:56:19 +00:00
|
|
|
|
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);
|
|
|
|
|
2012-02-29 18:46:50 +00:00
|
|
|
local::setProperty
|
|
|
|
(t, method, *properties, "sun.boot.class.path",
|
|
|
|
static_cast<Finder*>
|
|
|
|
(systemClassLoaderFinder(t, root(t, Machine::BootLoader)))->path());
|
|
|
|
|
2013-04-17 01:25:19 +00:00
|
|
|
local::setProperty(t, method, *properties, "file.encoding", "UTF-8");
|
2010-09-10 21:05:29 +00:00
|
|
|
#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 == '=') {
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, char, name, (p - start) + 1);
|
2013-02-22 21:20:09 +00:00
|
|
|
memcpy(RUNTIME_ARRAY_BODY(name), start, p - start);
|
|
|
|
RUNTIME_ARRAY_BODY(name)[p - start] = 0;
|
2010-09-10 21:05:29 +00:00
|
|
|
local::setProperty
|
|
|
|
(t, method, *properties, RUNTIME_ARRAY_BODY(name), p + 1);
|
|
|
|
}
|
2010-12-27 22:55:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>(properties);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
|
|
|
EXPORT(JVM_InitProperties)(Thread* t, jobject properties)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(properties) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jobject>(run(t, jvmInitProperties, arguments));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGC(Thread* t, uintptr_t*)
|
|
|
|
{
|
|
|
|
collect(t, Heap::MajorCollection);
|
|
|
|
|
|
|
|
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_GC)()
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
run(t, jvmGC, 0);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
2011-03-27 20:12:41 +00:00
|
|
|
EXPORT(JVM_MaxObjectInspectionAge)(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
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
|
|
|
{
|
2012-08-30 00:32:45 +00:00
|
|
|
return local::globalMachine->heap->limit();
|
2010-09-15 00:52:57 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-27 18:25:02 +00:00
|
|
|
EXPORT(JVM_ActiveProcessorCount)()
|
|
|
|
{
|
2011-03-26 17:15:52 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
SYSTEM_INFO si;
|
|
|
|
GetSystemInfo(&si);
|
|
|
|
return si.dwNumberOfProcessors;
|
|
|
|
#else
|
|
|
|
return sysconf(_SC_NPROCESSORS_ONLN);
|
|
|
|
#endif
|
2010-11-27 18:25:02 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmLoadLibrary(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
const char* path = reinterpret_cast<const char*>(arguments[0]);
|
|
|
|
|
|
|
|
THREAD_RUNTIME_ARRAY(t, char, p, strlen(path) + 1);
|
|
|
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p), path);
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(loadLibrary
|
|
|
|
(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_LoadLibrary)(const char* path)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
2010-12-27 22:55:23 +00:00
|
|
|
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(path) };
|
2010-11-04 17:02:09 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<void*>(run(t, jvmLoadLibrary, arguments));
|
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
|
|
|
{
|
2011-03-26 17:15:52 +00:00
|
|
|
return version <= JNI_VERSION_1_6;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmFillInStackTrace(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jobject throwable = reinterpret_cast<jobject>(arguments[0]);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2012-02-18 22:17:10 +00:00
|
|
|
object trace = getTrace(t, 2);
|
2010-09-10 21:05:29 +00:00
|
|
|
set(t, *throwable, ThrowableTrace, trace);
|
2011-03-17 14:43:01 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
EXPORT(JVM_FillInStackTrace)(Thread* t, jobject throwable)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(throwable) };
|
|
|
|
|
|
|
|
run(t, jvmFillInStackTrace, arguments);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetStackTraceElement(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject throwable = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jint index = arguments[1];
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, makeStackTraceElement
|
|
|
|
(t, objectArrayBody(t, throwableTrace(t, *throwable), index))));
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2012-06-14 01:10:28 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(throwable),
|
|
|
|
static_cast<uintptr_t>(index) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jobject>(run(t, jvmGetStackTraceElement, arguments));
|
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
|
2011-03-26 00:50:31 +00:00
|
|
|
EXPORT(JVM_CompileClass)(Thread*, jclass, jclass)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2011-03-26 00:50:31 +00:00
|
|
|
EXPORT(JVM_CompileClasses)(Thread*, jclass, jstring)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
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
|
2011-05-16 16:33:46 +00:00
|
|
|
EXPORT(JVM_EnableCompiler)(Thread*, jclass)
|
|
|
|
{
|
|
|
|
// ignore
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2011-05-16 16:33:46 +00:00
|
|
|
EXPORT(JVM_DisableCompiler)(Thread*, jclass)
|
|
|
|
{
|
|
|
|
// ignore
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2012-02-03 19:00:02 +00:00
|
|
|
uint64_t
|
|
|
|
jvmStartThread(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject thread = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
|
|
|
|
return startThread(t, *thread) != 0;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2012-02-03 19:00:02 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(thread) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2012-02-03 19:00:02 +00:00
|
|
|
run(t, jvmStartThread, arguments);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2011-02-02 01:14:32 +00:00
|
|
|
EXPORT(JVM_Yield)(Thread* t, jclass)
|
2010-09-17 22:10:01 +00:00
|
|
|
{
|
2011-02-02 01:14:32 +00:00
|
|
|
t->m->system->yield();
|
2010-09-17 22:10:01 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmSleep(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jlong milliseconds; memcpy(&milliseconds, arguments, sizeof(jlong));
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2012-08-12 17:17:59 +00:00
|
|
|
if (milliseconds <= 0) {
|
|
|
|
milliseconds = 1;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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));
|
2010-12-27 22:55:23 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
EXPORT(JVM_Sleep)(Thread* t, jclass, jlong milliseconds)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[sizeof(jlong) / BytesPerWord];
|
|
|
|
memcpy(arguments, &milliseconds, sizeof(jlong));
|
|
|
|
|
|
|
|
run(t, jvmSleep, arguments);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmInterrupt(Thread* t, uintptr_t* arguments)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
2013-04-23 19:47:15 +00:00
|
|
|
threadInterrupt(t, *reinterpret_cast<jobject>(arguments[0]));
|
2010-12-27 22:55:23 +00:00
|
|
|
|
|
|
|
return 1;
|
2010-09-15 00:52:57 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
EXPORT(JVM_Interrupt)(Thread* t, jobject thread)
|
2010-09-14 16:49:41 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(thread) };
|
|
|
|
|
|
|
|
run(t, jvmInterrupt, arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
jvmIsInterrupted(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject thread = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jboolean clear = arguments[1];
|
2010-09-14 16:49:41 +00:00
|
|
|
|
2013-04-23 19:47:15 +00:00
|
|
|
return threadIsInterrupted(t, *thread, clear);
|
2010-09-14 16:49:41 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
EXPORT(JVM_IsInterrupted)(Thread* t, jobject thread, jboolean clear)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(thread), clear };
|
|
|
|
|
|
|
|
return run(t, jvmIsInterrupted, arguments);
|
|
|
|
}
|
|
|
|
|
2012-03-11 11:06:08 +00:00
|
|
|
uint64_t
|
|
|
|
jvmHoldsLock(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
object m = objectMonitor(t, *reinterpret_cast<jobject>(arguments[0]), false);
|
|
|
|
|
|
|
|
return m and monitorOwner(t, m) == t;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
2012-03-11 11:06:08 +00:00
|
|
|
EXPORT(JVM_HoldsLock)(Thread* t, jclass, jobject o)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(o) };
|
|
|
|
|
|
|
|
return run(t, jvmHoldsLock, arguments);
|
|
|
|
}
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmDumpThreads(Thread* t, uintptr_t* arguments)
|
2010-11-27 23:27:30 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jobjectArray threads = reinterpret_cast<jobjectArray>(arguments[0]);
|
2010-11-27 23:27:30 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, result));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
|
|
|
EXPORT(JVM_DumpThreads)(Thread* t, jclass, jobjectArray threads)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(threads) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jobjectArray>(run(t, jvmDumpThreads, arguments));
|
2010-11-27 23:27:30 +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_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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetClassContext(Thread* t, uintptr_t*)
|
2010-09-10 23:47:23 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, context));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
|
|
|
EXPORT(JVM_GetClassContext)(Thread* t)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<jobjectArray>(run(t, jvmGetClassContext, 0));
|
2010-09-10 23:47:23 +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_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
|
|
|
|
2012-09-24 23:43:34 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetSystemPackage(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jstring s = reinterpret_cast<jstring>(arguments[0]);
|
|
|
|
|
|
|
|
ACQUIRE(t, t->m->classLock);
|
|
|
|
|
|
|
|
THREAD_RUNTIME_ARRAY(t, char, chars, stringLength(t, *s) + 1);
|
|
|
|
stringChars(t, *s, RUNTIME_ARRAY_BODY(chars));
|
|
|
|
|
|
|
|
object key = makeByteArray(t, RUNTIME_ARRAY_BODY(chars));
|
|
|
|
|
|
|
|
object array = hashMapFind
|
|
|
|
(t, root(t, Machine::PackageMap), key, byteArrayHash, byteArrayEqual);
|
|
|
|
|
|
|
|
if (array) {
|
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, t->m->classpath->makeString
|
|
|
|
(t, array, 0, byteArrayLength(t, array))));
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
2012-09-24 23:43:34 +00:00
|
|
|
EXPORT(JVM_GetSystemPackage)(Thread* t, jstring s)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
2012-09-24 23:43:34 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(s) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jstring>(run(t, jvmGetSystemPackage, arguments));
|
2010-09-15 00:52:57 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-04-01 01:00:42 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetSystemPackages(Thread* t, uintptr_t*)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, makeObjectArray
|
|
|
|
(t, resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader), "java/lang/Package"), 0)));
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2011-04-01 01:00:42 +00:00
|
|
|
EXPORT(JVM_GetSystemPackages)(Thread* t)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<jobjectArray>(run(t, jvmGetSystemPackages, 0));
|
|
|
|
}
|
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
|
2011-03-02 15:35:45 +00:00
|
|
|
EXPORT(JVM_LatestUserDefinedLoader)(Thread* t)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
class Visitor: public Processor::StackVisitor {
|
|
|
|
public:
|
|
|
|
Visitor(Thread* t):
|
|
|
|
t(t), loader(0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual bool visit(Processor::StackWalker* walker) {
|
|
|
|
object loader = classLoader(t, methodClass(t, walker->method()));
|
2011-03-27 20:13:36 +00:00
|
|
|
if (loader
|
|
|
|
and loader != root(t, Machine::BootLoader)
|
|
|
|
and strcmp
|
|
|
|
(&byteArrayBody(t, className(t, objectClass(t, loader)), 0),
|
|
|
|
reinterpret_cast<const int8_t*>
|
|
|
|
("sun/reflect/DelegatingClassLoader")))
|
|
|
|
{
|
2011-03-02 15:35:45 +00:00
|
|
|
this->loader = loader;
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread* t;
|
|
|
|
object loader;
|
|
|
|
} v(t);
|
|
|
|
|
|
|
|
t->m->processor->walkStack(t, &v);
|
|
|
|
|
|
|
|
return makeLocalReference(t, v.loader);
|
|
|
|
}
|
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);
|
|
|
|
|
2013-02-11 00:38:51 +00:00
|
|
|
return fieldAtOffset<uintptr_t>(*array, BytesPerWord);
|
2010-09-14 16:49:41 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-03-28 02:25:47 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetArrayElement(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject array = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jint index = arguments[1];
|
|
|
|
|
|
|
|
switch (byteArrayBody(t, className(t, objectClass(t, *array)), 1)) {
|
|
|
|
case 'Z':
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(makeLocalReference
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, makeBoolean(t, fieldAtOffset<int8_t>(*array, ArrayBody + index))));
|
2011-03-28 02:25:47 +00:00
|
|
|
case 'B':
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(makeLocalReference
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, makeByte(t, fieldAtOffset<int8_t>(*array, ArrayBody + index))));
|
2011-03-28 02:25:47 +00:00
|
|
|
case 'C':
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(makeLocalReference
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, makeChar(t, fieldAtOffset<int16_t>(*array, ArrayBody + (index * 2)))));
|
2011-03-28 02:25:47 +00:00
|
|
|
case 'S':
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(makeLocalReference
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, makeShort(t, fieldAtOffset<int16_t>(*array, ArrayBody + (index * 2)))));
|
2011-03-28 02:25:47 +00:00
|
|
|
case 'I':
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(makeLocalReference
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, makeInt(t, fieldAtOffset<int32_t>(*array, ArrayBody + (index * 4)))));
|
2011-03-28 02:25:47 +00:00
|
|
|
case 'F':
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(makeLocalReference
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, makeFloat(t, fieldAtOffset<int32_t>(*array, ArrayBody + (index * 4)))));
|
2011-03-28 02:25:47 +00:00
|
|
|
case 'J':
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(makeLocalReference
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, makeLong(t, fieldAtOffset<int64_t>(*array, ArrayBody + (index * 8)))));
|
2011-03-28 02:25:47 +00:00
|
|
|
case 'D':
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(makeLocalReference
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, makeDouble(t, fieldAtOffset<int64_t>(*array, ArrayBody + (index * 8)))));
|
2011-03-28 02:25:47 +00:00
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(makeLocalReference
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, fieldAtOffset<object>(*array, ArrayBody + (index * BytesPerWord))));
|
2011-03-28 02:25:47 +00:00
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2011-03-28 02:25:47 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(array),
|
2012-06-14 01:10:28 +00:00
|
|
|
static_cast<uintptr_t>(index) };
|
2010-09-14 16:49:41 +00:00
|
|
|
|
2011-03-28 02:25:47 +00:00
|
|
|
return reinterpret_cast<jobject>(run(t, jvmGetArrayElement, arguments));
|
2010-09-14 16:49:41 +00:00
|
|
|
}
|
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);
|
|
|
|
|
2011-03-28 02:25:47 +00:00
|
|
|
switch (byteArrayBody(t, className(t, objectClass(t, *array)), 1)) {
|
|
|
|
case 'Z':
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int8_t>(*array, ArrayBody + index) = booleanValue(t, *value);
|
2011-03-28 02:25:47 +00:00
|
|
|
break;
|
|
|
|
case 'B':
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int8_t>(*array, ArrayBody + index) = byteValue(t, *value);
|
2011-03-28 02:25:47 +00:00
|
|
|
break;
|
|
|
|
case 'C':
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int16_t>(*array, ArrayBody + (index * 2)) = charValue(t, *value);
|
2011-03-28 02:25:47 +00:00
|
|
|
break;
|
|
|
|
case 'S':
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int16_t>(*array, ArrayBody + (index * 2)) = shortValue(t, *value);
|
2011-03-28 02:25:47 +00:00
|
|
|
break;
|
|
|
|
case 'I':
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int32_t>(*array, ArrayBody + (index * 4)) = intValue(t, *value);
|
2011-03-28 02:25:47 +00:00
|
|
|
break;
|
|
|
|
case 'F':
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int32_t>(*array, ArrayBody + (index * 4)) = floatValue(t, *value);
|
2011-03-28 02:25:47 +00:00
|
|
|
break;
|
|
|
|
case 'J':
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int64_t>(*array, ArrayBody + (index * 8)) = longValue(t, *value);
|
2011-03-28 02:25:47 +00:00
|
|
|
break;
|
|
|
|
case 'D':
|
2013-02-11 00:38:51 +00:00
|
|
|
fieldAtOffset<int64_t>(*array, ArrayBody + (index * 8)) = doubleValue(t, *value);
|
2011-03-28 02:25:47 +00:00
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
set(t, *array, ArrayBody + (index * BytesPerWord), (value ? *value : 0));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
2010-09-14 16:49:41 +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_SetPrimitiveArrayElement)(Thread*, jobject, jint, jvalue,
|
2010-09-10 21:05:29 +00:00
|
|
|
unsigned char) { abort(); }
|
|
|
|
|
2011-03-26 17:15:52 +00:00
|
|
|
object
|
|
|
|
makeNewArray(Thread* t, object c, unsigned length)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
|
|
|
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') {
|
2011-03-26 17:15:52 +00:00
|
|
|
return makeBooleanArray(t, length);
|
2010-09-10 21:05:29 +00:00
|
|
|
} else {
|
2011-03-26 17:15:52 +00:00
|
|
|
return makeByteArray(t, length);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
2011-03-26 17:15:52 +00:00
|
|
|
case 'c': return makeCharArray(t, length);
|
|
|
|
case 'd': return makeDoubleArray(t, length);
|
|
|
|
case 'f': return makeFloatArray(t, length);
|
|
|
|
case 'i': return makeIntArray(t, length);
|
|
|
|
case 'l': return makeLongArray(t, length);
|
|
|
|
case 's': return makeShortArray(t, length);
|
2010-09-10 21:05:29 +00:00
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} else {
|
2011-03-26 17:15:52 +00:00
|
|
|
return makeObjectArray(t, c, length);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-26 17:15:52 +00:00
|
|
|
uint64_t
|
|
|
|
jvmNewArray(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jclass elementClass = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
jint length = arguments[1];
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, makeNewArray(t, jclassVmClass(t, *elementClass), length)));
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
|
|
|
EXPORT(JVM_NewArray)(Thread* t, jclass elementClass, jint length)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(elementClass),
|
2012-06-14 01:10:28 +00:00
|
|
|
static_cast<uintptr_t>(length) };
|
2010-12-27 22:55:23 +00:00
|
|
|
|
|
|
|
return reinterpret_cast<jobject>(run(t, jvmNewArray, arguments));
|
|
|
|
}
|
|
|
|
|
2011-03-26 17:15:52 +00:00
|
|
|
uint64_t
|
|
|
|
jvmNewMultiArray(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jclass elementClass = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
jintArray dimensions = reinterpret_cast<jintArray>(arguments[1]);
|
|
|
|
|
|
|
|
THREAD_RUNTIME_ARRAY(t, int32_t, counts, intArrayLength(t, *dimensions));
|
|
|
|
for (int i = intArrayLength(t, *dimensions) - 1; i >= 0; --i) {
|
|
|
|
RUNTIME_ARRAY_BODY(counts)[i] = intArrayBody(t, *dimensions, i);
|
|
|
|
if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) {
|
|
|
|
throwNew(t, Machine::NegativeArraySizeExceptionType, "%d",
|
|
|
|
RUNTIME_ARRAY_BODY(counts)[i]);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object array = makeNewArray
|
|
|
|
(t, jclassVmClass(t, *elementClass), RUNTIME_ARRAY_BODY(counts)[0]);
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
populateMultiArray(t, array, RUNTIME_ARRAY_BODY(counts), 0,
|
|
|
|
intArrayLength(t, *dimensions));
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, array));
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2011-03-26 17:15:52 +00:00
|
|
|
EXPORT(JVM_NewMultiArray)(Thread* t, jclass elementClass,
|
|
|
|
jintArray dimensions)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(elementClass),
|
|
|
|
reinterpret_cast<uintptr_t>(dimensions) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jobject>(run(t, jvmNewMultiArray, arguments));
|
|
|
|
}
|
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);
|
|
|
|
|
2012-09-23 02:22:33 +00:00
|
|
|
object method = getCaller(t, target, true);
|
2011-03-26 00:54:09 +00:00
|
|
|
|
|
|
|
return method ? makeLocalReference
|
|
|
|
(t, getJClass(t, methodClass(t, method))) : 0;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2010-12-27 22:55:23 +00:00
|
|
|
throwNew(t, Machine::IllegalArgumentExceptionType);
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-27 05:24:48 +00:00
|
|
|
uint64_t
|
|
|
|
jvmResolveClass(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
|
|
|
|
object method = resolveMethod
|
|
|
|
(t, root(t, Machine::BootLoader), "avian/Classes", "link",
|
|
|
|
"(Lavian/VMClass;)V");
|
|
|
|
|
|
|
|
t->m->processor->invoke(t, method, 0, jclassVmClass(t, *c));
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2011-03-27 05:24:48 +00:00
|
|
|
EXPORT(JVM_ResolveClass)(Thread* t, jclass c)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
|
|
|
|
|
|
|
|
run(t, jvmResolveClass, arguments);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmFindClassFromClassLoader(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
const char* name = reinterpret_cast<const char*>(arguments[0]);
|
|
|
|
jboolean init = arguments[1];
|
|
|
|
jobject loader = reinterpret_cast<jobject>(arguments[2]);
|
|
|
|
jboolean throwError = arguments[3];
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
object c = resolveClass
|
2011-03-18 03:42:15 +00:00
|
|
|
(t, loader ? *loader : root(t, Machine::BootLoader), name, true,
|
|
|
|
throwError ? Machine::NoClassDefFoundErrorType
|
|
|
|
: Machine::ClassNotFoundExceptionType);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
if (init) {
|
|
|
|
PROTECT(t, c);
|
|
|
|
|
|
|
|
initClass(t, c);
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, getJClass(t, c)));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
|
|
|
EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name,
|
|
|
|
jboolean init, jobject loader,
|
|
|
|
jboolean throwError)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(name),
|
|
|
|
init,
|
|
|
|
reinterpret_cast<uintptr_t>(loader),
|
|
|
|
throwError };
|
|
|
|
|
|
|
|
return reinterpret_cast<jclass>
|
|
|
|
(run(t, jvmFindClassFromClassLoader, arguments));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2010-11-05 21:34:28 +00:00
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2012-03-18 00:47:22 +00:00
|
|
|
JVM_FindClassFromBootLoader(Thread* t, const char* name)
|
2010-11-05 21:34:28 +00:00
|
|
|
{
|
2012-02-18 22:17:10 +00:00
|
|
|
return EXPORT(JVM_FindClassFromClassLoader)(t, name, false, 0, false);
|
2010-11-05 21:34:28 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2010-12-27 22:55:23 +00:00
|
|
|
EXPORT(JVM_FindClassFromClass)(Thread*, const char*, jboolean, jclass)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmFindLoadedClass(Thread* t, uintptr_t* arguments)
|
2010-09-10 23:47:23 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jobject loader = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jstring name = reinterpret_cast<jstring>(arguments[1]);
|
2010-09-10 23:47:23 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(c ? makeLocalReference(t, getJClass(t, c)) : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
|
|
|
EXPORT(JVM_FindLoadedClass)(Thread* t, jobject loader, jstring name)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(loader),
|
|
|
|
reinterpret_cast<uintptr_t>(name) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jclass>(run(t, jvmFindLoadedClass, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
jvmDefineClass(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject loader = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
const uint8_t* data = reinterpret_cast<const uint8_t*>(arguments[1]);
|
|
|
|
jsize length = arguments[2];
|
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, getJClass(t, defineClass(t, *loader, data, length))));
|
2010-09-10 23:47:23 +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_DefineClass)(Thread* t, const char*, jobject loader,
|
|
|
|
const uint8_t* data, jsize length, jobject)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(loader),
|
|
|
|
reinterpret_cast<uintptr_t>(data),
|
2012-06-14 01:10:28 +00:00
|
|
|
static_cast<uintptr_t>(length) };
|
2010-09-15 00:52:57 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jclass>(run(t, jvmDefineClass, arguments));
|
2010-09-15 00:52:57 +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_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));
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetClassInterfaces(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[0]);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-03-28 02:29:31 +00:00
|
|
|
object addendum = classAddendum(t, jclassVmClass(t, *c));
|
|
|
|
if (addendum) {
|
|
|
|
object table = classAddendumInterfaceTable(t, addendum);
|
|
|
|
if (table) {
|
|
|
|
PROTECT(t, table);
|
2011-02-19 21:07:45 +00:00
|
|
|
|
2011-03-28 02:29:31 +00:00
|
|
|
object array = makeObjectArray(t, arrayLength(t, table));
|
|
|
|
PROTECT(t, array);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-03-28 02:29:31 +00:00
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
object c = getJClass(t, arrayBody(t, table, i));
|
|
|
|
set(t, array, ArrayBody + (i * BytesPerWord), c);
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-03-28 02:29:31 +00:00
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, array));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
2011-03-28 02:29:31 +00:00
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, makeObjectArray(t, type(t, Machine::JclassType), 0)));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
|
|
|
EXPORT(JVM_GetClassInterfaces)(Thread* t, jclass c)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jclass>(run(t, jvmGetClassInterfaces, arguments));
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
2011-04-01 01:16:57 +00:00
|
|
|
jvmGetProtectionDomain(Thread* t, uintptr_t* arguments)
|
2010-09-15 00:52:57 +00:00
|
|
|
{
|
2011-04-01 01:16:57 +00:00
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[0]);
|
2010-09-15 00:52:57 +00:00
|
|
|
|
|
|
|
object method = resolveMethod
|
2011-04-01 01:16:57 +00:00
|
|
|
(t, root(t, Machine::BootLoader), "avian/OpenJDK", "getProtectionDomain",
|
|
|
|
"(Lavian/VMClass;)Ljava/security/ProtectionDomain;");
|
2010-09-15 00:52:57 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>
|
2011-04-01 01:16:57 +00:00
|
|
|
(makeLocalReference
|
|
|
|
(t, t->m->processor->invoke(t, method, 0, jclassVmClass(t, *c))));
|
2010-12-27 22:55:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2011-04-01 01:16:57 +00:00
|
|
|
EXPORT(JVM_GetProtectionDomain)(Thread* t, jclass c)
|
2010-12-27 22:55:23 +00:00
|
|
|
{
|
2011-04-01 01:16:57 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jobject>(run(t, jvmGetProtectionDomain, arguments));
|
2010-09-15 00:52:57 +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_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;
|
|
|
|
}
|
|
|
|
|
2011-03-17 14:43:01 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetComponentType(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2011-03-17 14:43:01 +00:00
|
|
|
jclass c = reinterpret_cast<jobject>(arguments[0]);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-03-17 15:41:52 +00:00
|
|
|
if (classArrayDimensions(t, jclassVmClass(t, *c))) {
|
|
|
|
uint8_t n = byteArrayBody(t, className(t, jclassVmClass(t, *c)), 1);
|
|
|
|
if (n != 'L' and n != '[') {
|
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(makeLocalReference(t, getJClass(t, primitiveClass(t, n))));
|
|
|
|
} else {
|
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, getJClass(t, classStaticTable(t, jclassVmClass(t, *c)))));
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
} else {
|
2011-03-17 15:41:52 +00:00
|
|
|
return 0;
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-17 14:43:01 +00:00
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
|
|
|
EXPORT(JVM_GetComponentType)(Thread* t, jclass c)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jclass>(run(t, jvmGetComponentType, arguments));
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2011-04-01 01:47:26 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetDeclaredClasses(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jclass c = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
|
|
|
|
object addendum = classAddendum(t, jclassVmClass(t, *c));
|
|
|
|
if (addendum) {
|
|
|
|
object table = classAddendumInnerClassTable(t, addendum);
|
|
|
|
if (table) {
|
|
|
|
PROTECT(t, table);
|
|
|
|
|
|
|
|
unsigned count = 0;
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
2013-04-23 03:20:21 +00:00
|
|
|
object outer = innerClassReferenceOuter(t, arrayBody(t, table, i));
|
|
|
|
if (outer and byteArrayEqual
|
|
|
|
(t, outer, className(t, jclassVmClass(t, *c))))
|
|
|
|
{
|
2011-04-01 01:47:26 +00:00
|
|
|
++ count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object result = makeObjectArray(t, count);
|
|
|
|
PROTECT(t, result);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
2013-04-23 03:20:21 +00:00
|
|
|
object outer = innerClassReferenceOuter(t, arrayBody(t, table, i));
|
|
|
|
if (outer and byteArrayEqual
|
|
|
|
(t, outer, className(t, jclassVmClass(t, *c))))
|
|
|
|
{
|
2011-04-01 01:47:26 +00:00
|
|
|
object inner = getJClass
|
|
|
|
(t, resolveClass
|
2013-04-17 21:12:58 +00:00
|
|
|
(t, classLoader(t, jclassVmClass(t, *c)),
|
|
|
|
innerClassReferenceInner(t, arrayBody(t, table, i))));
|
2011-04-01 01:47:26 +00:00
|
|
|
|
|
|
|
-- count;
|
|
|
|
set(t, result, ArrayBody + (count * BytesPerWord), inner);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return reinterpret_cast<uintptr_t>(makeLocalReference(t, result));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(makeLocalReference(t, makeObjectArray(t, 0)));
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2011-04-01 01:47:26 +00:00
|
|
|
EXPORT(JVM_GetDeclaredClasses)(Thread* t, jclass c)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jclass>(run(t, jvmGetDeclaredClasses, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
jvmGetDeclaringClass(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jclass c = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
|
2013-04-17 21:12:58 +00:00
|
|
|
object class_ = jclassVmClass(t, *c);
|
|
|
|
object addendum = classAddendum(t, class_);
|
|
|
|
if (addendum) {
|
|
|
|
object table = classAddendumInnerClassTable(t, addendum);
|
|
|
|
if (table) {
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
|
|
object reference = arrayBody(t, table, i);
|
|
|
|
if (strcmp
|
|
|
|
(&byteArrayBody(t, innerClassReferenceInner(t, reference), 0),
|
|
|
|
&byteArrayBody(t, className(t, class_), 0)) == 0)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, getJClass
|
|
|
|
(t, resolveClass
|
|
|
|
(t, classLoader(t, class_), innerClassReferenceOuter
|
|
|
|
(t, reference)))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-04-01 01:47:26 +00:00
|
|
|
|
2013-04-17 21:12:58 +00:00
|
|
|
return 0;
|
2011-04-01 01:47:26 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jclass JNICALL
|
2011-04-01 01:47:26 +00:00
|
|
|
EXPORT(JVM_GetDeclaringClass)(Thread* t, jclass c)
|
2011-02-25 15:17:15 +00:00
|
|
|
{
|
2011-04-01 01:47:26 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jclass>(run(t, jvmGetDeclaringClass, arguments));
|
2011-02-25 15:17:15 +00:00
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-04-01 01:47:26 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetClassSignature(Thread* t, uintptr_t* arguments)
|
2011-02-25 15:17:15 +00:00
|
|
|
{
|
2011-04-01 01:47:26 +00:00
|
|
|
jclass c = reinterpret_cast<jobject>(arguments[0]);
|
2011-03-18 03:42:15 +00:00
|
|
|
|
|
|
|
object addendum = classAddendum(t, jclassVmClass(t, *c));
|
|
|
|
if (addendum) {
|
|
|
|
object signature = addendumSignature(t, addendum);
|
|
|
|
if (signature) {
|
2011-04-01 01:47:26 +00:00
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, t->m->classpath->makeString
|
|
|
|
(t, signature, 0, byteArrayLength(t, signature) - 1)));
|
2011-03-18 03:42:15 +00:00
|
|
|
}
|
|
|
|
}
|
2011-02-25 15:17:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-04-01 01:47:26 +00:00
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
|
|
|
EXPORT(JVM_GetClassSignature)(Thread* t, jclass c)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jclass>(run(t, jvmGetClassSignature, arguments));
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmGetClassDeclaredMethods(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
jboolean publicOnly = arguments[1];
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-04-10 03:20:56 +00:00
|
|
|
object table = getClassMethodTable(t, jclassVmClass(t, *c));
|
2010-09-10 21:05:29 +00:00
|
|
|
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) != '<')
|
|
|
|
{
|
2012-12-19 19:39:33 +00:00
|
|
|
object method = makeJmethod(t, vmMethod, i);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
assert(t, ai < objectArrayLength(t, array));
|
|
|
|
|
|
|
|
set(t, array, ArrayBody + ((ai++) * BytesPerWord), method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, array));
|
2010-09-10 21:05:29 +00:00
|
|
|
} else {
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, makeObjectArray(t, type(t, Machine::JmethodType), 0)));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-12-27 22:55:23 +00:00
|
|
|
EXPORT(JVM_GetClassDeclaredMethods)(Thread* t, jclass c, jboolean publicOnly)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c), publicOnly };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jobjectArray>
|
|
|
|
(run(t, jvmGetClassDeclaredMethods, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
jvmGetClassDeclaredFields(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
jboolean publicOnly = arguments[1];
|
2010-09-10 21:05:29 +00:00
|
|
|
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)) {
|
2012-12-19 19:39:33 +00:00
|
|
|
object field = makeJfield(t, vmField, i);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, array));
|
2010-09-10 21:05:29 +00:00
|
|
|
} else {
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, makeObjectArray(t, type(t, Machine::JfieldType), 0)));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
2010-12-27 22:55:23 +00:00
|
|
|
EXPORT(JVM_GetClassDeclaredFields)(Thread* t, jclass c, jboolean publicOnly)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c), publicOnly };
|
|
|
|
|
|
|
|
return reinterpret_cast<jobjectArray>
|
|
|
|
(run(t, jvmGetClassDeclaredFields, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
jvmGetClassDeclaredConstructors(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
jboolean publicOnly = arguments[1];
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2011-04-10 03:20:56 +00:00
|
|
|
object table = getClassMethodTable(t, jclassVmClass(t, *c));
|
2010-09-10 21:05:29 +00:00
|
|
|
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)
|
|
|
|
{
|
2012-12-19 19:39:33 +00:00
|
|
|
object method = makeJconstructor(t, vmMethod, i);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
assert(t, ai < objectArrayLength(t, array));
|
|
|
|
|
|
|
|
set(t, array, ArrayBody + ((ai++) * BytesPerWord), method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, array));
|
2010-09-10 21:05:29 +00:00
|
|
|
} else {
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, makeObjectArray(t, type(t, Machine::JconstructorType), 0)));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
|
|
|
EXPORT(JVM_GetClassDeclaredConstructors)(Thread* t, jclass c,
|
|
|
|
jboolean publicOnly)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c), publicOnly };
|
|
|
|
|
|
|
|
return reinterpret_cast<jobjectArray>
|
|
|
|
(run(t, jvmGetClassDeclaredConstructors, arguments));
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmInvokeMethod(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jobject method = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jobject instance = reinterpret_cast<jobject>(arguments[1]);
|
|
|
|
jobjectArray args = reinterpret_cast<jobjectArray>(arguments[2]);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
object vmMethod = arrayBody
|
|
|
|
(t, classMethodTable
|
|
|
|
(t, jclassVmClass(t, jmethodClazz(t, *method))),
|
|
|
|
jmethodSlot(t, *method));
|
|
|
|
|
2013-04-18 17:25:29 +00:00
|
|
|
if (methodFlags(t, vmMethod) & ACC_STATIC) {
|
|
|
|
instance = 0;
|
|
|
|
}
|
|
|
|
|
2013-04-09 23:43:25 +00:00
|
|
|
if (instance and not instanceOf(t, methodClass(t, vmMethod), *instance)) {
|
|
|
|
throwNew(t, Machine::IllegalArgumentExceptionType);
|
|
|
|
}
|
|
|
|
|
2011-02-23 00:54:56 +00:00
|
|
|
return reinterpret_cast<uint64_t>
|
2013-02-21 22:37:17 +00:00
|
|
|
(makeLocalReference
|
|
|
|
(t, invoke
|
|
|
|
(t, vmMethod, instance ? *instance : 0, args ? *args : 0)));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
2010-12-27 22:55:23 +00:00
|
|
|
EXPORT(JVM_InvokeMethod)(Thread* t, jobject method, jobject instance,
|
|
|
|
jobjectArray args)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(method),
|
|
|
|
reinterpret_cast<uintptr_t>(instance),
|
|
|
|
reinterpret_cast<uintptr_t>(args) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jobject>(run(t, jvmInvokeMethod, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
jvmNewInstanceFromConstructor(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject constructor = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jobjectArray args = reinterpret_cast<jobjectArray>(arguments[1]);
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
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));
|
|
|
|
|
2012-09-23 02:22:33 +00:00
|
|
|
THREAD_RESOURCE0(t, {
|
|
|
|
if (t->exception) {
|
|
|
|
object exception = t->exception;
|
|
|
|
t->exception = makeThrowable
|
|
|
|
(t, Machine::InvocationTargetExceptionType, 0, 0, exception);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
if (args) {
|
|
|
|
t->m->processor->invokeArray(t, method, instance, *args);
|
2010-09-10 21:05:29 +00:00
|
|
|
} else {
|
|
|
|
t->m->processor->invoke(t, method, instance);
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, instance));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
|
|
|
EXPORT(JVM_NewInstanceFromConstructor)(Thread* t, jobject constructor,
|
|
|
|
jobjectArray args)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(constructor),
|
|
|
|
reinterpret_cast<uintptr_t>(args) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jobject>
|
|
|
|
(run(t, jvmNewInstanceFromConstructor, arguments));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2013-04-09 23:44:21 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetLongAt)(Thread* t, jobject, jobject pool, jint index)
|
|
|
|
{
|
|
|
|
ENTER(t, Thread::ActiveState);
|
|
|
|
|
|
|
|
uint64_t v;
|
|
|
|
memcpy(&v, &singletonValue(t, *pool, index - 1), 8);
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jfloat JNICALL
|
2013-04-23 03:23:32 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetFloatAt)(Thread* t, jobject, jobject pool,
|
|
|
|
jint index)
|
2012-08-30 00:34:28 +00:00
|
|
|
{
|
2013-04-23 03:23:32 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
2012-08-30 00:34:28 +00:00
|
|
|
|
2013-04-23 03:23:32 +00:00
|
|
|
return bitsToFloat(singletonValue(t, *pool, index - 1));
|
2012-08-30 00:34:28 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT jdouble JNICALL
|
2012-08-30 00:34:28 +00:00
|
|
|
EXPORT(JVM_ConstantPoolGetDoubleAt)(Thread* t, jobject, jobject pool,
|
|
|
|
jint index)
|
|
|
|
{
|
2013-04-23 03:23:32 +00:00
|
|
|
ENTER(t, Thread::ActiveState);
|
2012-08-30 00:34:28 +00:00
|
|
|
|
2013-04-23 03:23:32 +00:00
|
|
|
double v;
|
|
|
|
memcpy(&v, &singletonValue(t, *pool, index - 1), 8);
|
|
|
|
|
|
|
|
return v;
|
2012-08-30 00:34:28 +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_ConstantPoolGetStringAt)(Thread*, jobject, jobject, jint)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmConstantPoolGetUTF8At(Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
jobject pool = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jint index = arguments[1];
|
|
|
|
|
2013-02-03 21:09:29 +00:00
|
|
|
object array = parseUtf8(t, singletonObject(t, *pool, index - 1));
|
2010-12-27 22:55:23 +00:00
|
|
|
|
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, t->m->classpath->makeString
|
2013-02-11 00:38:51 +00:00
|
|
|
(t, array, 0, fieldAtOffset<uintptr_t>(array, BytesPerWord) - 1)));
|
2010-12-27 22:55:23 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2012-06-14 01:10:28 +00:00
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(pool),
|
|
|
|
static_cast<uintptr_t>(index) };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jstring>
|
|
|
|
(run(t, jvmConstantPoolGetUTF8At, arguments));
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
void
|
|
|
|
maybeWrap(Thread* t, bool wrapException)
|
|
|
|
{
|
|
|
|
if (t->exception
|
|
|
|
and wrapException
|
|
|
|
and not (instanceOf(t, type(t, Machine::ErrorType), t->exception)
|
|
|
|
or instanceOf
|
|
|
|
(t, type(t, Machine::RuntimeExceptionType), t->exception)))
|
|
|
|
{
|
|
|
|
object exception = t->exception;
|
|
|
|
t->exception = 0;
|
|
|
|
|
|
|
|
PROTECT(t, exception);
|
|
|
|
|
|
|
|
object paeClass = resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader),
|
|
|
|
"java/security/PrivilegedActionException");
|
|
|
|
PROTECT(t, paeClass);
|
|
|
|
|
|
|
|
object paeConstructor = resolveMethod
|
|
|
|
(t, paeClass, "<init>", "(Ljava/lang/Exception;)V");
|
|
|
|
PROTECT(t, paeConstructor);
|
|
|
|
|
|
|
|
object result = make(t, paeClass);
|
|
|
|
PROTECT(t, result);
|
|
|
|
|
|
|
|
t->m->processor->invoke(t, paeConstructor, result, exception);
|
|
|
|
|
|
|
|
t->exception = result;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
jvmDoPrivileged(Thread* t, uintptr_t* arguments)
|
2010-09-10 21:05:29 +00:00
|
|
|
{
|
2010-12-27 22:55:23 +00:00
|
|
|
jobject action = reinterpret_cast<jobject>(arguments[0]);
|
|
|
|
jboolean wrapException = arguments[1];
|
2010-09-10 21:05:29 +00:00
|
|
|
|
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
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
method = resolveMethod
|
|
|
|
(t, privilegedExceptionAction, "run", "()Ljava/lang/Object;");
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RESOURCE(t, jboolean, wrapException, maybeWrap(t, wrapException));
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<uint64_t>
|
|
|
|
(makeLocalReference(t, t->m->processor->invoke(t, method, *action)));
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
extern "C" JNIEXPORT jobject JNICALL
|
|
|
|
EXPORT(JVM_DoPrivileged)
|
|
|
|
(Thread* t, jclass, jobject action, jobject, jboolean wrapException)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(action),
|
|
|
|
wrapException };
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
return reinterpret_cast<jobject>(run(t, jvmDoPrivileged, arguments));
|
2010-09-10 21:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2012-03-13 14:26:51 +00:00
|
|
|
int r = OPEN(path, flags, mode);
|
|
|
|
if (r == -1) {
|
|
|
|
return errno == EEXIST ? JVM_EEXIST : -1;
|
|
|
|
} else {
|
|
|
|
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_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
|
2011-03-26 17:15:52 +00:00
|
|
|
EXPORT(JVM_SetLength)(jint fd, jlong length)
|
|
|
|
{
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
|
|
|
if (h == INVALID_HANDLE_VALUE) {
|
|
|
|
errno = EBADF;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-03-26 17:45:33 +00:00
|
|
|
long high = length >> 32;
|
|
|
|
DWORD r = SetFilePointer(h, static_cast<long>(length), &high, FILE_BEGIN);
|
|
|
|
if (r == 0xFFFFFFFF and GetLastError() != NO_ERROR) {
|
|
|
|
errno = EIO;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SetEndOfFile(h)) {
|
2011-03-26 17:15:52 +00:00
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
errno = EIO;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
return ftruncate(fd, length);
|
|
|
|
#endif
|
|
|
|
}
|
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
|
2011-03-02 15:35:45 +00:00
|
|
|
EXPORT(JVM_SocketAvailable)(jint socket, jint* count)
|
|
|
|
{
|
2011-03-26 17:45:33 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
unsigned long c = *count;
|
|
|
|
int r = ioctlsocket(socket, FIONREAD, &c);
|
|
|
|
*count = c;
|
|
|
|
return r;
|
|
|
|
#else
|
2011-03-02 15:35:45 +00:00
|
|
|
return ioctl(socket, FIONREAD, count) < 0 ? 0 : 1;
|
2011-03-26 17:45:33 +00:00
|
|
|
#endif
|
2011-03-02 15:35:45 +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_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
|
2011-02-25 15:17:15 +00:00
|
|
|
EXPORT(JVM_GetSockOpt)(jint socket, int level, int optionName,
|
|
|
|
char* optionValue, int* optionLength)
|
|
|
|
{
|
2011-03-18 03:42:15 +00:00
|
|
|
socklen_t length = *optionLength;
|
2011-02-25 15:17:15 +00:00
|
|
|
int rv = getsockopt(socket, level, optionName, optionValue, &length);
|
|
|
|
*optionLength = length;
|
|
|
|
return rv;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2011-02-23 01:37:42 +00:00
|
|
|
EXPORT(JVM_SetSockOpt)(jint socket, int level, int optionName,
|
|
|
|
const char* optionValue, int optionLength)
|
|
|
|
{
|
|
|
|
return setsockopt(socket, level, optionName, optionValue, optionLength);
|
|
|
|
}
|
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);
|
|
|
|
}
|
|
|
|
|
2011-04-10 03:17:15 +00:00
|
|
|
int JNICALL
|
|
|
|
GetVersion(Thread*)
|
|
|
|
{
|
|
|
|
return JMM_VERSION_1_0;
|
|
|
|
}
|
|
|
|
|
2011-08-06 00:06:29 +00:00
|
|
|
uint64_t
|
|
|
|
getInputArgumentArray(Thread* t, uintptr_t*)
|
|
|
|
{
|
|
|
|
object array = makeObjectArray
|
|
|
|
(t, type(t, Machine::StringType), t->m->argumentCount);
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < t->m->argumentCount; ++i) {
|
|
|
|
object argument = makeString(t, t->m->arguments[i]);
|
|
|
|
set(t, array, ArrayBody + (i * BytesPerWord), argument);
|
|
|
|
}
|
|
|
|
|
|
|
|
return reinterpret_cast<uintptr_t>(makeLocalReference(t, array));
|
|
|
|
}
|
|
|
|
|
|
|
|
jobjectArray JNICALL
|
|
|
|
GetInputArgumentArray(Thread* t)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<jobjectArray>(run(t, getInputArgumentArray, 0));
|
|
|
|
}
|
|
|
|
|
2011-04-10 03:17:15 +00:00
|
|
|
jint JNICALL
|
|
|
|
GetOptionalSupport(Thread*, jmmOptionalSupport* support)
|
|
|
|
{
|
|
|
|
memset(support, 0, sizeof(jmmOptionalSupport));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
jlong JNICALL
|
|
|
|
GetLongAttribute(Thread* t, jobject, jmmLongAttribute attribute)
|
|
|
|
{
|
|
|
|
const unsigned JMM_JVM_INIT_DONE_TIME_MS = 7;
|
|
|
|
|
|
|
|
switch (attribute) {
|
|
|
|
case JMM_JVM_INIT_DONE_TIME_MS:
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
jboolean JNICALL
|
|
|
|
GetBoolAttribute(Thread* t, jmmBoolAttribute attribute)
|
|
|
|
{
|
|
|
|
const unsigned JMM_THREAD_CPU_TIME = 24;
|
2012-02-22 00:32:20 +00:00
|
|
|
const unsigned JMM_THREAD_ALLOCATED_MEMORY = 25;
|
2011-04-10 03:17:15 +00:00
|
|
|
|
|
|
|
switch (attribute) {
|
|
|
|
case JMM_THREAD_CPU_TIME:
|
2012-02-22 00:32:20 +00:00
|
|
|
case JMM_THREAD_ALLOCATED_MEMORY:
|
2011-04-10 03:17:15 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
getMemoryManagers(Thread* t, uintptr_t*)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, makeObjectArray
|
|
|
|
(t, resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader),
|
|
|
|
"java/lang/management/MemoryManagerMXBean"), 0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
jobjectArray JNICALL
|
|
|
|
GetMemoryManagers(Thread* t, jobject)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<jobjectArray>(run(t, getMemoryManagers, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
getMemoryPools(Thread* t, uintptr_t*)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(makeLocalReference
|
|
|
|
(t, makeObjectArray
|
|
|
|
(t, resolveClass
|
|
|
|
(t, root(t, Machine::BootLoader),
|
|
|
|
"java/lang/management/MemoryPoolMXBean"), 0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
jobjectArray JNICALL
|
|
|
|
GetMemoryPools(Thread* t, jobject)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<jobjectArray>(run(t, getMemoryPools, 0));
|
|
|
|
}
|
|
|
|
|
2010-09-10 21:05:29 +00:00
|
|
|
extern "C" JNIEXPORT void* JNICALL
|
2011-04-10 03:17:15 +00:00
|
|
|
EXPORT(JVM_GetManagement)(jint version)
|
|
|
|
{
|
|
|
|
if (version == JMM_VERSION_1_0) {
|
|
|
|
JmmInterface* interface
|
|
|
|
= &(static_cast<MyClasspath*>
|
|
|
|
(local::globalMachine->classpath)->jmmInterface);
|
|
|
|
|
|
|
|
memset(interface, 0, sizeof(JmmInterface));
|
|
|
|
|
|
|
|
interface->GetVersion = GetVersion;
|
|
|
|
interface->GetOptionalSupport = GetOptionalSupport;
|
|
|
|
interface->GetLongAttribute = GetLongAttribute;
|
|
|
|
interface->GetBoolAttribute = GetBoolAttribute;
|
|
|
|
interface->GetMemoryManagers = GetMemoryManagers;
|
|
|
|
interface->GetMemoryPools = GetMemoryPools;
|
2011-08-06 00:06:29 +00:00
|
|
|
interface->GetInputArgumentArray = GetInputArgumentArray;
|
2011-04-10 03:17:15 +00:00
|
|
|
|
|
|
|
return interface;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
|
2013-04-17 21:12:58 +00:00
|
|
|
uint64_t
|
|
|
|
getEnclosingMethodInfo(Thread* t, uintptr_t* arguments)
|
2011-02-25 15:17:15 +00:00
|
|
|
{
|
2013-04-17 21:12:58 +00:00
|
|
|
jclass c = reinterpret_cast<jclass>(arguments[0]);
|
|
|
|
object class_ = jclassVmClass(t, *c);
|
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
object addendum = classAddendum(t, class_);
|
|
|
|
if (addendum) {
|
|
|
|
object enclosingClass = classAddendumEnclosingClass(t, addendum);
|
|
|
|
if (enclosingClass) {
|
|
|
|
PROTECT(t, enclosingClass);
|
|
|
|
|
|
|
|
object array = makeObjectArray(t, type(t, Machine::JobjectType), 3);
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
enclosingClass = getJClass
|
|
|
|
(t, resolveClass(t, classLoader(t, class_), enclosingClass));
|
|
|
|
|
|
|
|
set(t, array, ArrayBody, enclosingClass);
|
|
|
|
|
|
|
|
object enclosingMethod = classAddendumEnclosingMethod(t, addendum);
|
|
|
|
|
|
|
|
if (enclosingMethod) {
|
|
|
|
PROTECT(t, enclosingMethod);
|
|
|
|
|
|
|
|
object name = t->m->classpath->makeString
|
|
|
|
(t, pairFirst(t, enclosingMethod), 0,
|
|
|
|
byteArrayLength(t, pairFirst(t, enclosingMethod)) - 1);
|
|
|
|
|
|
|
|
set(t, array, ArrayBody + BytesPerWord, name);
|
|
|
|
|
|
|
|
object spec = t->m->classpath->makeString
|
|
|
|
(t, pairSecond(t, enclosingMethod), 0,
|
|
|
|
byteArrayLength(t, pairSecond(t, enclosingMethod)) - 1);
|
|
|
|
|
|
|
|
set(t, array, ArrayBody + (2 * BytesPerWord), spec);
|
|
|
|
}
|
|
|
|
|
|
|
|
return reinterpret_cast<uintptr_t>(makeLocalReference(t, array));
|
|
|
|
}
|
|
|
|
}
|
2011-02-25 15:17:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2013-04-17 21:12:58 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
|
|
|
EXPORT(JVM_GetEnclosingMethodInfo)(Thread* t, jclass c)
|
|
|
|
{
|
|
|
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c) };
|
|
|
|
|
|
|
|
return reinterpret_cast<jobjectArray>
|
|
|
|
(run(t, getEnclosingMethodInfo, arguments));
|
|
|
|
}
|
|
|
|
|
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
|
2012-02-18 22:17:10 +00:00
|
|
|
EXPORT(JVM_GetVersionInfo)(JNIEnv*, local::jvm_version_info* info, size_t size)
|
|
|
|
{
|
|
|
|
memset(info, 0, size);
|
|
|
|
info->jvm_version = 0x01070000;
|
|
|
|
}
|
2010-11-07 17:08:04 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
EXPORT(JVM_CX8Field)(JNIEnv*, jobject*, jfieldID*, jlong, jlong)
|
|
|
|
{ abort(); }
|
2010-09-10 21:05:29 +00:00
|
|
|
|
2012-03-11 22:26:46 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2012-03-18 00:47:22 +00:00
|
|
|
EXPORT(JVM_SetNativeThreadName)(JNIEnv*, jobject, jstring) { abort(); }
|
2012-03-11 22:26:46 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
} // namespace local
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
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)()
|
2012-03-13 16:31:08 +00:00
|
|
|
{
|
|
|
|
// hack: We don't want to expose thread interruption implementation
|
|
|
|
// details, so we give the class library a fake event to play with.
|
|
|
|
// This means that threads won't be interruptable when blocked in
|
|
|
|
// Process.waitFor.
|
|
|
|
static HANDLE fake = 0;
|
|
|
|
if (fake == 0) {
|
|
|
|
fake = CreateEvent(0, true, false, 0);
|
|
|
|
}
|
|
|
|
return fake;
|
|
|
|
}
|
2010-11-07 19:24:40 +00:00
|
|
|
|
|
|
|
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]);
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, char, countryChars, stringLength(t, country) + 1);
|
2010-11-07 19:24:40 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-03-26 15:53:47 +00:00
|
|
|
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
2010-11-07 19:24:40 +00:00
|
|
|
if (finder == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
System::Region* r = finder->find(ef.path);
|
|
|
|
if (r == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RESOURCE(t, System::Region*, r, r->dispose());
|
2010-11-07 19:24:40 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RESOURCE(t, char*, tmpDir, rmdir(tmpDir));
|
2010-11-07 19:24:40 +00:00
|
|
|
|
|
|
|
char libDir[MAX_PATH + 1];
|
|
|
|
vm::snprintf(libDir, MAX_PATH, "%s/lib", tmpDir);
|
|
|
|
if (mkdir(libDir) != 0 and errno != EEXIST) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RESOURCE(t, char*, libDir, rmdir(libDir));
|
2010-11-07 19:24:40 +00:00
|
|
|
|
|
|
|
char file[MAX_PATH + 1];
|
|
|
|
vm::snprintf(file, MAX_PATH, "%s/tzmappings", libDir);
|
|
|
|
FILE* out = vm::fopen(file, "wb");
|
|
|
|
if (out == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RESOURCE(t, char*, file, unlink(file));
|
|
|
|
THREAD_RESOURCE(t, FILE*, out, fclose(out));
|
2010-11-07 19:24:40 +00:00
|
|
|
|
|
|
|
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) {
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RESOURCE(t, char*, javaTZ, free(javaTZ));
|
|
|
|
|
|
|
|
return reinterpret_cast<int64_t>(makeString(t, "%s", javaTZ));
|
2010-11-07 19:24:40 +00:00
|
|
|
} 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
|