java/io bugfixes and coverage; jni bugfixes; minor refactoring

This commit is contained in:
Joel Dice 2007-07-26 18:06:05 -06:00
parent b00fcd4463
commit 7212ba1c30
17 changed files with 570 additions and 264 deletions

261
classpath/java-io.cpp Normal file
View File

@ -0,0 +1,261 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "jni.h"
#undef JNIEXPORT
#define JNIEXPORT __attribute__ ((visibility("default")))
#ifdef WIN32
# include <io.h>
# define OPEN _open
# define CLOSE _close
# define READ _read
# define WRITE _write
# define STAT _stat
# define STRUCT_STAT struct _stat
# define MKDIR(path, mode) _mkdir(path)
# define CREAT _creat
# define OPEN_MASK O_BINARY
#else
# include <unistd.h>
# define OPEN open
# define CLOSE close
# define READ read
# define WRITE write
# define STAT stat
# define STRUCT_STAT struct stat
# define MKDIR mkdir
# define CREAT creat
# define OPEN_MASK 0
#endif
namespace {
inline void
throwNew(JNIEnv* e, const char* class_, const char* message)
{
jclass c = e->FindClass(class_);
if (c) {
e->ThrowNew(c, message);
e->DeleteLocalRef(c);
}
}
inline bool
exists(const char* path)
{
STRUCT_STAT s;
return STAT(path, &s) == 0;
}
inline int
doOpen(JNIEnv* e, const char* path, int mask)
{
int fd = OPEN(path, mask | OPEN_MASK, S_IRUSR | S_IWUSR);
if (fd == -1) {
throwNew(e, "java/lang/IOException", strerror(errno));
}
return fd;
}
inline void
doClose(JNIEnv* e, jint fd)
{
int r = CLOSE(fd);
if (r == -1) {
throwNew(e, "java/lang/IOException", strerror(errno));
}
}
inline int
doRead(JNIEnv* e, jint fd, jbyte* data, jint length)
{
int r = READ(fd, data, length);
if (r > 0) {
return r;
} else if (r == 0) {
return -1;
} else {
throwNew(e, "java/lang/IOException", strerror(errno));
return 0;
}
}
inline void
doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
{
int r = WRITE(fd, data, length);
if (r != length) {
throwNew(e, "java/lang/IOException", strerror(errno));
}
}
} // namespace
extern "C" JNIEXPORT jstring JNICALL
Java_java_io_File_toAbsolutePath(JNIEnv* /*e*/, jclass, jstring path)
{
// todo
return path;
}
extern "C" JNIEXPORT jlong JNICALL
Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
if (chars) {
STRUCT_STAT s;
int r = STAT(chars, &s);
if (r == 0) {
return s.st_size;
}
e->ReleaseStringUTFChars(path, chars);
}
return -1;
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
if (chars) {
if (not exists(chars)) {
int r = ::MKDIR(chars, 0700);
if (r != 0) {
throwNew(e, "java/lang/IOException", strerror(errno));
}
}
e->ReleaseStringUTFChars(path, chars);
}
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
if (chars) {
if (not exists(chars)) {
int fd = CREAT(chars, 0600);
if (fd == -1) {
throwNew(e, "java/lang/IOException", strerror(errno));
} else {
doClose(e, fd);
}
}
e->ReleaseStringUTFChars(path, chars);
}
}
extern "C" JNIEXPORT jboolean JNICALL
Java_java_io_File_exists(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
if (chars) {
bool v = exists(chars);
e->ReleaseStringUTFChars(path, chars);
return v;
} else {
return false;
}
}
extern "C" JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_open(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
if (chars) {
int fd = doOpen(e, chars, O_RDONLY);
e->ReleaseStringUTFChars(path, chars);
return fd;
} else {
return -1;
}
}
extern "C" JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_read__I(JNIEnv* e, jclass, jint fd)
{
jbyte data;
int r = doRead(e, fd, &data, 1);
if (r <= 0) {
return -1;
} else {
return data;
}
}
extern "C" JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_read__I_3BII
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
{
jbyte* data = static_cast<jbyte*>(malloc(length));
if (data == 0) {
throwNew(e, "java/lang/OutOfMemoryError", 0);
return 0;
}
int r = doRead(e, fd, data, length);
e->SetByteArrayRegion(b, offset, length, data);
free(data);
return r;
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_FileInputStream_close(JNIEnv* e, jclass, jint fd)
{
doClose(e, fd);
}
extern "C" JNIEXPORT jint JNICALL
Java_java_io_FileOutputStream_open(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
if (chars) {
int fd = doOpen(e, chars, O_WRONLY | O_CREAT);
e->ReleaseStringUTFChars(path, chars);
return fd;
} else {
return -1;
}
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c)
{
jbyte data = c;
doWrite(e, fd, &data, 1);
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_write__I_3BII
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
{
jbyte* data = static_cast<jbyte*>(malloc(length));
if (data == 0) {
throwNew(e, "java/lang/OutOfMemoryError", 0);
return;
}
e->GetByteArrayRegion(b, offset, length, data);
if (not e->ExceptionCheck()) {
doWrite(e, fd, data, length);
}
free(data);
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint fd)
{
doClose(e, fd);
}

View File

@ -9,14 +9,13 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring key)
{
jstring value = 0;
jboolean isCopy;
const char* chars = e->GetStringUTFChars(key, &isCopy);
const char* chars = e->GetStringUTFChars(key, 0);
if (chars) {
if (strcmp(chars, "line.separator") == 0) {
value = e->NewStringUTF("\n");
}
e->ReleaseStringUTFChars(key, chars);
}
e->ReleaseStringUTFChars(key, chars);
return value;
}

View File

@ -0,0 +1,61 @@
package java.io;
public class File {
private final String path;
public File(String path) {
if (path == null) throw new NullPointerException();
this.path = path;
}
public File(String parent, String child) {
this(parent + "/" + child);
}
public File(File parent, String child) {
this(parent.getPath() + "/" + child);
}
public String getName() {
int index = path.lastIndexOf("/");
if (index >= 0) {
return path.substring(index + 1);
} else {
return path;
}
}
public String getPath() {
return path;
}
private static native String toAbsolutePath(String path);
public String getAbsolutePath() {
return toAbsolutePath(path);
}
private static native long length(String path);
public long length() {
return length(path);
}
private static native boolean exists(String path);
public boolean exists() {
return exists(path);
}
private static native void mkdir(String path);
public void mkdir() {
mkdir(path);
}
private static native void createNewFile(String path);
public void createNewFile() {
createNewFile(path);
}
}

View File

@ -1,79 +0,0 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "jni.h"
#undef JNIEXPORT
#define JNIEXPORT __attribute__ ((visibility("default")))
#ifdef WIN32
# include <io.h>
# define CLOSE _close
# define READ _read
#else
# include <unistd.h>
# define CLOSE close
# define READ read
#endif
namespace {
int
doRead(JNIEnv* e, jint fd, jbyte* data, jint length)
{
int r = READ(fd, data, length);
if (r > 0) {
return r;
} else if (r == 0) {
return -1;
} else {
e->ThrowNew(e->FindClass("java/lang/IOException"), strerror(errno));
return 0;
}
}
} // namespace
extern "C" JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_read__I(JNIEnv* e, jclass, jint fd)
{
jbyte data;
int r = doRead(e, fd, &data, 1);
if (r <= 0) {
return -1;
} else {
return data;
}
}
extern "C" JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_read__I_3BII
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
{
jbyte* data = static_cast<jbyte*>(malloc(length));
if (data == 0) {
e->ThrowNew(e->FindClass("java/lang/OutOfMemoryError"), 0);
return 0;
}
int r = doRead(e, fd, data, length);
e->SetByteArrayRegion(b, offset, length, data);
free(data);
return r;
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_FileInputStream_close(JNIEnv* e, jclass, jint fd)
{
int r = CLOSE(fd);
if (r == -1) {
e->ThrowNew(e->FindClass("java/lang/IOException"), strerror(errno));
}
}

View File

@ -7,6 +7,16 @@ public class FileInputStream extends InputStream {
this.fd = fd.value;
}
public FileInputStream(String path) throws IOException {
fd = open(path);
}
public FileInputStream(File file) throws IOException {
this(file.getPath());
}
private static native int open(String path) throws IOException;
private static native int read(int fd) throws IOException;
private static native int read(int fd, byte[] b, int offset, int length)
@ -19,6 +29,14 @@ public class FileInputStream extends InputStream {
}
public int read(byte[] b, int offset, int length) throws IOException {
if (b == null) {
throw new NullPointerException();
}
if (offset < 0 || offset + length > b.length) {
throw new ArrayIndexOutOfBoundsException();
}
return read(fd, b, offset, length);
}

View File

@ -1,69 +0,0 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "jni.h"
#undef JNIEXPORT
#define JNIEXPORT __attribute__ ((visibility("default")))
#ifdef WIN32
# include <io.h>
# define CLOSE _close
# define WRITE _write
#else
# include <unistd.h>
# define CLOSE close
# define WRITE write
#endif
namespace {
void
doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
{
int r = WRITE(fd, data, length);
if (r != length) {
e->ThrowNew(e->FindClass("java/lang/IOException"), strerror(errno));
}
}
} // namespace
extern "C" JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c)
{
jbyte data = c;
doWrite(e, fd, &data, 1);
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_write__I_3BII
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
{
jbyte* data = static_cast<jbyte*>(malloc(length));
if (data == 0) {
e->ThrowNew(e->FindClass("java/lang/OutOfMemoryError"), 0);
return;
}
e->GetByteArrayRegion(b, offset, length, data);
if (not e->ExceptionCheck()) {
doWrite(e, fd, data, length);
}
free(data);
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint fd)
{
int r = CLOSE(fd);
if (r == -1) {
e->ThrowNew(e->FindClass("java/lang/IOException"), strerror(errno));
}
}

View File

@ -7,6 +7,16 @@ public class FileOutputStream extends OutputStream {
this.fd = fd.value;
}
public FileOutputStream(String path) throws IOException {
fd = open(path);
}
public FileOutputStream(File file) throws IOException {
this(file.getPath());
}
private static native int open(String path) throws IOException;
public static native void write(int fd, int c) throws IOException;
public static native void write(int fd, byte[] b, int offset, int length)
@ -19,6 +29,14 @@ public class FileOutputStream extends OutputStream {
}
public void write(byte[] b, int offset, int length) throws IOException {
if (b == null) {
throw new NullPointerException();
}
if (offset < 0 || offset + length > b.length) {
throw new ArrayIndexOutOfBoundsException();
}
write(fd, b, offset, length);
}

View File

@ -87,6 +87,42 @@ public final class String implements Comparable<String> {
}
}
public int indexOf(String s) {
if (s.length == 0) return 0;
for (int i = 0; i < length - s.length; ++i) {
int j = 0;
for (; j < s.length; ++j) {
if (charAt(i + j) != s.charAt(j)) {
break;
}
}
if (j == s.length) {
return i;
}
}
return -1;
}
public int lastIndexOf(String s) {
if (s.length == 0) return length;
for (int i = length - s.length; i >= 0; --i) {
int j = 0;
for (; j < s.length && i + j < length; ++j) {
if (charAt(i + j) != s.charAt(j)) {
break;
}
}
if (j == s.length) {
return i;
}
}
return -1;
}
public String substring(int start) {
return substring(start, length);
}

View File

@ -16,7 +16,7 @@ src = src
classpath = classpath
test = test
input = $(cls)/Hello.class
input = $(cls)/Reflection.class
cxx = g++
cc = gcc

View File

@ -23,14 +23,8 @@ replace(char a, char b, char* c)
for (; *c; ++c) if (*c == a) *c = b;
}
} // namespace
namespace vm {
namespace builtin {
jstring
toString(Thread* t, jobject this_)
Object_toString(Thread* t, jobject this_)
{
object s = makeString
(t, "%s@%p",
@ -41,31 +35,31 @@ toString(Thread* t, jobject this_)
}
jclass
getClass(Thread* t, jobject this_)
Object_getClass(Thread* t, jobject this_)
{
return pushReference(t, objectClass(t, *this_));
}
void
wait(Thread* t, jobject this_, jlong milliseconds)
Object_wait(Thread* t, jobject this_, jlong milliseconds)
{
vm::wait(t, *this_, milliseconds);
}
void
notify(Thread* t, jobject this_)
Object_notify(Thread* t, jobject this_)
{
vm::notify(t, *this_);
}
void
notifyAll(Thread* t, jobject this_)
Object_notifyAll(Thread* t, jobject this_)
{
vm::notifyAll(t, *this_);
}
jclass
forName(Thread* t, jclass, jstring name)
Class_forName(Thread* t, jclass, jstring name)
{
if (LIKELY(name)) {
object n = makeByteArray(t, stringLength(t, *name) + 1, false);
@ -95,7 +89,7 @@ forName(Thread* t, jclass, jstring name)
}
jboolean
isAssignableFrom(Thread* t, jobject this_, jclass that)
Class_isAssignableFrom(Thread* t, jobject this_, jclass that)
{
if (LIKELY(that)) {
return vm::isAssignableFrom(t, *this_, *that);
@ -106,7 +100,7 @@ isAssignableFrom(Thread* t, jobject this_, jclass that)
}
jobject
get(Thread* t, jobject this_, jobject instancep)
Field_get(Thread* t, jobject this_, jobject instancep)
{
object field = *this_;
@ -169,7 +163,8 @@ get(Thread* t, jobject this_, jobject instancep)
}
jobject
invoke(Thread* t, jobject this_, jobject instancep, jobjectArray argumentsp)
Method_invoke(Thread* t, jobject this_, jobject instancep,
jobjectArray argumentsp)
{
object method = *this_;
@ -206,25 +201,9 @@ invoke(Thread* t, jobject this_, jobject instancep, jobjectArray argumentsp)
return 0;
}
jobject
currentThread(Thread* t, jclass)
{
return pushReference(t, t->javaThread);
}
void
sleep(Thread* t, jclass, jlong milliseconds)
{
if (milliseconds == 0) milliseconds = INT64_MAX;
ENTER(t, Thread::IdleState);
t->vm->system->sleep(milliseconds);
}
void
arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
jint dstOffset, jint length)
System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
jint dstOffset, jint length)
{
if (LIKELY(src and dst)) {
object s = *src;
@ -263,13 +242,13 @@ arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
}
jlong
currentTimeMillis(Thread* t, jclass)
System_currentTimeMillis(Thread* t, jclass)
{
return t->vm->system->now();
}
void
loadLibrary(Thread* t, jobject, jstring name)
Runtime_loadLibrary(Thread* t, jobject, jstring name)
{
if (LIKELY(name)) {
char n[stringLength(t, *name) + 1];
@ -297,7 +276,7 @@ loadLibrary(Thread* t, jobject, jstring name)
}
void
gc(Thread* t, jobject)
Runtime_gc(Thread* t, jobject)
{
ENTER(t, Thread::ExclusiveState);
@ -305,13 +284,13 @@ gc(Thread* t, jobject)
}
void
exit(Thread* t, jobject, jint code)
Runtime_exit(Thread* t, jobject, jint code)
{
t->vm->system->exit(code);
}
jobject
trace(Thread* t, jclass, jint skipCount)
Throwable_trace(Thread* t, jclass, jint skipCount)
{
int frame = t->frame;
while (skipCount-- and frame >= 0) {
@ -334,7 +313,7 @@ trace(Thread* t, jclass, jint skipCount)
}
jarray
resolveTrace(Thread* t, jclass, jobject trace)
Throwable_resolveTrace(Thread* t, jclass, jobject trace)
{
unsigned length = arrayLength(t, *trace);
object array = makeObjectArray
@ -367,8 +346,23 @@ resolveTrace(Thread* t, jclass, jobject trace)
return pushReference(t, array);
}
jobject
Thread_currentThread(Thread* t, jclass)
{
return pushReference(t, t->javaThread);
}
void
start(Thread* t, jobject this_)
Thread_sleep(Thread* t, jclass, jlong milliseconds)
{
if (milliseconds == 0) milliseconds = INT64_MAX;
ENTER(t, Thread::IdleState);
t->vm->system->sleep(milliseconds);
}
void
Thread_start(Thread* t, jobject this_)
{
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, *this_));
if (p) {
@ -413,56 +407,62 @@ start(Thread* t, jobject this_)
}
}
} // namespace
namespace vm {
void
populate(Thread* t, object map)
populateBuiltinMap(Thread* t, object map)
{
struct {
const char* key;
void* value;
} builtins[] = {
{ "Java_java_lang_Class_forName",
reinterpret_cast<void*>(forName) },
reinterpret_cast<void*>(::Class_forName) },
{ "Java_java_lang_Class_isAssignableFrom",
reinterpret_cast<void*>(isAssignableFrom) },
reinterpret_cast<void*>(::Class_isAssignableFrom) },
{ "Java_java_lang_System_arraycopy",
reinterpret_cast<void*>(arraycopy) },
reinterpret_cast<void*>(::System_arraycopy) },
{ "Java_java_lang_System_currentTimeMillis",
reinterpret_cast<void*>(::System_currentTimeMillis) },
{ "Java_java_lang_Runtime_loadLibrary",
reinterpret_cast<void*>(loadLibrary) },
reinterpret_cast<void*>(::Runtime_loadLibrary) },
{ "Java_java_lang_Runtime_gc",
reinterpret_cast<void*>(gc) },
reinterpret_cast<void*>(::Runtime_gc) },
{ "Java_java_lang_Runtiime_exit",
reinterpret_cast<void*>(exit) },
reinterpret_cast<void*>(::Runtime_exit) },
{ "Java_java_lang_Thread_doStart",
reinterpret_cast<void*>(start) },
reinterpret_cast<void*>(::Thread_start) },
{ "Java_java_lang_Thread_currentThread",
reinterpret_cast<void*>(currentThread) },
reinterpret_cast<void*>(::Thread_currentThread) },
{ "Java_java_lang_Thread_sleep",
reinterpret_cast<void*>(sleep) },
reinterpret_cast<void*>(::Thread_sleep) },
{ "Java_java_lang_Throwable_resolveTrace",
reinterpret_cast<void*>(resolveTrace) },
reinterpret_cast<void*>(::Throwable_resolveTrace) },
{ "Java_java_lang_Throwable_trace",
reinterpret_cast<void*>(trace) },
reinterpret_cast<void*>(::Throwable_trace) },
{ "Java_java_lang_Object_getClass",
reinterpret_cast<void*>(getClass) },
reinterpret_cast<void*>(::Object_getClass) },
{ "Java_java_lang_Object_notify",
reinterpret_cast<void*>(notify) },
reinterpret_cast<void*>(::Object_notify) },
{ "Java_java_lang_Object_notifyAll",
reinterpret_cast<void*>(notifyAll) },
reinterpret_cast<void*>(::Object_notifyAll) },
{ "Java_java_lang_Object_toString",
reinterpret_cast<void*>(toString) },
reinterpret_cast<void*>(::Object_toString) },
{ "Java_java_lang_Object_wait",
reinterpret_cast<void*>(wait) },
reinterpret_cast<void*>(::Object_wait) },
{ "Java_java_lang_reflect_Field_get",
reinterpret_cast<void*>(get) },
reinterpret_cast<void*>(::Field_get) },
{ "Java_java_lang_reflect_Method_invoke",
reinterpret_cast<void*>(invoke) },
reinterpret_cast<void*>(::Method_invoke) },
{ 0, 0 }
};
@ -476,6 +476,4 @@ populate(Thread* t, object map)
}
}
} // namespace builtin
} // namespace vm

