CL: Cleaned-up callbacks and object registries.
Mapped: Added .capacity() and .foreach() with default elementCount.
This commit is contained in:
parent
83c2208aa0
commit
f3472da2ed
|
@ -31,24 +31,39 @@
|
|||
*/
|
||||
package org.lwjgl.opencl;
|
||||
|
||||
import org.lwjgl.PointerWrapperAbstract;
|
||||
|
||||
/**
|
||||
* Instances of this class can be used to receive OpenCL program build notifications.
|
||||
* A single CLBuildProgramCallback instance should only be used with programs created
|
||||
* in the same CLContext.
|
||||
*
|
||||
* @author Spasi
|
||||
*/
|
||||
public abstract class CLBuildProgramCallback extends CLCallback {
|
||||
public abstract class CLBuildProgramCallback extends PointerWrapperAbstract {
|
||||
|
||||
private CLContext context;
|
||||
|
||||
protected CLBuildProgramCallback() {
|
||||
super(CallbackUtil.getBuildProgramCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the context that contains the CLPrograms to which we're registered.
|
||||
*
|
||||
* @param context the CLContext object
|
||||
*/
|
||||
void setContext(final CLContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from native code.
|
||||
*
|
||||
* @param program_address the CLProgram object pointer
|
||||
*/
|
||||
private void handleMessage(long program_address) {
|
||||
handleMessage(CLContext.getCLProgramGlobal(program_address));
|
||||
handleMessage(context.getCLProgram(program_address));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2010 LWJGL Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'LWJGL' nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.lwjgl.opencl;
|
||||
|
||||
import org.lwjgl.PointerWrapperAbstract;
|
||||
|
||||
/**
|
||||
* Base class for OpenCL callback objects.
|
||||
*
|
||||
* @author Spasi
|
||||
*/
|
||||
abstract class CLCallback extends PointerWrapperAbstract {
|
||||
|
||||
private final boolean custom;
|
||||
|
||||
protected CLCallback(final long pointer) {
|
||||
this(pointer, false);
|
||||
}
|
||||
|
||||
protected CLCallback(final long pointer, final boolean custom) {
|
||||
super(pointer);
|
||||
|
||||
this.custom = custom;
|
||||
}
|
||||
|
||||
final boolean isCustom() {
|
||||
return custom;
|
||||
}
|
||||
|
||||
}
|
|
@ -50,7 +50,7 @@ public final class CLCommandQueue extends CLObjectChild<CLContext> {
|
|||
super(pointer, context);
|
||||
if ( isValid() ) {
|
||||
this.device = device;
|
||||
this.clEvents = new CLObjectRegistryGlobal<CLEvent>(CLContext.clEventsGlobal);
|
||||
this.clEvents = new CLObjectRegistry<CLEvent>();
|
||||
context.getCLCommandQueueRegistry().registerObject(this);
|
||||
} else {
|
||||
this.device = null;
|
||||
|
|
|
@ -54,12 +54,6 @@ public final class CLContext extends CLObjectChild<CLPlatform> {
|
|||
private final CLObjectRegistry<CLProgram> clPrograms;
|
||||
private final CLObjectRegistry<CLEvent> clEvents;
|
||||
|
||||
/** Global registry for build callbacks. */
|
||||
static final FastLongMap<CLProgram> clProgramsGlobal = new FastLongMap<CLProgram>();
|
||||
|
||||
/** Global registry for event callbacks. */
|
||||
static final FastLongMap<CLEvent> clEventsGlobal = new FastLongMap<CLEvent>();
|
||||
|
||||
CLContext(final long pointer, final CLPlatform platform) {
|
||||
super(pointer, platform);
|
||||
|
||||
|
@ -70,8 +64,8 @@ public final class CLContext extends CLObjectChild<CLPlatform> {
|
|||
clCommandQueues = new CLObjectRegistry<CLCommandQueue>();
|
||||
clMems = new CLObjectRegistry<CLMem>();
|
||||
clSamplers = new CLObjectRegistry<CLSampler>();
|
||||
clPrograms = new CLObjectRegistryGlobal<CLProgram>(clProgramsGlobal);
|
||||
clEvents = new CLObjectRegistryGlobal<CLEvent>(clEventsGlobal);
|
||||
clPrograms = new CLObjectRegistry<CLProgram>();
|
||||
clEvents = new CLObjectRegistry<CLEvent>();
|
||||
} else {
|
||||
clCommandQueues = null;
|
||||
clMems = null;
|
||||
|
@ -275,8 +269,4 @@ public final class CLContext extends CLObjectChild<CLPlatform> {
|
|||
|
||||
CLObjectRegistry<CLEvent> getCLEventRegistry() { return clEvents; }
|
||||
|
||||
static CLProgram getCLProgramGlobal(final long id) { return clProgramsGlobal.get(id); }
|
||||
|
||||
static CLEvent getCLEventGlobal(final long id) { return clEventsGlobal.get(id); }
|
||||
|
||||
}
|
|
@ -108,6 +108,13 @@ public final class CLEvent extends CLObjectChild<CLContext> {
|
|||
|
||||
// -------[ IMPLEMENTATION STUFF BELOW ]-------
|
||||
|
||||
CLObjectRegistry<CLEvent> getParentRegistry() {
|
||||
if ( queue == null )
|
||||
return getParent().getCLEventRegistry();
|
||||
else
|
||||
return queue.getCLEventRegistry();
|
||||
}
|
||||
|
||||
int release() {
|
||||
try {
|
||||
return super.release();
|
||||
|
|
|
@ -31,30 +31,46 @@
|
|||
*/
|
||||
package org.lwjgl.opencl;
|
||||
|
||||
import org.lwjgl.PointerWrapperAbstract;
|
||||
|
||||
/**
|
||||
* Instances of this class can be used to receive OpenCL memory object destruction notifications.
|
||||
* Instances of this class can be used to handle OpenCL event callbacks. A single
|
||||
* CLEventCallback instance should only be used on events generated from the same
|
||||
* CLCommandQueue or on user events associated with the same CLContext.
|
||||
*
|
||||
* @author Spasi
|
||||
*/
|
||||
public abstract class CLEventCallback extends CLCallback {
|
||||
public abstract class CLEventCallback extends PointerWrapperAbstract {
|
||||
|
||||
private CLObjectRegistry<CLEvent> eventRegistry;
|
||||
|
||||
protected CLEventCallback() {
|
||||
super(CallbackUtil.getEventCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the eventRegistry that contains the CLEvents to which we're registered.
|
||||
*
|
||||
* @param eventRegistry the CLEvent object registry
|
||||
*/
|
||||
void setRegistry(final CLObjectRegistry<CLEvent> eventRegistry) {
|
||||
this.eventRegistry = eventRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from native code.
|
||||
*
|
||||
* @param event_address the CLEvent object pointer
|
||||
*/
|
||||
private void handleMessage(long event_address, int event_command_exec_status) {
|
||||
handleMessage(CLContext.getCLEventGlobal(event_address), event_command_exec_status);
|
||||
handleMessage(eventRegistry.getObject(event_address), event_command_exec_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback method.
|
||||
*
|
||||
* @param event the CLEvent object
|
||||
* @param event the CLEvent object
|
||||
* @param event_command_exec_status the execution status
|
||||
*/
|
||||
protected abstract void handleMessage(CLEvent event, int event_command_exec_status);
|
||||
|
||||
|
|
|
@ -31,12 +31,14 @@
|
|||
*/
|
||||
package org.lwjgl.opencl;
|
||||
|
||||
import org.lwjgl.PointerWrapperAbstract;
|
||||
|
||||
/**
|
||||
* Instances of this class can be used to receive OpenCL memory object destruction notifications.
|
||||
*
|
||||
* @author Spasi
|
||||
*/
|
||||
public abstract class CLMemObjectDestructorCallback extends CLCallback {
|
||||
public abstract class CLMemObjectDestructorCallback extends PointerWrapperAbstract {
|
||||
|
||||
protected CLMemObjectDestructorCallback() {
|
||||
super(CallbackUtil.getMemObjectDestructorCallback());
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
*/
|
||||
package org.lwjgl.opencl;
|
||||
|
||||
import org.lwjgl.PointerWrapperAbstract;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
|
@ -43,7 +45,7 @@ import java.nio.ByteBuffer;
|
|||
* @see CL10#clEnqueueNativeKernel
|
||||
* @see #execute(java.nio.ByteBuffer[])
|
||||
*/
|
||||
public abstract class CLNativeKernel extends CLCallback {
|
||||
public abstract class CLNativeKernel extends PointerWrapperAbstract {
|
||||
|
||||
protected CLNativeKernel() {
|
||||
super(CallbackUtil.getNativeKernelCallback());
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2010 LWJGL Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'LWJGL' nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.lwjgl.opencl;
|
||||
|
||||
/**
|
||||
* A CLObject registry that also registers/unregisters objects to/from a global registry.
|
||||
*
|
||||
* @author Spasi
|
||||
*/
|
||||
final class CLObjectRegistryGlobal<T extends CLObjectChild> extends CLObjectRegistry<T> {
|
||||
|
||||
private final FastLongMap<T> globalRegistry;
|
||||
|
||||
CLObjectRegistryGlobal(final FastLongMap<T> globalRegistry) {
|
||||
this.globalRegistry = globalRegistry;
|
||||
}
|
||||
|
||||
void registerObject(final T object) {
|
||||
super.registerObject(object);
|
||||
globalRegistry.put(object.getPointer(), object);
|
||||
}
|
||||
|
||||
void unregisterObject(final T object) {
|
||||
super.unregisterObject(object);
|
||||
globalRegistry.remove(object.getPointerUnsafe());
|
||||
}
|
||||
|
||||
}
|
|
@ -53,9 +53,6 @@ public final class CLPlatform extends CLObject {
|
|||
|
||||
private final CLObjectRegistry<CLDevice> clDevices;
|
||||
|
||||
/** Global registry for build callbacks. */
|
||||
static final FastLongMap<CLDevice> clDevicesGlobal = new FastLongMap<CLDevice>();
|
||||
|
||||
private Object caps;
|
||||
|
||||
CLPlatform(final long pointer) {
|
||||
|
@ -63,7 +60,7 @@ public final class CLPlatform extends CLObject {
|
|||
|
||||
if ( isValid() ) {
|
||||
clPlatforms.put(pointer, this);
|
||||
clDevices = new CLObjectRegistryGlobal<CLDevice>(clDevicesGlobal);
|
||||
clDevices = new CLObjectRegistry<CLDevice>();
|
||||
} else
|
||||
clDevices = null;
|
||||
}
|
||||
|
@ -195,8 +192,6 @@ public final class CLPlatform extends CLObject {
|
|||
|
||||
CLObjectRegistry<CLDevice> getCLDeviceRegistry() { return clDevices; }
|
||||
|
||||
static CLDevice getCLDeviceGlobal(final long id) { return clDevicesGlobal.get(id); }
|
||||
|
||||
/**
|
||||
* Called from <code>clGetDeviceIDs</code> to register new devices.
|
||||
*
|
||||
|
|
|
@ -55,13 +55,20 @@ public class MappedObjectTests1 {
|
|||
ByteBuffer bb = ByteBuffer.allocateDirect(200);
|
||||
MappedFloat vecs = MappedFloat.map(bb);
|
||||
|
||||
// verify 'malloc' and SIZEOF
|
||||
// verify 'malloc', SIZEOF and capacity()
|
||||
{
|
||||
MappedFloat vecs1 = MappedFloat.malloc(1234);
|
||||
|
||||
assert (vecs1.getSizeof() == MappedFloat.SIZEOF);
|
||||
assert (vecs1.getSizeof() * 1234 == vecs1.backingByteBuffer().capacity());
|
||||
assert (MappedFloat.SIZEOF * 1234 == vecs1.backingByteBuffer().capacity());
|
||||
assert(vecs1.capacity() == vecs1.backingByteBuffer().capacity() / MappedFloat.SIZEOF);
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(200);
|
||||
buf.position(10 * MappedFloat.SIZEOF);
|
||||
|
||||
MappedFloat vecs2 = MappedFloat.map(buf);
|
||||
assert(vecs2.capacity() == (vecs2.backingByteBuffer().capacity() / MappedFloat.SIZEOF) - 10);
|
||||
}
|
||||
|
||||
// manipulate 'mapped.value'
|
||||
|
|
|
@ -70,15 +70,21 @@ public class MappedObjectTests3 {
|
|||
}
|
||||
|
||||
static void testForeach() {
|
||||
int elementCount = 4;
|
||||
int elementCount = 10;
|
||||
MappedSomething some = MappedSomething.malloc(elementCount);
|
||||
|
||||
int i = 0;
|
||||
for ( MappedSomething item : foreach(some, elementCount) ) {
|
||||
for ( MappedSomething item : foreach(some, elementCount / 2) ) {
|
||||
assert (item.view == i++);
|
||||
}
|
||||
assert (some.view != elementCount);
|
||||
System.out.println("current.view=" + some.view + ", not " + elementCount + ", as you might expect");
|
||||
assert (some.view == (elementCount / 2) - 1);
|
||||
System.out.println("current.view=" + some.view + ", not " + (elementCount / 2) + ", as you might expect");
|
||||
|
||||
i = 0;
|
||||
for ( MappedSomething item : foreach(some) ) {
|
||||
assert (item.view == i++);
|
||||
}
|
||||
assert (some.view == elementCount - 1);
|
||||
}
|
||||
|
||||
public static class Xyz extends MappedObject {
|
||||
|
|
|
@ -143,23 +143,41 @@ public class HelloOpenCL {
|
|||
System.out.println("-TRYING TO EXEC NATIVE KERNEL-");
|
||||
final CLCommandQueue queue = clCreateCommandQueue(context, device, 0, null);
|
||||
|
||||
final PointerBuffer ev = BufferUtils.createPointerBuffer(1);
|
||||
|
||||
clEnqueueNativeKernel(queue, new CLNativeKernel() {
|
||||
protected void execute(final ByteBuffer[] memobjs) {
|
||||
if ( memobjs == null )
|
||||
System.out.println("OK, it's null");
|
||||
else {
|
||||
System.out.println("memobjs = " + memobjs.length);
|
||||
for ( int k = 0; k < memobjs.length; k++ ) {
|
||||
System.out.println("memobjs[" + k + "].remaining() = " + memobjs[k].remaining());
|
||||
for ( int l = memobjs[k].position(); l < memobjs[k].limit(); l++ ) {
|
||||
memobjs[k].put(l, (byte)l);
|
||||
}
|
||||
System.out.println("\tmemobjs.length = " + memobjs.length);
|
||||
for ( int k = 0; k < memobjs.length; k++ ) {
|
||||
System.out.println("\tmemobjs[" + k + "].remaining() = " + memobjs[k].remaining());
|
||||
for ( int l = memobjs[k].position(); l < memobjs[k].limit(); l++ ) {
|
||||
memobjs[k].put(l, (byte)l);
|
||||
}
|
||||
}
|
||||
System.out.println("\tNative kernel done.");
|
||||
}
|
||||
}, new CLMem[] { buffer }, new long[] { 128 }, null, null);
|
||||
}, new CLMem[] { buffer }, new long[] { 128 }, null, ev);
|
||||
|
||||
clFinish(queue);
|
||||
final CLEvent e = queue.getCLEvent(ev.get(0));
|
||||
|
||||
clSetEventCallback(e, CL_COMPLETE, new CLEventCallback() {
|
||||
protected void handleMessage(final CLEvent event, final int event_command_exec_status) {
|
||||
System.out.println("\t\tEvent callback status: " + getEventStatusName(event_command_exec_status));
|
||||
}
|
||||
});
|
||||
|
||||
int status = e.getInfoInt(CL_EVENT_COMMAND_EXECUTION_STATUS);
|
||||
System.out.println("NATIVE KERNEL STATUS: " + getEventStatusName(status));
|
||||
clFlush(queue);
|
||||
do {
|
||||
int newStatus = e.getInfoInt(CL_EVENT_COMMAND_EXECUTION_STATUS);
|
||||
if ( newStatus != status ) {
|
||||
status = newStatus;
|
||||
System.out.println("NATIVE KERNEL STATUS: " + getEventStatusName(status));
|
||||
}
|
||||
} while ( status != CL_SUCCESS ); // Busy-spin until we're done
|
||||
|
||||
clReleaseEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,6 +200,19 @@ public class HelloOpenCL {
|
|||
System.out.println("\t" + param_name + " = " + device.getInfoString(param));
|
||||
}
|
||||
|
||||
private static String getEventStatusName(final int status) {
|
||||
switch ( status ) {
|
||||
case CL_QUEUED:
|
||||
return "CL_QUEUED";
|
||||
case CL_SUBMITTED:
|
||||
return "CL_SUBMITTED";
|
||||
case CL_RUNNING:
|
||||
return "CL_RUNNING";
|
||||
default:
|
||||
return "CL_COMPLETE";
|
||||
}
|
||||
}
|
||||
|
||||
private static void die(String kind, String description) {
|
||||
System.out.println(kind + " error " + description + " occured");
|
||||
}
|
||||
|
|
|
@ -132,6 +132,16 @@ public abstract class MappedObject {
|
|||
throw new InternalError("type not registered");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of mapped objects that fit in the mapped buffer.
|
||||
*
|
||||
* @return the mapped object capacity
|
||||
*/
|
||||
public final int capacity() {
|
||||
// No call-site modification for this, we override in every subclass instead.
|
||||
throw new InternalError("type not registered");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MappedObject instance, mapping the memory region of the specified direct ByteBuffer.
|
||||
* <p/>
|
||||
|
@ -200,7 +210,7 @@ public abstract class MappedObject {
|
|||
|
||||
/**
|
||||
* Any code in the default constructor will not run automatically. This method
|
||||
* can be used to run execute that code on the current view.
|
||||
* can be used to execute that code on the current view.
|
||||
*/
|
||||
public final void runViewConstructor() {
|
||||
// any method that calls this method will have its call-site modified
|
||||
|
@ -235,6 +245,18 @@ public abstract class MappedObject {
|
|||
throw new InternalError("type not registered");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link Iterable} <MappedObject> that will step through
|
||||
* <code>capacity()</code> views, leaving the <code>view</code> at
|
||||
* the last valid value.<br>
|
||||
* <p/>
|
||||
* For convenience you are encouraged to static-import this specific method:
|
||||
* <code>import static org.lwjgl.util.mapped.MappedObject.foreach;</code>
|
||||
*/
|
||||
public static <T extends MappedObject> Iterable<T> foreach(T mapped) {
|
||||
return foreach(mapped, mapped.capacity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link Iterable} <MappedObject> that will step through
|
||||
* <code>elementCount</code> views, leaving the <code>view</code> at
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
package org.lwjgl.util.mapped;
|
||||
|
||||
import org.lwjgl.LWJGLUtil;
|
||||
import org.lwjgl.MemoryUtil;
|
||||
import org.objectweb.asm.*;
|
||||
import org.objectweb.asm.tree.*;
|
||||
import org.objectweb.asm.tree.analysis.*;
|
||||
|
@ -42,6 +43,7 @@ import java.io.PrintWriter;
|
|||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -82,9 +84,9 @@ public class MappedObjectTransformer {
|
|||
static final String NEXT_METHOD_NAME = "next";
|
||||
static final String ALIGN_METHOD_NAME = "getAlign";
|
||||
static final String SIZEOF_METHOD_NAME = "getSizeof";
|
||||
static final String CAPACITY_METHOD_NAME = "capacity"; // Used for .asArray().length
|
||||
|
||||
// Internal methods
|
||||
static final String LENGTH_METHOD_NAME = "length$LWJGL"; // Used for .asArray().length
|
||||
static final String VIEW_CONSTRUCTOR_NAME = "constructView$LWJGL"; // Used by runViewConstructor
|
||||
|
||||
static final Map<Integer, String> OPCODE_TO_NAME = new HashMap<Integer, String>();
|
||||
|
@ -228,6 +230,7 @@ public class MappedObjectTransformer {
|
|||
NEXT_METHOD_NAME,
|
||||
ALIGN_METHOD_NAME,
|
||||
SIZEOF_METHOD_NAME,
|
||||
CAPACITY_METHOD_NAME,
|
||||
};
|
||||
|
||||
public MethodVisitor visitMethod(int access, final String name, final String desc, final String signature, final String[] exceptions) {
|
||||
|
@ -285,7 +288,7 @@ public class MappedObjectTransformer {
|
|||
final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className);
|
||||
|
||||
generateViewAddressGetter();
|
||||
generateLengthGetter();
|
||||
generateCapacity();
|
||||
generateAlignGetter(mappedSubtype);
|
||||
generateSizeofGetter();
|
||||
generateNext();
|
||||
|
@ -329,16 +332,25 @@ public class MappedObjectTransformer {
|
|||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generateLengthGetter() {
|
||||
MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, LENGTH_METHOD_NAME, "(L" + className + ";)I", null, null);
|
||||
private void generateCapacity() {
|
||||
// return (backingByteBuffer().capacity() + (int)(MemoryUtil.getAddress0(backingByteBuffer()) - baseAddress)) / SIZEOF;
|
||||
MethodVisitor mv = super.visitMethod(ACC_PUBLIC, CAPACITY_METHOD_NAME, "()I", null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, MAPPED_OBJECT_JVM, "backingByteBuffer", "()L" + jvmClassName(ByteBuffer.class) + ";");
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, jvmClassName(ByteBuffer.class), "capacity", "()I");
|
||||
mv.visitInsn(SWAP);
|
||||
mv.visitMethodInsn(INVOKESTATIC, jvmClassName(MemoryUtil.class), "getAddress0", "(L" + jvmClassName(Buffer.class) + ";)J");
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, MAPPED_OBJECT_JVM, "baseAddress", "J");
|
||||
mv.visitInsn(LSUB);
|
||||
mv.visitInsn(L2I);
|
||||
mv.visitInsn(IADD);
|
||||
mv.visitFieldInsn(GETSTATIC, className, "SIZEOF", "I");
|
||||
mv.visitInsn(IDIV);
|
||||
mv.visitInsn(IRETURN);
|
||||
mv.visitMaxs(2, 1);
|
||||
mv.visitMaxs(3, 1);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
|
@ -1037,7 +1049,7 @@ public class MappedObjectTransformer {
|
|||
|
||||
instructions.remove(nextInsn);
|
||||
loadInsn.var = var;
|
||||
instructions.insert(loadInsn, new MethodInsnNode(INVOKESTATIC, mappedSubtype.className, LENGTH_METHOD_NAME, "(L" + mappedSubtype.className + ";)I"));
|
||||
instructions.insert(loadInsn, new MethodInsnNode(INVOKEVIRTUAL, mappedSubtype.className, CAPACITY_METHOD_NAME, "()I"));
|
||||
|
||||
return i + 1;
|
||||
} else if ( stackSize < loadStackSize ) // Consumed by something other than AALOAD or ARRAYLENGTH
|
||||
|
|
|
@ -432,7 +432,7 @@ public interface CL10 {
|
|||
@Code(
|
||||
tryBlock = true,
|
||||
// Create a GlobalRef to the callback object.
|
||||
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
|
||||
javaBeforeNative = "\t\tlong user_data = pfn_notify == null || pfn_notify.isCustom() ? 0 : CallbackUtil.createGlobalRef(pfn_notify);",
|
||||
// Associate context with the GlobalRef, so we can delete it later.
|
||||
javaFinally = "\t\t\tCallbackUtil.registerCallback(__result, user_data);"
|
||||
)
|
||||
|
@ -845,7 +845,8 @@ public interface CL10 {
|
|||
@Code(
|
||||
tryBlock = true,
|
||||
// Create a GlobalRef to the callback object.
|
||||
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
|
||||
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);\n" +
|
||||
"\t\tif ( pfn_notify != null ) pfn_notify.setContext(program.getParent());",
|
||||
// Check if we need to delete the GlobalRef.
|
||||
javaFinally = "\t\t\tCallbackUtil.checkCallback(__result, user_data);"
|
||||
)
|
||||
|
@ -861,7 +862,8 @@ public interface CL10 {
|
|||
@Code(
|
||||
tryBlock = true,
|
||||
// Create a GlobalRef to the callback object.
|
||||
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
|
||||
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);\n" +
|
||||
"\t\tif ( pfn_notify != null ) pfn_notify.setContext(program.getParent());",
|
||||
// Check if we need to delete the GlobalRef.
|
||||
javaFinally = "\t\t\tCallbackUtil.checkCallback(__result, user_data);"
|
||||
)
|
||||
|
@ -877,7 +879,8 @@ public interface CL10 {
|
|||
@Code(
|
||||
tryBlock = true,
|
||||
// Create a GlobalRef to the callback object.
|
||||
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
|
||||
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);\n" +
|
||||
"\t\tif ( pfn_notify != null ) pfn_notify.setContext(program.getParent());",
|
||||
// Check if we need to delete the GlobalRef.
|
||||
javaFinally = "\t\t\tCallbackUtil.checkCallback(__result, user_data);"
|
||||
)
|
||||
|
|
|
@ -190,7 +190,8 @@ public interface CL11 {
|
|||
@Code(
|
||||
tryBlock = true,
|
||||
// Create a GlobalRef to the callback object.
|
||||
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
|
||||
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);\n" +
|
||||
"\t\tpfn_notify.setRegistry(event.getParentRegistry());",
|
||||
// Check if we need to delete the GlobalRef.
|
||||
javaFinally = "\t\t\tCallbackUtil.checkCallback(__result, user_data);"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue