implement JNI methods needed by AWT

These include PushLocalFrame, PopLocalFrame, NewDirectByteBuffer,
GetDirectBufferAddress, and GetDirectBufferCapacity.
This commit is contained in:
Joel Dice 2012-08-11 06:56:19 -06:00
parent 2642a167e2
commit 01be4b23bb
12 changed files with 620 additions and 165 deletions

View File

@ -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 + ")";
}
}

View File

@ -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<ByteBuffer> {
private final byte[] array;
private int arrayOffset;
public abstract class ByteBuffer
extends Buffer
implements Comparable<ByteBuffer>
{
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<ByteBuffer> {
}
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<ByteBuffer> {
}
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<ByteBuffer> {
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() + ")";
}
}

View File

@ -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 + ")";
}
}

View File

@ -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 + ")";
}
}

View File

@ -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);
}
}

View File

@ -511,3 +511,55 @@ Avian_sun_misc_Unsafe_getAddress__J
return *reinterpret_cast<intptr_t*>(p);
}
extern "C" JNIEXPORT void JNICALL
Avian_sun_misc_Unsafe_copyMemory
(Thread* t, object, uintptr_t* arguments)
{
object srcBase = reinterpret_cast<object>(arguments[1]);
int64_t srcOffset; memcpy(&srcOffset, arguments + 2, 8);
object dstBase = reinterpret_cast<object>(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<uint8_t>(srcBase, srcOffset)
: reinterpret_cast<uint8_t*>(srcOffset);
void* dst = dstBase
? &cast<uint8_t>(dstBase, dstOffset)
: reinterpret_cast<uint8_t*>(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<object>(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<intptr_t>(array) + ArrayBody;
return reinterpret_cast<intptr_t>(array);
}

View File

@ -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<int64_t>(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<object>(arguments[1]);
int64_t srcOffset; memcpy(&srcOffset, arguments + 2, 8);
object dstBase = reinterpret_cast<object>(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<uint8_t>(srcBase, srcOffset)
: reinterpret_cast<uint8_t*>(srcOffset);
void* dst = dstBase
? &cast<uint8_t>(dstBase, dstOffset)
: reinterpret_cast<uint8_t*>(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<local::MyClasspath*>(t->m->classpath)->javaHome);

View File

@ -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<MyThread*>(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<MyThread*>(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)
{

View File

@ -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<Thread*>(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<Thread*>(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)
{

View File

@ -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<uintptr_t>(o) };
return reinterpret_cast<jobject>(run(t, getObjectClass, arguments));
return reinterpret_cast<jclass>(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<uintptr_t*>(*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<uintptr_t>(capacity) };
return run(t, pushLocalFrame, arguments) ? 0 : -1;
}
uint64_t
popLocalFrame(Thread* t, uintptr_t* arguments)
{
object result = *reinterpret_cast<jobject>(arguments[0]);
PROTECT(t, result);
t->m->processor->popLocalFrame(t);
return reinterpret_cast<uint64_t>(makeLocalReference(t, result));
}
jobject JNICALL
PopLocalFrame(Thread* t, jobject result)
{
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(result) };
return reinterpret_cast<jobject>(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, "<init>", "(JI)V"),
reinterpret_cast<jlong>(p),
static_cast<jint>(capacity));
}
void* JNICALL
GetDirectBufferAddress(Thread* t, jobject b)
{
return reinterpret_cast<void*>
(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

View File

@ -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;

View File

@ -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));
}