mirror of
https://github.com/corda/corda.git
synced 2025-06-16 06:08:13 +00:00
java/io bugfixes and coverage; jni bugfixes; minor refactoring
This commit is contained in:
261
classpath/java-io.cpp
Normal file
261
classpath/java-io.cpp
Normal 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);
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
61
classpath/java/io/File.java
Normal file
61
classpath/java/io/File.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
2
makefile
2
makefile
@ -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
|
||||||
|
120
src/builtin.cpp
120
src/builtin.cpp
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -5,12 +5,8 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
namespace jni {
|
|
||||||
|
|
||||||
void
|
void
|
||||||
populate(JNIEnvVTable* table);
|
populateJNITable(JNIEnvVTable* table);
|
||||||
|
|
||||||
} // namespace jni
|
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
|
@ -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, ...)
|
||||||
{
|
{
|
||||||
|
@ -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, ...);
|
||||||
|
|
||||||
|
22
src/run.cpp
22
src/run.cpp
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user