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

This commit is contained in:
Joel Dice 2007-07-25 18:48:28 -06:00
parent 38a982c7dd
commit 9ab88ef619
14 changed files with 233 additions and 49 deletions

View File

@ -5,7 +5,7 @@ public class FileDescriptor {
public static final FileDescriptor out = new FileDescriptor(1); public static final FileDescriptor out = new FileDescriptor(1);
public static final FileDescriptor err = new FileDescriptor(2); public static final FileDescriptor err = new FileDescriptor(2);
private final int value; final int value;
private FileDescriptor(int value) { private FileDescriptor(int value) {
this.value = value; this.value = value;

View File

@ -0,0 +1,79 @@
#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

@ -1,15 +1,28 @@
package java.io; package java.io;
public class FileInputStream extends InputStream { public class FileInputStream extends InputStream {
private final FileDescriptor fd; private final int fd;
public FileInputStream(FileDescriptor 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);
}
} }

View File

@ -0,0 +1,69 @@
#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

@ -1,16 +1,28 @@
package java.io; package java.io;
public class FileOutputStream extends OutputStream { public class FileOutputStream extends OutputStream {
private final FileDescriptor fd; private final int fd;
public FileOutputStream(FileDescriptor 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; 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);
}
} }

View File

@ -1,4 +1,3 @@
#include "stdio.h"
#include "string.h" #include "string.h"
#include "jni.h" #include "jni.h"
@ -6,7 +5,7 @@
#define JNIEXPORT __attribute__ ((visibility("default"))) #define JNIEXPORT __attribute__ ((visibility("default")))
extern "C" JNIEXPORT jstring JNICALL 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; jstring value = 0;

View File

@ -16,7 +16,7 @@ src = src
classpath = classpath classpath = classpath
test = test test = test
input = $(cls)/Threads.class input = $(cls)/Hello.class
cxx = g++ cxx = g++
cc = gcc cc = gcc
@ -55,7 +55,7 @@ java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(cls)/%.class,$(x)))
stdcpp-sources = $(src)/stdc++.cpp stdcpp-sources = $(src)/stdc++.cpp
stdcpp-objects = $(call cpp-objects,$(stdcpp-sources),$(src)) 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-objects = $(call cpp-objects,$(jni-sources),$(classpath))
jni-cflags = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux $(cflags) jni-cflags = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux $(cflags)
jni-library = $(bld)/libnatives.so jni-library = $(bld)/libnatives.so

View File

