From 9ab88ef619985ca00a077e5493b483e4106fabb0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 25 Jul 2007 18:48:28 -0600 Subject: [PATCH] a static jni method takes the jclass for that method as its second argument; simplify pad() and divide(), and rename divide() to ceiling(); sketch FileInputStream.cpp and FileOutputStream.cpp --- classpath/java/io/FileDescriptor.java | 2 +- classpath/java/io/FileInputStream.cpp | 79 +++++++++++++++++++++++++ classpath/java/io/FileInputStream.java | 23 +++++-- classpath/java/io/FileOutputStream.cpp | 69 +++++++++++++++++++++ classpath/java/io/FileOutputStream.java | 22 +++++-- classpath/java/lang/System.cpp | 3 +- makefile | 4 +- src/builtin.cpp | 16 ++--- src/common.h | 9 ++- src/heap.cpp | 4 +- src/machine.cpp | 8 +-- src/machine.h | 12 ++-- src/run.cpp | 27 ++++++--- test/test.sh | 4 +- 14 files changed, 233 insertions(+), 49 deletions(-) create mode 100644 classpath/java/io/FileInputStream.cpp create mode 100644 classpath/java/io/FileOutputStream.cpp diff --git a/classpath/java/io/FileDescriptor.java b/classpath/java/io/FileDescriptor.java index 357564ed6d..c0404df92f 100644 --- a/classpath/java/io/FileDescriptor.java +++ b/classpath/java/io/FileDescriptor.java @@ -5,7 +5,7 @@ public class FileDescriptor { public static final FileDescriptor out = new FileDescriptor(1); public static final FileDescriptor err = new FileDescriptor(2); - private final int value; + final int value; private FileDescriptor(int value) { this.value = value; diff --git a/classpath/java/io/FileInputStream.cpp b/classpath/java/io/FileInputStream.cpp new file mode 100644 index 0000000000..0da02c68f1 --- /dev/null +++ b/classpath/java/io/FileInputStream.cpp @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include + +#include "jni.h" + +#undef JNIEXPORT +#define JNIEXPORT __attribute__ ((visibility("default"))) + +#ifdef WIN32 +# include +# define CLOSE _close +# define READ _read +#else +# include +# 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(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)); + } +} diff --git a/classpath/java/io/FileInputStream.java b/classpath/java/io/FileInputStream.java index 33f1a895e9..d01f77325f 100644 --- a/classpath/java/io/FileInputStream.java +++ b/classpath/java/io/FileInputStream.java @@ -1,15 +1,28 @@ package java.io; public class FileInputStream extends InputStream { - private final FileDescriptor fd; + private final int fd; public FileInputStream(FileDescriptor fd) { - this.fd = fd; + this.fd = fd.value; } - public native int read() throws IOException; + private static native int read(int fd) throws IOException; - public native int read(byte[] b, int offset, int length) throws IOException; + private static native int read(int fd, byte[] b, int offset, int length) + throws IOException; - public native void close() throws IOException; + public static native void close(int fd) throws IOException; + + public int read() throws IOException { + return read(fd); + } + + public int read(byte[] b, int offset, int length) throws IOException { + return read(fd, b, offset, length); + } + + public void close() throws IOException { + close(fd); + } } diff --git a/classpath/java/io/FileOutputStream.cpp b/classpath/java/io/FileOutputStream.cpp new file mode 100644 index 0000000000..3fcc3d47a6 --- /dev/null +++ b/classpath/java/io/FileOutputStream.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include + +#include "jni.h" + +#undef JNIEXPORT +#define JNIEXPORT __attribute__ ((visibility("default"))) + +#ifdef WIN32 +# include +# define CLOSE _close +# define WRITE _write +#else +# include +# 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(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)); + } +} diff --git a/classpath/java/io/FileOutputStream.java b/classpath/java/io/FileOutputStream.java index 6dec42f6ca..e6b99a3222 100644 --- a/classpath/java/io/FileOutputStream.java +++ b/classpath/java/io/FileOutputStream.java @@ -1,16 +1,28 @@ package java.io; public class FileOutputStream extends OutputStream { - private final FileDescriptor fd; + private final int fd; public FileOutputStream(FileDescriptor fd) { - this.fd = fd; + this.fd = fd.value; } - public native void write(int c) throws IOException; + public static native void write(int fd, int c) throws IOException; - public native void write(byte[] b, int offset, int length) + public static native void write(int fd, byte[] b, int offset, int length) throws IOException; - public native void close() throws IOException; + public static native void close(int fd) throws IOException; + + public void write(int c) throws IOException { + write(fd, c); + } + + public void write(byte[] b, int offset, int length) throws IOException { + write(fd, b, offset, length); + } + + public void close() throws IOException { + close(fd); + } } diff --git a/classpath/java/lang/System.cpp b/classpath/java/lang/System.cpp index b4f0351d40..7cb7402375 100644 --- a/classpath/java/lang/System.cpp +++ b/classpath/java/lang/System.cpp @@ -1,4 +1,3 @@ -#include "stdio.h" #include "string.h" #include "jni.h" @@ -6,7 +5,7 @@ #define JNIEXPORT __attribute__ ((visibility("default"))) extern "C" JNIEXPORT jstring JNICALL -Java_java_lang_System_getProperty(JNIEnv* e, jstring key) +Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring key) { jstring value = 0; diff --git a/makefile b/makefile index d7b7654b52..ca9db33a67 100644 --- a/makefile +++ b/makefile @@ -16,7 +16,7 @@ src = src classpath = classpath test = test -input = $(cls)/Threads.class +input = $(cls)/Hello.class cxx = g++ cc = gcc @@ -55,7 +55,7 @@ java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(cls)/%.class,$(x))) stdcpp-sources = $(src)/stdc++.cpp stdcpp-objects = $(call cpp-objects,$(stdcpp-sources),$(src)) -jni-sources = $(classpath)/java/lang/System.cpp +jni-sources = $(shell find $(classpath) -name '*.cpp') jni-objects = $(call cpp-objects,$(jni-sources),$(classpath)) jni-cflags = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux $(cflags) jni-library = $(bld)/libnatives.so diff --git a/src/builtin.cpp b/src/builtin.cpp index 27a5cc4e0b..31b93b87af 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -65,7 +65,7 @@ notifyAll(Thread* t, jobject this_) } jclass -forName(Thread* t, jstring name) +forName(Thread* t, jclass, jstring name) { if (LIKELY(name)) { object n = makeByteArray(t, stringLength(t, *name) + 1, false); @@ -207,13 +207,13 @@ invoke(Thread* t, jobject this_, jobject instancep, jobjectArray argumentsp) } jobject -currentThread(Thread* t) +currentThread(Thread* t, jclass) { return pushReference(t, t->javaThread); } void -sleep(Thread* t, jlong milliseconds) +sleep(Thread* t, jclass, jlong milliseconds) { if (milliseconds == 0) milliseconds = INT64_MAX; @@ -223,8 +223,8 @@ sleep(Thread* t, jlong milliseconds) } void -arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset, - jint length) +arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst, + jint dstOffset, jint length) { if (LIKELY(src and dst)) { object s = *src; @@ -263,7 +263,7 @@ arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset, } jlong -currentTimeMillis(Thread* t) +currentTimeMillis(Thread* t, jclass) { return t->vm->system->now(); } @@ -311,7 +311,7 @@ exit(Thread* t, jobject, jint code) } jobject -trace(Thread* t, jint skipCount) +trace(Thread* t, jclass, jint skipCount) { int frame = t->frame; while (skipCount-- and frame >= 0) { @@ -334,7 +334,7 @@ trace(Thread* t, jint skipCount) } jarray -resolveTrace(Thread* t, jobject trace) +resolveTrace(Thread* t, jclass, jobject trace) { unsigned length = arrayLength(t, *trace); object array = makeObjectArray diff --git a/src/common.h b/src/common.h index b7fd62dd16..5d4c04df45 100644 --- a/src/common.h +++ b/src/common.h @@ -60,15 +60,14 @@ avg(unsigned a, unsigned b) inline unsigned pad(unsigned n) { - unsigned extra = n % BytesPerWord; - return (extra ? n + BytesPerWord - extra : n); + n += BytesPerWord - 1; + return n - (n % BytesPerWord); } inline unsigned -divide(unsigned n, unsigned d) +ceiling(unsigned n, unsigned d) { - if (n and d > n) return 1; - return (n / d) + (n % d ? 1 : 0); + return (n + d - 1) / d; } inline bool diff --git a/src/heap.cpp b/src/heap.cpp index 95b4c660a0..708b53a73a 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -2,7 +2,7 @@ #include "system.h" #include "common.h" -#define CHAIN_HEADER_SIZE divide(sizeof(Segment::Chain), BytesPerWord) +#define CHAIN_HEADER_SIZE ceiling(sizeof(Segment::Chain), BytesPerWord) using namespace vm; @@ -164,7 +164,7 @@ class Segment { unsigned size(unsigned capacity) { unsigned result - = divide(divide(capacity, scale) * bitsPerRecord, BitsPerWord); + = ceiling(ceiling(capacity, scale) * bitsPerRecord, BitsPerWord); assert(segment->context, result); return result; } diff --git a/src/machine.cpp b/src/machine.cpp index 63cb4e0a54..0b73a80a57 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -761,7 +761,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) classObjectMask(t, classSuper(t, class_))); } else { object mask = makeIntArray - (t, divide(classFixedSize(t, class_), BitsPerWord * BytesPerWord), true); + (t, ceiling(classFixedSize(t, class_), BitsPerWord * BytesPerWord), true); intArrayBody(t, mask, 0) = 1; bool sawReferenceField = false; @@ -1571,7 +1571,7 @@ allocate2(Thread* t, unsigned sizeInBytes) ENTER(t, Thread::IdleState); } - if (t->heapIndex + divide(sizeInBytes, BytesPerWord) + if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) >= Thread::HeapSizeInWords) { ENTER(t, Thread::ExclusiveState); @@ -2287,9 +2287,9 @@ collect(Thread* t, Heap::CollectionType type) // "fixed size: %d; array length: %d; element size: %d; mask: %x\n", // fixedSize, arrayLength, arrayElementSize, mask[0]); - unsigned fixedSizeInWords = divide(fixedSize, BytesPerWord); + unsigned fixedSizeInWords = ceiling(fixedSize, BytesPerWord); unsigned arrayElementSizeInWords - = divide(arrayElementSize, BytesPerWord); + = ceiling(arrayElementSize, BytesPerWord); for (unsigned i = 0; i < fixedSizeInWords; ++i) { if (mask[wordOf(i)] & (static_cast(1) << bitOf(i))) { diff --git a/src/machine.h b/src/machine.h index 49018fdac5..3557243b87 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1303,7 +1303,7 @@ inline object allocateSmall(Thread* t, unsigned sizeInBytes) { object o = t->heap + t->heapIndex; - t->heapIndex += divide(sizeInBytes, BytesPerWord); + t->heapIndex += ceiling(sizeInBytes, BytesPerWord); return o; } @@ -1315,7 +1315,7 @@ allocate(Thread* t, unsigned sizeInBytes) { stress(t); - if (UNLIKELY(t->heapIndex + divide(sizeInBytes, BytesPerWord) + if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord) >= Thread::HeapSizeInWords or t->vm->exclusive)) { @@ -1729,10 +1729,10 @@ hash(const int8_t* s, unsigned length) inline unsigned baseSize(Thread* t, object o, object class_) { - return divide(classFixedSize(t, class_), BytesPerWord) - + divide(classArrayElementSize(t, class_) - * cast(o, classFixedSize(t, class_) - BytesPerWord), - BytesPerWord); + return ceiling(classFixedSize(t, class_), BytesPerWord) + + ceiling(classArrayElementSize(t, class_) + * cast(o, classFixedSize(t, class_) - BytesPerWord), + BytesPerWord); } inline bool diff --git a/src/run.cpp b/src/run.cpp index f1c3d94513..db334a3f46 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -265,23 +265,24 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin) { PROTECT(t, method); + unsigned count = methodParameterCount(t, method) + 1; + if (methodFlags(t, method) & ACC_STATIC) { + ++ count; + } + object data = makeNativeMethodData(t, function, 0, // argument table size 0, // return code, builtin, - methodParameterCount(t, method) + 1, + count, false); - unsigned argumentTableSize = BytesPerWord; + unsigned argumentTableSize = BytesPerWord * 2; unsigned index = 0; nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE; - - if ((methodFlags(t, method) & ACC_STATIC) == 0) { - nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE; - argumentTableSize += BytesPerWord; - } + nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE; const char* s = reinterpret_cast (&byteArrayBody(t, methodSpec(t, method), 0)); @@ -395,6 +396,9 @@ invokeNative(Thread* t, object method) pushFrame(t, method); unsigned count = methodParameterCount(t, method); + if (methodFlags(t, method) & ACC_STATIC) { + ++ count; + } unsigned size = nativeMethodDataArgumentTableSize(t, data); uintptr_t args[size / BytesPerWord]; @@ -402,8 +406,15 @@ invokeNative(Thread* t, object method) args[offset++] = reinterpret_cast(t); + unsigned start = 0; + if (methodFlags(t, method) & ACC_STATIC) { + start = 1; + args[offset++] = reinterpret_cast + (pushReference(t, methodClass(t, method))); + } + unsigned sp = frameBase(t, t->frame); - for (unsigned i = 0; i < count; ++i) { + for (unsigned i = start; i < count; ++i) { unsigned type = nativeMethodDataParameterTypes(t, data, i + 1); switch (type) { diff --git a/test/test.sh b/test/test.sh index b0fd9bbcb1..2d1a228d64 100644 --- a/test/test.sh +++ b/test/test.sh @@ -11,8 +11,10 @@ tests=${@} echo -n "" >${log} +echo + for test in ${tests}; do - printf "${test}: " + printf "%16s" "${test}: " case ${mode} in debug )