View File

@ -5,12 +5,8 @@
namespace vm {
namespace builtin {
void
populate(Thread* t, object map);
} // namespace builtin
populateBuiltinMap(Thread* t, object map);
} // namespace vm

View File

@ -1,9 +1,9 @@
#include "jnienv.h"
#include "machine.h"
namespace vm {
using namespace vm;
namespace jni {
namespace {
jsize
GetStringUTFLength(Thread* t, jstring s)
@ -41,16 +41,84 @@ NewStringUTF(Thread* t, const char* chars)
}
void
populate(JNIEnvVTable* table)
GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
jbyte* dst)
{
ENTER(t, Thread::ActiveState);
memcpy(dst, &byteArrayBody(t, *array, offset), length);
}
void
SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
const jbyte* src)
{
ENTER(t, Thread::ActiveState);
memcpy(&byteArrayBody(t, *array, offset), src, length);
}
jclass
FindClass(Thread* t, const char* name)
{
ENTER(t, Thread::ActiveState);
object n = makeByteArray(t, strlen(name) + 1, false);
memcpy(&byteArrayBody(t, n, 0), name, byteArrayLength(t, n));
return pushReference(t, resolveClass(t, n));
}
jint
ThrowNew(Thread* t, jclass c, const char* message)
{
if (t->exception) {
return -1;
}
ENTER(t, Thread::ActiveState);
object m = 0;
PROTECT(t, m);
if (message) {
m = makeString(t, "%s", message);
}
object trace = makeTrace(t);
PROTECT(t, trace);
t->exception = make(t, *c);
set(t, throwableMessageUnsafe(t, t->exception), m);
set(t, throwableTraceUnsafe(t, t->exception), trace);
return 0;
}
jboolean
ExceptionCheck(Thread* t)
{
return t->exception != 0;
}
} // namespace
namespace vm {
void
populateJNITable(JNIEnvVTable* table)
{
memset(table, 0, sizeof(JNIEnvVTable));
table->GetStringUTFLength = GetStringUTFLength;
table->GetStringUTFChars = GetStringUTFChars;
table->ReleaseStringUTFChars = ReleaseStringUTFChars;
table->NewStringUTF = NewStringUTF;
table->GetStringUTFLength = ::GetStringUTFLength;
table->GetStringUTFChars = ::GetStringUTFChars;
table->ReleaseStringUTFChars = ::ReleaseStringUTFChars;
table->NewStringUTF = ::NewStringUTF;
table->GetByteArrayRegion = ::GetByteArrayRegion;
table->SetByteArrayRegion = ::SetByteArrayRegion;
table->FindClass = ::FindClass;
table->ThrowNew = ::ThrowNew;
table->ExceptionCheck = ::ExceptionCheck;
}
} // namespace jni
} // namespace vm

