diff --git a/classpath/java/nio/ArrayByteBuffer.java b/classpath/java/nio/ArrayByteBuffer.java new file mode 100644 index 0000000000..2f2e7d5024 --- /dev/null +++ b/classpath/java/nio/ArrayByteBuffer.java @@ -0,0 +1,87 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +class ArrayByteBuffer extends ByteBuffer { + private final byte[] array; + private final int arrayOffset; + + ArrayByteBuffer(byte[] array, int offset, int length, boolean readOnly) { + super(readOnly); + + this.array = array; + this.arrayOffset = offset; + this.capacity = length; + this.limit = length; + this.position = 0; + } + + public ByteBuffer asReadOnlyBuffer() { + ByteBuffer b = new ArrayByteBuffer(array, arrayOffset, capacity, true); + b.position(position()); + b.limit(limit()); + return b; + } + + public byte[] array() { + return array; + } + + public ByteBuffer slice() { + return new ArrayByteBuffer + (array, arrayOffset + position, remaining(), true); + } + + public int arrayOffset() { + return arrayOffset; + } + + protected void doPut(int position, byte val) { + array[arrayOffset + position] = val; + } + + public ByteBuffer put(ByteBuffer src) { + checkPut(position, src.remaining()); + src.get(array, arrayOffset + position, src.remaining()); + position += src.remaining(); + return this; + } + + public ByteBuffer put(byte[] src, int offset, int length) { + checkPut(position, length); + + System.arraycopy(src, offset, array, arrayOffset + position, length); + position += length; + + return this; + } + + public ByteBuffer get(byte[] dst, int offset, int length) { + checkGet(position, length); + + System.arraycopy(array, arrayOffset + position, dst, offset, length); + position += length; + + return this; + } + + protected byte doGet(int position) { + return array[arrayOffset+position]; + } + + public String toString() { + return "(ArrayByteBuffer with array: " + array + + " arrayOffset: " + arrayOffset + + " position: " + position + + " limit: " + limit + + " capacity: " + capacity + ")"; + } +} diff --git a/classpath/java/nio/ByteBuffer.java b/classpath/java/nio/ByteBuffer.java index e63217f6ea..73da8fbc78 100644 --- a/classpath/java/nio/ByteBuffer.java +++ b/classpath/java/nio/ByteBuffer.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -10,13 +10,22 @@ package java.nio; -public class ByteBuffer extends Buffer implements Comparable { - private final byte[] array; - private int arrayOffset; +public abstract class ByteBuffer + extends Buffer + implements Comparable +{ private final boolean readOnly; + protected ByteBuffer(boolean readOnly) { + this.readOnly = readOnly; + } + public static ByteBuffer allocate(int capacity) { - return new ByteBuffer(new byte[capacity], 0, capacity, false); + return new ArrayByteBuffer(new byte[capacity], 0, capacity, false); + } + + public static ByteBuffer allocateDirect(int capacity) { + return FixedArrayByteBuffer.make(capacity); } public static ByteBuffer wrap(byte[] array) { @@ -24,23 +33,51 @@ public class ByteBuffer extends Buffer implements Comparable { } public static ByteBuffer wrap(byte[] array, int offset, int length) { - return new ByteBuffer(array, offset, length, false); + return new ArrayByteBuffer(array, offset, length, false); } - private ByteBuffer(byte[] array, int offset, int length, boolean readOnly) { - this.array = array; - this.readOnly = readOnly; - arrayOffset = offset; - capacity = length; - limit = capacity; - position = 0; + public abstract ByteBuffer asReadOnlyBuffer(); + + public abstract ByteBuffer slice(); + + protected abstract void doPut(int offset, byte val); + + public abstract ByteBuffer put(byte[] arr, int offset, int len); + + protected abstract byte doGet(int offset); + + public abstract ByteBuffer get(byte[] dst, int offset, int length); + + public boolean hasArray() { + return false; } - public ByteBuffer asReadOnlyBuffer() { - ByteBuffer b = new ByteBuffer(array, arrayOffset, capacity, true); - b.position(position()); - b.limit(limit()); - return b; + public ByteBuffer compact() { + if (position != 0) { + ByteBuffer b = slice(); + position = 0; + put(b); + } + + position = remaining(); + limit(capacity()); + + return this; + } + + public ByteBuffer put(ByteBuffer src) { + if (src.hasArray()) { + checkPut(position, src.remaining()); + + put(src.array(), src.arrayOffset() + src.position, src.remaining()); + src.position(src.position() + src.remaining()); + + return this; + } else { + byte[] buffer = new byte[src.remaining()]; + src.get(buffer); + return put(buffer); + } } public int compareTo(ByteBuffer o) { @@ -60,37 +97,22 @@ public class ByteBuffer extends Buffer implements Comparable { } public byte[] array() { - return array; - } - - public ByteBuffer slice() { - return new ByteBuffer(array, arrayOffset + position, remaining(), true); + throw new UnsupportedOperationException(); } public int arrayOffset() { - return arrayOffset; + throw new UnsupportedOperationException(); } - public ByteBuffer compact() { - if (position != 0) { - System.arraycopy(array, arrayOffset+position, array, arrayOffset, remaining()); - } - position=remaining(); - limit(capacity()); - + public ByteBuffer put(int offset, byte val) { + checkPut(offset, 1); + doPut(offset, val); return this; } public ByteBuffer put(byte val) { - checkPut(1); - array[arrayOffset+(position++)] = val; - return this; - } - - public ByteBuffer put(ByteBuffer src) { - checkPut(src.remaining()); - put(src.array, src.arrayOffset + src.position, src.remaining()); - src.position += src.remaining(); + put(position, val); + ++ position; return this; } @@ -98,125 +120,122 @@ public class ByteBuffer extends Buffer implements Comparable { return put(arr, 0, arr.length); } - public ByteBuffer put(byte[] arr, int offset, int len) { - checkPut(len); - System.arraycopy(arr, offset, array, arrayOffset+position, len); - position += len; + public ByteBuffer putLong(int position, long val) { + checkPut(position, 8); + + doPut(position , (byte) ((val >> 56) & 0xff)); + doPut(position + 1, (byte) ((val >> 48) & 0xff)); + doPut(position + 2, (byte) ((val >> 40) & 0xff)); + doPut(position + 3, (byte) ((val >> 32) & 0xff)); + doPut(position + 4, (byte) ((val >> 24) & 0xff)); + doPut(position + 5, (byte) ((val >> 16) & 0xff)); + doPut(position + 6, (byte) ((val >> 8) & 0xff)); + doPut(position + 7, (byte) ((val ) & 0xff)); + return this; } public ByteBuffer putInt(int position, int val) { checkPut(position, 4); - array[arrayOffset+position] = (byte)((val >> 24) & 0xff); - array[arrayOffset+position+1] = (byte)((val >> 16) & 0xff); - array[arrayOffset+position+2] = (byte)((val >> 8) & 0xff); - array[arrayOffset+position+3] = (byte)((val ) & 0xff); + + doPut(position , (byte) ((val >> 24) & 0xff)); + doPut(position + 1, (byte) ((val >> 16) & 0xff)); + doPut(position + 2, (byte) ((val >> 8) & 0xff)); + doPut(position + 3, (byte) ((val ) & 0xff)); + + return this; + } + + public ByteBuffer putShort(int position, short val) { + checkPut(position, 2); + + doPut(position , (byte) ((val >> 8) & 0xff)); + doPut(position + 1, (byte) ((val ) & 0xff)); + + return this; + } + + public ByteBuffer putLong(long val) { + putLong(position, val); + position += 8; return this; } public ByteBuffer putInt(int val) { - checkPut(4); putInt(position, val); position += 4; return this; } public ByteBuffer putShort(short val) { - checkPut(2); - put((byte)((val >> 8) & 0xff)); - put((byte)(val & 0xff)); + putShort(position, val); + position += 2; return this; } - public ByteBuffer putLong(long val) { - checkPut(8); - putInt((int)(val >> 32)); - putInt((int)val); - return this; - } - - public byte get() { - checkGet(1); - return array[arrayOffset+(position++)]; + public byte get(int position) { + checkGet(position, 1); + return doGet(position); } public ByteBuffer get(byte[] dst) { return get(dst, 0, dst.length); } - public ByteBuffer get(byte[] dst, int offset, int length) { - checkGet(length); - System.arraycopy(array, arrayOffset + position, dst, offset, length); - position += length; - return this; - } + public long getLong(int position) { + checkGet(position, 8); - public byte get(int position) { - checkGet(position, 1); - return array[arrayOffset+position]; + return (((long) (doGet(position ) & 0xFF)) << 56) + | (((long) (doGet(position + 1) & 0xFF)) << 48) + | (((long) (doGet(position + 2) & 0xFF)) << 40) + | (((long) (doGet(position + 3) & 0xFF)) << 32) + | (((long) (doGet(position + 4) & 0xFF)) << 24) + | (((long) (doGet(position + 5) & 0xFF)) << 16) + | (((long) (doGet(position + 6) & 0xFF)) << 8) + | (((long) (doGet(position + 7) & 0xFF)) ); } public int getInt(int position) { checkGet(position, 4); - int p = arrayOffset + position; - return ((array[p] & 0xFF) << 24) - | ((array[p + 1] & 0xFF) << 16) - | ((array[p + 2] & 0xFF) << 8) - | ((array[p + 3] & 0xFF)); + return (((int) (doGet(position ) & 0xFF)) << 24) + | (((int) (doGet(position + 1) & 0xFF)) << 16) + | (((int) (doGet(position + 2) & 0xFF)) << 8) + | (((int) (doGet(position + 3) & 0xFF)) ); } public short getShort(int position) { checkGet(position, 2); - int p = arrayOffset + position; - return (short) (((array[p] & 0xFF) << 8) | ((array[p + 1] & 0xFF))); - } - - public int getInt() { - checkGet(4); - int i = get() << 24; - i |= (get() & 0xff) << 16; - i |= (get() & 0xff) << 8; - i |= (get() & 0xff); - return i; - } - - public short getShort() { - checkGet(2); - short s = (short)(get() << 8); - s |= get() & 0xff; - return s; + return (short) (( ((int) (doGet(position ) & 0xFF)) << 8) + | (((int) (doGet(position + 1) & 0xFF)) )); } public long getLong() { - checkGet(8); - long l = (long)getInt() << 32; - l |= (long)getInt() & 0xffffffffL; - return l; + long r = getLong(position); + position += 8; + return r; } - private void checkPut(int amount) { - if (readOnly) throw new ReadOnlyBufferException(); - if (amount > limit-position) throw new IndexOutOfBoundsException(); + public int getInt() { + int r = getInt(position); + position += 4; + return r; } - private void checkPut(int position, int amount) { + public short getShort() { + short r = getShort(position); + position += 2; + return r; + } + + protected void checkPut(int position, int amount) { if (readOnly) throw new ReadOnlyBufferException(); if (position < 0 || position+amount > limit) throw new IndexOutOfBoundsException(); } - private void checkGet(int amount) { + protected void checkGet(int position, int amount) { if (amount > limit-position) throw new IndexOutOfBoundsException(); } - - private void checkGet(int position, int amount) { - if (position < 0 || position+amount > limit) - throw new IndexOutOfBoundsException(); - } - - public String toString() { - return "(ByteBuffer with array: " + array + " arrayOffset: " + arrayOffset + " position: " + position + " remaining; " + remaining() + ")"; - } } diff --git a/classpath/java/nio/DirectByteBuffer.java b/classpath/java/nio/DirectByteBuffer.java new file mode 100644 index 0000000000..d33a0d5f6f --- /dev/null +++ b/classpath/java/nio/DirectByteBuffer.java @@ -0,0 +1,105 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +import sun.misc.Unsafe; + +class DirectByteBuffer extends ByteBuffer { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final int baseOffset = unsafe.arrayBaseOffset(byte[].class); + + protected final long address; + + protected DirectByteBuffer(long address, int capacity, boolean readOnly) { + super(readOnly); + + this.address = address; + this.capacity = capacity; + this.limit = capacity; + this.position = 0; + } + + protected DirectByteBuffer(long address, int capacity) { + this(address, capacity, false); + } + + public ByteBuffer asReadOnlyBuffer() { + ByteBuffer b = new DirectByteBuffer(address, capacity, true); + b.position(position()); + b.limit(limit()); + return b; + } + + public ByteBuffer slice() { + return new DirectByteBuffer(address + position, remaining(), true); + } + + protected void doPut(int position, byte val) { + unsafe.putByte(address + position, val); + } + + public ByteBuffer put(ByteBuffer src) { + if (src instanceof DirectByteBuffer) { + checkPut(position, src.remaining()); + + DirectByteBuffer b = (DirectByteBuffer) src; + + unsafe.copyMemory + (b.address + b.position, address + position, b.remaining()); + + position += b.remaining(); + b.position += b.remaining(); + + return this; + } else { + return super.put(src); + } + } + + public ByteBuffer put(byte[] src, int offset, int length) { + if (offset < 0 || offset + length > src.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + checkPut(position, length); + + unsafe.copyMemory + (src, baseOffset + offset, null, address + position, length); + + position += length; + + return this; + } + + public ByteBuffer get(byte[] dst, int offset, int length) { + if (offset < 0 || offset + length > dst.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + checkGet(position, length); + + unsafe.copyMemory + (null, address + position, dst, baseOffset + offset, length); + + return this; + } + + protected byte doGet(int position) { + return unsafe.getByte(address + position); + } + + public String toString() { + return "(DirectByteBuffer with address: " + address + + " position: " + position + + " limit: " + limit + + " capacity: " + capacity + ")"; + } +} diff --git a/classpath/java/nio/FixedArrayByteBuffer.java b/classpath/java/nio/FixedArrayByteBuffer.java new file mode 100644 index 0000000000..c56ff421f0 --- /dev/null +++ b/classpath/java/nio/FixedArrayByteBuffer.java @@ -0,0 +1,58 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +class FixedArrayByteBuffer extends DirectByteBuffer { + private final byte[] array; + private final int arrayOffset; + + private FixedArrayByteBuffer(long address, + byte[] array, + int offset, + int capacity, + boolean readOnly) + { + super(address, capacity, readOnly); + + this.array = array; + this.arrayOffset = offset; + } + + public static FixedArrayByteBuffer make(int capacity) { + long[] address = new long[1]; + byte[] array = allocateFixed(capacity, address); + return new FixedArrayByteBuffer(address[0], array, 0, capacity, false); + } + + private static native byte[] allocateFixed(int capacity, long[] address); + + public ByteBuffer asReadOnlyBuffer() { + ByteBuffer b = new FixedArrayByteBuffer + (address, array, arrayOffset, capacity, true); + b.position(position()); + b.limit(limit()); + return b; + } + + public ByteBuffer slice() { + return new FixedArrayByteBuffer + (address + position, array, arrayOffset + position, remaining(), true); + } + + public String toString() { + return "(FixedArrayByteBuffer with address: " + address + + " array: " + array + + " arrayOffset: " + arrayOffset + + " position: " + position + + " limit: " + limit + + " capacity: " + capacity + ")"; + } +} diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java index b7613d2559..4f395718c9 100644 --- a/classpath/sun/misc/Unsafe.java +++ b/classpath/sun/misc/Unsafe.java @@ -47,4 +47,14 @@ public final class Unsafe { public native long getAddress(long address); public native void putAddress(long address, long x); + + public native int arrayBaseOffset(Class arrayClass); + + public native void copyMemory(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long count); + + public void copyMemory(long src, long dst, long count) { + copyMemory(null, src, null, dst, count); + } } diff --git a/src/builtin.cpp b/src/builtin.cpp index 9c3dca8508..c438aebea0 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -511,3 +511,55 @@ Avian_sun_misc_Unsafe_getAddress__J return *reinterpret_cast(p); } + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_copyMemory +(Thread* t, object, uintptr_t* arguments) +{ + object srcBase = reinterpret_cast(arguments[1]); + int64_t srcOffset; memcpy(&srcOffset, arguments + 2, 8); + object dstBase = reinterpret_cast(arguments[4]); + int64_t dstOffset; memcpy(&dstOffset, arguments + 5, 8); + int64_t count; memcpy(&count, arguments + 7, 8); + + PROTECT(t, srcBase); + PROTECT(t, dstBase); + + ACQUIRE(t, t->m->referenceLock); + + void* src = srcBase + ? &cast(srcBase, srcOffset) + : reinterpret_cast(srcOffset); + + void* dst = dstBase + ? &cast(dstBase, dstOffset) + : reinterpret_cast(dstOffset); + + memcpy(dst, src, count); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_arrayBaseOffset +(Thread*, object, uintptr_t*) +{ + return ArrayBody; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_nio_FixedArrayByteBuffer_allocateFixed +(Thread* t, object, uintptr_t* arguments) +{ + int capacity = arguments[0]; + object address = reinterpret_cast(arguments[1]); + PROTECT(t, address); + + object array = allocate3 + (t, t->m->heap, Machine::FixedAllocation, ArrayBody + capacity, false); + + setObjectClass(t, array, type(t, Machine::ByteArrayType)); + byteArrayLength(t, array) = capacity; + + longArrayBody(t, address, 0) = reinterpret_cast(array) + ArrayBody; + + return reinterpret_cast(array); +} diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 8c5ed0e126..b0e0c51a2c 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2396,13 +2396,6 @@ Avian_sun_misc_Unsafe_staticFieldOffset (t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield))); } -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_arrayBaseOffset -(Thread*, object, uintptr_t*) -{ - return BytesPerWord * 2; -} - extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_arrayIndexScale (Thread* t, object, uintptr_t* arguments) @@ -2522,6 +2515,14 @@ Avian_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J return cast(o, offset); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J + (t, method, arguments); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_getLongVolatile (Thread* t, object, uintptr_t* arguments) @@ -2784,32 +2785,6 @@ Avian_sun_misc_Unsafe_park monitorRelease(t, local::interruptLock(t, t->javaThread)); } -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_copyMemory -(Thread* t, object, uintptr_t* arguments) -{ - object srcBase = reinterpret_cast(arguments[1]); - int64_t srcOffset; memcpy(&srcOffset, arguments + 2, 8); - object dstBase = reinterpret_cast(arguments[4]); - int64_t dstOffset; memcpy(&dstOffset, arguments + 5, 8); - int64_t count; memcpy(&count, arguments + 7, 8); - - PROTECT(t, srcBase); - PROTECT(t, dstBase); - - ACQUIRE(t, t->m->referenceLock); - - void* src = srcBase - ? &cast(srcBase, srcOffset) - : reinterpret_cast(srcOffset); - - void* dst = dstBase - ? &cast(dstBase, dstOffset) - : reinterpret_cast(dstOffset); - - memcpy(dst, src, count); -} - extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_monitorEnter (Thread* t, object, uintptr_t* arguments) @@ -3023,6 +2998,8 @@ jvmInitProperties(Thread* t, uintptr_t* arguments) local::setProperty(t, method, *properties, "java.vm.vendor", "Avian Contributors"); + local::setProperty(t, method, *properties, "java.vm.name","Avian"); + local::setProperty (t, method, *properties, "java.home", static_cast(t->m->classpath)->javaHome); diff --git a/src/compile.cpp b/src/compile.cpp index 166468dcec..07e7f53911 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -202,6 +202,17 @@ class MyThread: public Thread { bool methodIsMostRecent; }; + class ReferenceFrame { + public: + ReferenceFrame(ReferenceFrame* next, Reference* reference): + next(next), + reference(reference) + { } + + ReferenceFrame* next; + Reference* reference; + }; + static void doTransition(MyThread* t, void* ip, void* stack, object continuation, MyThread::CallTrace* trace) { @@ -255,6 +266,7 @@ class MyThread: public Thread { transition(0), traceContext(0), stackLimit(0), + referenceFrame(0), methodLockIsClean(true) { arch->acquire(); @@ -280,6 +292,7 @@ class MyThread: public Thread { Context* transition; TraceContext* traceContext; uintptr_t stackLimit; + ReferenceFrame* referenceFrame; bool methodLockIsClean; }; @@ -8778,6 +8791,32 @@ class MyProcessor: public Processor { } } + virtual bool + pushLocalFrame(Thread* vmt, unsigned) + { + MyThread* t = static_cast(vmt); + + t->referenceFrame = new + (t->m->heap->allocate(sizeof(MyThread::ReferenceFrame))) + MyThread::ReferenceFrame(t->referenceFrame, t->reference); + + return true; + } + + virtual void + popLocalFrame(Thread* vmt) + { + MyThread* t = static_cast(vmt); + + MyThread::ReferenceFrame* f = t->referenceFrame; + t->referenceFrame = f->next; + while (t->reference != f->reference) { + vm::dispose(t, t->reference); + } + + t->m->heap->free(f, sizeof(MyThread::ReferenceFrame)); + } + virtual object invokeArray(Thread* t, object method, object this_, object arguments) { diff --git a/src/interpret.cpp b/src/interpret.cpp index c3617122a5..4175f77146 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -28,18 +28,31 @@ const unsigned FrameFootprint = 4; class Thread: public vm::Thread { public: + class ReferenceFrame { + public: + ReferenceFrame(ReferenceFrame* next, unsigned sp): + next(next), + sp(sp) + { } + + ReferenceFrame* next; + unsigned sp; + }; + Thread(Machine* m, object javaThread, vm::Thread* parent): vm::Thread(m, javaThread, parent), ip(0), sp(0), frame(-1), - code(0) + code(0), + referenceFrame(0) { } unsigned ip; unsigned sp; int frame; object code; + ReferenceFrame* referenceFrame; uintptr_t stack[0]; }; @@ -3010,6 +3023,34 @@ class MyProcessor: public Processor { } } + virtual bool + pushLocalFrame(vm::Thread* vmt, unsigned capacity) + { + Thread* t = static_cast(vmt); + + if (t->sp + capacity < stackSizeInWords(t) / 2) { + t->referenceFrame = new + (t->m->heap->allocate(sizeof(Thread::ReferenceFrame))) + Thread::ReferenceFrame(t->referenceFrame, t->sp); + + return true; + } else { + return false; + } + } + + virtual void + popLocalFrame(vm::Thread* vmt) + { + Thread* t = static_cast(vmt); + + Thread::ReferenceFrame* f = t->referenceFrame; + t->referenceFrame = f->next; + t->sp = f->sp; + + t->m->heap->free(f, sizeof(Thread::ReferenceFrame)); + } + virtual object invokeArray(vm::Thread* vmt, object method, object this_, object arguments) { diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 5846bea7b2..e4abe152f5 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -407,24 +407,6 @@ ExceptionCheck(Thread* t) return t->exception != 0; } -jobject JNICALL -NewDirectByteBuffer(Thread*, void*, jlong) -{ - return 0; -} - -void* JNICALL -GetDirectBufferAddress(Thread*, jobject) -{ - return 0; -} - -jlong JNICALL -GetDirectBufferCapacity(Thread*, jobject) -{ - return -1; -} - uint64_t getObjectClass(Thread* t, uintptr_t* arguments) { @@ -439,7 +421,7 @@ GetObjectClass(Thread* t, jobject o) { uintptr_t arguments[] = { reinterpret_cast(o) }; - return reinterpret_cast(run(t, getObjectClass, arguments)); + return reinterpret_cast(run(t, getObjectClass, arguments)); } uint64_t @@ -3154,6 +3136,8 @@ GetPrimitiveArrayCritical(Thread* t, jarray array, jboolean* isCopy) *isCopy = true; } + expect(t, *array); + return reinterpret_cast(*array) + 2; } @@ -3276,6 +3260,66 @@ IsSameObject(Thread* t, jobject a, jobject b) } } +uint64_t +pushLocalFrame(Thread* t, uintptr_t* arguments) +{ + if (t->m->processor->pushLocalFrame(t, arguments[0])) { + return 1; + } else { + throw_(t, root(t, Machine::OutOfMemoryError)); + } +} + +jint JNICALL +PushLocalFrame(Thread* t, jint capacity) +{ + uintptr_t arguments[] = { static_cast(capacity) }; + + return run(t, pushLocalFrame, arguments) ? 0 : -1; +} + +uint64_t +popLocalFrame(Thread* t, uintptr_t* arguments) +{ + object result = *reinterpret_cast(arguments[0]); + PROTECT(t, result); + + t->m->processor->popLocalFrame(t); + + return reinterpret_cast(makeLocalReference(t, result)); +} + +jobject JNICALL +PopLocalFrame(Thread* t, jobject result) +{ + uintptr_t arguments[] = { reinterpret_cast(result) }; + + return reinterpret_cast(run(t, popLocalFrame, arguments)); +} + +jobject JNICALL +NewDirectByteBuffer(Thread* t, void* p, jlong capacity) +{ + jclass c = FindClass(t, "java/nio/DirectByteBuffer"); + return NewObject(t, c, GetMethodID(t, c, "", "(JI)V"), + reinterpret_cast(p), + static_cast(capacity)); +} + +void* JNICALL +GetDirectBufferAddress(Thread* t, jobject b) +{ + return reinterpret_cast + (GetLongField(t, b, GetFieldID(t, GetObjectClass(t, b), "address", "J"))); +} + +jlong JNICALL +GetDirectBufferCapacity(Thread* t, jobject b) +{ + return GetIntField + (t, b, GetFieldID(t, GetObjectClass(t, b), "capacity", "I")); +} + struct JavaVMOption { char* optionString; void* extraInfo; @@ -3556,6 +3600,8 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) envTable->MonitorExit = local::MonitorExit; envTable->GetJavaVM = local::GetJavaVM; envTable->IsSameObject = local::IsSameObject; + envTable->PushLocalFrame = local::PushLocalFrame; + envTable->PopLocalFrame = local::PopLocalFrame; } } // namespace vm diff --git a/src/processor.h b/src/processor.h index c4c6fd9ad2..6da91dddce 100644 --- a/src/processor.h +++ b/src/processor.h @@ -103,6 +103,12 @@ class Processor { virtual void disposeLocalReference(Thread* t, object* r) = 0; + virtual bool + pushLocalFrame(Thread* t, unsigned capacity) = 0; + + virtual void + popLocalFrame(Thread* t) = 0; + virtual object invokeArray(Thread* t, object method, object this_, object arguments) = 0; diff --git a/test/jni.cpp b/test/jni.cpp index 8dd009325a..8c1ea91f05 100644 --- a/test/jni.cpp +++ b/test/jni.cpp @@ -36,3 +36,18 @@ Java_JNI_addMix return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20; } + +extern "C" JNIEXPORT jobject JNICALL +Java_Buffers_allocateNative(JNIEnv* e, jclass, jint capacity) +{ + void* p = allocate(e, capacity); + if (p == 0) return 0; + + return e->NewDirectByteBuffer(p, capacity); +} + +extern "C" JNIEXPORT void JNICALL +Java_Buffers_freeNative(JNIEnv* e, jclass, jobject b) +{ + free(e->GetDirectBufferAddress(b)); +}