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; jstring value = 0;
jboolean isCopy; const char* chars = e->GetStringUTFChars(key, 0);
const char* chars = e->GetStringUTFChars(key, &isCopy);
if (chars) { if (chars) {
if (strcmp(chars, "line.separator") == 0) { if (strcmp(chars, "line.separator") == 0) {
value = e->NewStringUTF("\n"); value = e->NewStringUTF("\n");
} }
e->ReleaseStringUTFChars(key, chars);
} }
e->ReleaseStringUTFChars(key, chars);
return value; 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; 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) throws IOException;
private static native int read(int fd, byte[] b, int offset, int length) 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 { 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); 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; 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, int c) throws IOException;
public static native void write(int fd, byte[] b, int offset, int length) 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 { 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); 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) { public String substring(int start) {
return substring(start, length); return substring(start, length);
} }

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
#include "jnienv.h" #include "jnienv.h"
#include "machine.h" #include "machine.h"
namespace vm { using namespace vm;
namespace jni { namespace {
jsize jsize
GetStringUTFLength(Thread* t, jstring s) GetStringUTFLength(Thread* t, jstring s)
@ -41,16 +41,84 @@ NewStringUTF(Thread* t, const char* chars)
} }
void 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)); memset(table, 0, sizeof(JNIEnvVTable));
table->GetStringUTFLength = GetStringUTFLength; table->GetStringUTFLength = ::GetStringUTFLength;
table->GetStringUTFChars = GetStringUTFChars; table->GetStringUTFChars = ::GetStringUTFChars;
table->ReleaseStringUTFChars = ReleaseStringUTFChars; table->ReleaseStringUTFChars = ::ReleaseStringUTFChars;
table->NewStringUTF = NewStringUTF; table->NewStringUTF = ::NewStringUTF;
table->GetByteArrayRegion = ::GetByteArrayRegion;
table->SetByteArrayRegion = ::SetByteArrayRegion;
table->FindClass = ::FindClass;
table->ThrowNew = ::ThrowNew;
table->ExceptionCheck = ::ExceptionCheck;
} }
} // namespace jni
} // namespace vm } // namespace vm

View File

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

View File

@ -468,7 +468,7 @@ makeJNIName(Thread* t, object method, bool decorate)
for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1 for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
and byteArrayBody(t, methodSpec, i) != ')'; ++i) and byteArrayBody(t, methodSpec, i) != ')'; ++i)
{ {
index += mangle(byteArrayBody(t, className, i), index += mangle(byteArrayBody(t, methodSpec, i),
&byteArrayBody(t, name, index)); &byteArrayBody(t, name, index));
} }
} }
@ -962,12 +962,12 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (flags & ACC_NATIVE) { if (flags & ACC_NATIVE) {
object p = hashMapFindNode object p = hashMapFindNode
(t, nativeMap, method, methodHash, methodEqual); (t, nativeMap, methodName(t, method), byteArrayHash, byteArrayEqual);
if (p) { if (p) {
set(t, tripleSecond(t, p), method); set(t, tripleSecond(t, p), method);
} else { } 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); PROTECT(t, method);
object overloaded = hashMapFind object overloaded = hashMapFind
(t, nativeMap, method, methodHash, methodEqual); (t, nativeMap, methodName(t, method), byteArrayHash, byteArrayEqual);
object jniName = makeJNIName(t, method, overloaded); object jniName = makeJNIName(t, method, overloaded);
set(t, methodCode(t, method), jniName); set(t, methodCode(t, method), jniName);
@ -1283,7 +1283,7 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
tenuredWeakReferences(0), tenuredWeakReferences(0),
unsafe(false) unsafe(false)
{ {
jni::populate(&jniEnvVTable); populateJNITable(&jniEnvVTable);
if (not system->success(system->make(&stateLock)) or if (not system->success(system->make(&stateLock)) or
not system->success(system->make(&heapLock)) 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->builtinMap = makeHashMap(this, NormalMap, 0, 0);
m->monitorMap = makeHashMap(this, WeakMap, 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)); t->javaThread = makeThread(t, 0, 0, reinterpret_cast<int64_t>(t));
} else { } 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 object
makeByteArray(Thread* t, const char* format, ...) makeByteArray(Thread* t, const char* format, ...)
{ {

View File

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

View File

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