View File

@ -5,12 +5,8 @@
namespace vm {
namespace jni {
void
populate(JNIEnvVTable* table);
} // namespace jni
populateJNITable(JNIEnvVTable* table);
} // namespace vm

View File

@ -468,7 +468,7 @@ makeJNIName(Thread* t, object method, bool decorate)
for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
and byteArrayBody(t, methodSpec, i) != ')'; ++i)
{
index += mangle(byteArrayBody(t, className, i),
index += mangle(byteArrayBody(t, methodSpec, i),
&byteArrayBody(t, name, index));
}
}
@ -962,12 +962,12 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (flags & ACC_NATIVE) {
object p = hashMapFindNode
(t, nativeMap, method, methodHash, methodEqual);
(t, nativeMap, methodName(t, method), byteArrayHash, byteArrayEqual);
if (p) {
set(t, tripleSecond(t, p), method);
} else {
hashMapInsert(t, nativeMap, method, 0, methodHash);
hashMapInsert(t, nativeMap, methodName(t, method), 0, byteArrayHash);
}
}
@ -981,7 +981,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
PROTECT(t, method);
object overloaded = hashMapFind
(t, nativeMap, method, methodHash, methodEqual);
(t, nativeMap, methodName(t, method), byteArrayHash, byteArrayEqual);
object jniName = makeJNIName(t, method, overloaded);
set(t, methodCode(t, method), jniName);
@ -1283,7 +1283,7 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
tenuredWeakReferences(0),
unsafe(false)
{
jni::populate(&jniEnvVTable);
populateJNITable(&jniEnvVTable);
if (not system->success(system->make(&stateLock)) or
not system->success(system->make(&heapLock)) or
@ -1374,7 +1374,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
m->builtinMap = makeHashMap(this, NormalMap, 0, 0);
m->monitorMap = makeHashMap(this, WeakMap, 0, 0);
builtin::populate(t, m->builtinMap);
populateBuiltinMap(t, m->builtinMap);
t->javaThread = makeThread(t, 0, 0, reinterpret_cast<int64_t>(t));
} else {
@ -1585,6 +1585,28 @@ allocate2(Thread* t, unsigned sizeInBytes)
}
}
object
make(Thread* t, object class_)
{
PROTECT(t, class_);
unsigned sizeInBytes = pad(classFixedSize(t, class_));
object instance = allocate(t, sizeInBytes);
*static_cast<object*>(instance) = class_;
memset(static_cast<object*>(instance) + 1, 0,
sizeInBytes - sizeof(object));
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
PROTECT(t, instance);
ACQUIRE(t, t->vm->referenceLock);
jreferenceNextUnsafe(t, instance) = t->vm->weakReferences;
t->vm->weakReferences = instance;
}
return instance;
}
object
makeByteArray(Thread* t, const char* format, ...)
{

View File

@ -6,8 +6,6 @@
#include "heap.h"
#include "class-finder.h"
#define JNIEXPORT __attribute__ ((visibility("default")))
#define JNIIMPORT __attribute__ ((visibility("hidden")))
#define JNICALL
#define PROTECT(thread, name) \
@ -22,7 +20,7 @@
namespace vm {
const bool Verbose = false;
const bool DebugRun = false;
const bool DebugRun = true;
const bool DebugStack = false;
const bool DebugMonitors = false;
@ -1471,6 +1469,9 @@ makeUnsatisfiedLinkError(Thread* t, object message)
return makeUnsatisfiedLinkError(t, message, trace, 0);
}
object
make(Thread* t, object class_);
object
makeByteArray(Thread* t, const char* format, ...);

View File

@ -76,28 +76,6 @@ popFrame(Thread* t)
}
}
object
make(Thread* t, object class_)
{
PROTECT(t, class_);
unsigned sizeInBytes = pad(classFixedSize(t, class_));
object instance = allocate(t, sizeInBytes);
*static_cast<object*>(instance) = class_;
memset(static_cast<object*>(instance) + 1, 0,
sizeInBytes - sizeof(object));
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
PROTECT(t, instance);
ACQUIRE(t, t->vm->referenceLock);
jreferenceNextUnsafe(t, instance) = t->vm->weakReferences;
t->vm->weakReferences = instance;
}
return instance;
}
inline void
setStatic(Thread* t, object field, object value)
{

View File

@ -36,6 +36,8 @@ for test in ${tests}; do
fi
done
echo
if [ -n "${trouble}" ]; then
printf "\nsee ${log} for output\n"
printf "see ${log} for output\n"
fi