@ -65,7 +65,7 @@ notifyAll(Thread* t, jobject this_)
} }
jclass jclass
forName(Thread* t, jstring name) 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);
@ -207,13 +207,13 @@ invoke(Thread* t, jobject this_, jobject instancep, jobjectArray argumentsp)
} }
jobject jobject
currentThread(Thread* t) currentThread(Thread* t, jclass)
{ {
return pushReference(t, t->javaThread); return pushReference(t, t->javaThread);
} }
void void
sleep(Thread* t, jlong milliseconds) sleep(Thread* t, jclass, jlong milliseconds)
{ {
if (milliseconds == 0) milliseconds = INT64_MAX; if (milliseconds == 0) milliseconds = INT64_MAX;
@ -223,8 +223,8 @@ sleep(Thread* t, jlong milliseconds)
} }
void void
arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset, arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
jint length) jint dstOffset, jint length)
{ {
if (LIKELY(src and dst)) { if (LIKELY(src and dst)) {
object s = *src; object s = *src;
@ -263,7 +263,7 @@ arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset,
} }
jlong jlong
currentTimeMillis(Thread* t) currentTimeMillis(Thread* t, jclass)
{ {
return t->vm->system->now(); return t->vm->system->now();
} }
@ -311,7 +311,7 @@ exit(Thread* t, jobject, jint code)
} }
jobject jobject
trace(Thread* t, jint skipCount) 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 +334,7 @@ trace(Thread* t, jint skipCount)
} }
jarray jarray
resolveTrace(Thread* t, jobject trace) resolveTrace(Thread* t, jclass, jobject trace)
{ {
unsigned length = arrayLength(t, *trace); unsigned length = arrayLength(t, *trace);
object array = makeObjectArray object array = makeObjectArray

View File

@ -60,15 +60,14 @@ avg(unsigned a, unsigned b)
inline unsigned inline unsigned
pad(unsigned n) pad(unsigned n)
{ {
unsigned extra = n % BytesPerWord; n += BytesPerWord - 1;
return (extra ? n + BytesPerWord - extra : n); return n - (n % BytesPerWord);
} }
inline unsigned inline unsigned
divide(unsigned n, unsigned d) ceiling(unsigned n, unsigned d)
{ {
if (n and d > n) return 1; return (n + d - 1) / d;
return (n / d) + (n % d ? 1 : 0);
} }
inline bool inline bool

View File

@ -2,7 +2,7 @@
#include "system.h" #include "system.h"
#include "common.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; using namespace vm;
@ -164,7 +164,7 @@ class Segment {
unsigned size(unsigned capacity) { unsigned size(unsigned capacity) {
unsigned result unsigned result
= divide(divide(capacity, scale) * bitsPerRecord, BitsPerWord); = ceiling(ceiling(capacity, scale) * bitsPerRecord, BitsPerWord);
assert(segment->context, result); assert(segment->context, result);
return result; return result;
} }

View File

@ -761,7 +761,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
classObjectMask(t, classSuper(t, class_))); classObjectMask(t, classSuper(t, class_)));
} else { } else {
object mask = makeIntArray object mask = makeIntArray
(t, divide(classFixedSize(t, class_), BitsPerWord * BytesPerWord), true); (t, ceiling(classFixedSize(t, class_), BitsPerWord * BytesPerWord), true);
intArrayBody(t, mask, 0) = 1; intArrayBody(t, mask, 0) = 1;
bool sawReferenceField = false; bool sawReferenceField = false;
@ -1571,7 +1571,7 @@ allocate2(Thread* t, unsigned sizeInBytes)
ENTER(t, Thread::IdleState); ENTER(t, Thread::IdleState);
} }
if (t->heapIndex + divide(sizeInBytes, BytesPerWord) if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
>= Thread::HeapSizeInWords) >= Thread::HeapSizeInWords)
{ {
ENTER(t, Thread::ExclusiveState); 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", // "fixed size: %d; array length: %d; element size: %d; mask: %x\n",
// fixedSize, arrayLength, arrayElementSize, mask[0]); // fixedSize, arrayLength, arrayElementSize, mask[0]);
unsigned fixedSizeInWords = divide(fixedSize, BytesPerWord); unsigned fixedSizeInWords = ceiling(fixedSize, BytesPerWord);
unsigned arrayElementSizeInWords unsigned arrayElementSizeInWords
= divide(arrayElementSize, BytesPerWord); = ceiling(arrayElementSize, BytesPerWord);
for (unsigned i = 0; i < fixedSizeInWords; ++i) { for (unsigned i = 0; i < fixedSizeInWords; ++i) {
if (mask[wordOf(i)] & (static_cast<uintptr_t>(1) << bitOf(i))) { if (mask[wordOf(i)] & (static_cast<uintptr_t>(1) << bitOf(i))) {

View File

@ -1303,7 +1303,7 @@ inline object
allocateSmall(Thread* t, unsigned sizeInBytes) allocateSmall(Thread* t, unsigned sizeInBytes)
{ {
object o = t->heap + t->heapIndex; object o = t->heap + t->heapIndex;
t->heapIndex += divide(sizeInBytes, BytesPerWord); t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
return o; return o;
} }
@ -1315,7 +1315,7 @@ allocate(Thread* t, unsigned sizeInBytes)
{ {
stress(t); stress(t);
if (UNLIKELY(t->heapIndex + divide(sizeInBytes, BytesPerWord) if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
>= Thread::HeapSizeInWords >= Thread::HeapSizeInWords
or t->vm->exclusive)) or t->vm->exclusive))
{ {
@ -1729,10 +1729,10 @@ hash(const int8_t* s, unsigned length)
inline unsigned inline unsigned
baseSize(Thread* t, object o, object class_) baseSize(Thread* t, object o, object class_)
{ {
return divide(classFixedSize(t, class_), BytesPerWord) return ceiling(classFixedSize(t, class_), BytesPerWord)
+ divide(classArrayElementSize(t, class_) + ceiling(classArrayElementSize(t, class_)
* cast<uintptr_t>(o, classFixedSize(t, class_) - BytesPerWord), * cast<uintptr_t>(o, classFixedSize(t, class_) - BytesPerWord),
BytesPerWord); BytesPerWord);
} }
inline bool inline bool

View File

@ -265,23 +265,24 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin)
{ {
PROTECT(t, method); PROTECT(t, method);
unsigned count = methodParameterCount(t, method) + 1;
if (methodFlags(t, method) & ACC_STATIC) {
++ count;
}
object data = makeNativeMethodData(t, object data = makeNativeMethodData(t,
function, function,
0, // argument table size 0, // argument table size
0, // return code, 0, // return code,
builtin, builtin,
methodParameterCount(t, method) + 1, count,
false); false);
unsigned argumentTableSize = BytesPerWord; unsigned argumentTableSize = BytesPerWord * 2;
unsigned index = 0; unsigned index = 0;
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE; nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
argumentTableSize += BytesPerWord;
}
const char* s = reinterpret_cast<const char*> const char* s = reinterpret_cast<const char*>
(&byteArrayBody(t, methodSpec(t, method), 0)); (&byteArrayBody(t, methodSpec(t, method), 0));
@ -395,6 +396,9 @@ invokeNative(Thread* t, object method)
pushFrame(t, method); pushFrame(t, method);
unsigned count = methodParameterCount(t, method); unsigned count = methodParameterCount(t, method);
if (methodFlags(t, method) & ACC_STATIC) {
++ count;
}
unsigned size = nativeMethodDataArgumentTableSize(t, data); unsigned size = nativeMethodDataArgumentTableSize(t, data);
uintptr_t args[size / BytesPerWord]; uintptr_t args[size / BytesPerWord];
@ -402,8 +406,15 @@ invokeNative(Thread* t, object method)
args[offset++] = reinterpret_cast<uintptr_t>(t); args[offset++] = reinterpret_cast<uintptr_t>(t);
unsigned start = 0;
if (methodFlags(t, method) & ACC_STATIC) {
start = 1;
args[offset++] = reinterpret_cast<uintptr_t>
(pushReference(t, methodClass(t, method)));
}
unsigned sp = frameBase(t, t->frame); 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); unsigned type = nativeMethodDataParameterTypes(t, data, i + 1);
switch (type) { switch (type) {

View File

@ -11,8 +11,10 @@ tests=${@}
echo -n "" >${log} echo -n "" >${log}
echo
for test in ${tests}; do for test in ${tests}; do
printf "${test}: " printf "%16s" "${test}: "
case ${mode} in case ${mode} in
debug ) debug )