diff --git a/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java b/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java
index 51f06e19..cb402522 100644
--- a/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java
+++ b/src/java/org/lwjgl/test/mapped/MappedObjectTests1.java
@@ -89,6 +89,15 @@ public class MappedObjectTests1 {
vecs.view = 0;
}
+ // manipulate 'view' with next()
+ {
+ assert (vecs.view == 0);
+ vecs.next();
+ assert (vecs.view == 1);
+ assert (vecs.value != 1.1f); // old view
+ vecs.view = 0;
+ }
+
// test bounds checking
{
assert (vecs.view == 0);
diff --git a/src/java/org/lwjgl/util/mapped/MappedHelper.java b/src/java/org/lwjgl/util/mapped/MappedHelper.java
index a4f2cff0..2b9b5ada 100644
--- a/src/java/org/lwjgl/util/mapped/MappedHelper.java
+++ b/src/java/org/lwjgl/util/mapped/MappedHelper.java
@@ -87,6 +87,10 @@ public class MappedHelper {
return (int)(mapped.viewAddress - mapped.baseAddress) / sizeof;
}
+ public static void put_view_next(MappedObject mapped, int sizeof) {
+ mapped.setViewAddress(mapped.viewAddress + sizeof);
+ }
+
public static MappedObject dup(MappedObject src, MappedObject dst) {
dst.baseAddress = src.baseAddress;
dst.viewAddress = src.viewAddress;
diff --git a/src/java/org/lwjgl/util/mapped/MappedObject.java b/src/java/org/lwjgl/util/mapped/MappedObject.java
index 8605b1f5..9d3a93b0 100644
--- a/src/java/org/lwjgl/util/mapped/MappedObject.java
+++ b/src/java/org/lwjgl/util/mapped/MappedObject.java
@@ -86,12 +86,7 @@ public class MappedObject {
*/
public int view;
- /** Moves the current view to the next element. */
- public final void next() {
- setViewAddress(this.viewAddress + this.sizeof);
- }
-
- final void setViewAddress(final long address) {
+ public final void setViewAddress(final long address) {
if ( CHECKS )
checkAddress(address);
this.viewAddress = address;
@@ -99,8 +94,9 @@ public class MappedObject {
final void checkAddress(final long address) {
final long base = MappedObjectUnsafe.getBufferBaseAddress(preventGC);
- if ( address < base || preventGC.capacity() < (address - base + this.sizeof) )
- throw new IndexOutOfBoundsException();
+ final int offset = (int)(address - base);
+ if ( address < base || preventGC.capacity() < (offset + this.sizeof) )
+ throw new IndexOutOfBoundsException(Integer.toString(offset / sizeof));
}
final void checkRange(final int bytes) {
@@ -186,6 +182,12 @@ public class MappedObject {
throw new InternalError("type not registered");
}
+ /** Moves the current view to the next element. */
+ public final void next() {
+ // any method that calls this method will have its call-site modified
+ throw new InternalError("type not registered");
+ }
+
/**
* Copies and amount of SIZEOF
bytes, from the current
* mapped object, to the specified mapped object.
diff --git a/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java b/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java
index c20eda5c..ea987002 100644
--- a/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java
+++ b/src/java/org/lwjgl/util/mapped/MappedObjectTransformer.java
@@ -38,6 +38,9 @@ public class MappedObjectTransformer {
static final Map className_to_subtype;
+ static final String MAPPED_OBJECT_JVM = jvmClassName(MappedObject.class);
+ static final String MAPPED_HELPER_JVM = jvmClassName(MappedHelper.class);
+
static {
className_to_subtype = new HashMap();
@@ -56,7 +59,7 @@ public class MappedObjectTransformer {
// => IADD
// => PUTFIELD MyMappedType.view
//
- MappedSubtypeInfo info = new MappedSubtypeInfo(jvmClassName(MappedObject.class), -1, -1);
+ MappedSubtypeInfo info = new MappedSubtypeInfo(MAPPED_OBJECT_JVM, -1, -1);
className_to_subtype.put(info.className, info);
}
@@ -162,7 +165,7 @@ public class MappedObjectTransformer {
{
MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className);
- if ( mappedSubtype != null && !mappedSubtype.className.equals(jvmClassName(MappedObject.class)) ) {
+ if ( mappedSubtype != null && !mappedSubtype.className.equals(MAPPED_OBJECT_JVM) ) {
if ( "".equals(name) ) {
if ( !"()V".equals(desc) )
throw new IllegalStateException(className + " can only have a default constructor, found: " + desc);
@@ -170,7 +173,7 @@ public class MappedObjectTransformer {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
- mv.visitMethodInsn(INVOKESPECIAL, jvmClassName(MappedObject.class), "", "()V");
+ mv.visitMethodInsn(INVOKESPECIAL, MAPPED_OBJECT_JVM, "", "()V");
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
@@ -181,7 +184,7 @@ public class MappedObjectTransformer {
}
}
- return new MappedInstanceMethodAdapter(className, name, desc, super.visitMethod(access, name, desc, signature, exceptions));
+ return new MappedInstanceMethodAdapter(access, className, name, desc, super.visitMethod(access, name, desc, signature, exceptions));
}
@Override
@@ -252,17 +255,25 @@ public class MappedObjectTransformer {
@Override
public void visitMethodInsn(int opcode, String className, String methodName, String signature) {
- if ( opcode == INVOKESPECIAL && className.equals(jvmClassName(MappedObject.class)) && "".equals(methodName) && "()V".equals(signature) ) {
+ if ( opcode == INVOKESPECIAL && className.equals(MAPPED_OBJECT_JVM) && "".equals(methodName) && "()V".equals(signature) ) {
// stack: instance
visitInsn(POP);
// stack: -
return;
}
- for ( MappedSubtypeInfo mappedType : className_to_subtype.values() ) {
- boolean isMapDirectMethod = (opcode == INVOKESTATIC && "map".equals(methodName) && className.equals(mappedType.className) && signature.equals("(JI)L" + jvmClassName(MappedObject.class) + ";"));
- boolean isMapBufferMethod = (opcode == INVOKESTATIC && "map".equals(methodName) && className.equals(mappedType.className) && signature.equals("(Ljava/nio/ByteBuffer;)L" + jvmClassName(MappedObject.class) + ";"));
- boolean isMallocMethod = (opcode == INVOKESTATIC && "malloc".equals(methodName) && className.equals(mappedType.className) && signature.equals("(I)L" + jvmClassName(MappedObject.class) + ";"));
+ MappedSubtypeInfo mappedType = className_to_subtype.get(className);
+ if ( mappedType != null && visitMappedMethod(opcode, className, methodName, signature, mappedType) )
+ return;
+
+ super.visitMethodInsn(opcode, className, methodName, signature);
+ }
+
+ private boolean visitMappedMethod(final int opcode, final String className, final String methodName, final String signature, final MappedSubtypeInfo mappedType) {
+ if ( opcode == INVOKESTATIC ) {
+ boolean isMapDirectMethod = "map".equals(methodName) && signature.equals("(JI)L" + MAPPED_OBJECT_JVM + ";");
+ boolean isMapBufferMethod = "map".equals(methodName) && signature.equals("(Ljava/nio/ByteBuffer;)L" + MAPPED_OBJECT_JVM + ";");
+ boolean isMallocMethod = "malloc".equals(methodName) && signature.equals("(I)L" + MAPPED_OBJECT_JVM + ";");
if ( (isMapDirectMethod || isMapBufferMethod) || isMallocMethod ) {
if ( isMallocMethod ) {
@@ -275,7 +286,7 @@ public class MappedObjectTransformer {
// stack: buffer
} else if ( isMapDirectMethod ) {
// stack: capacity, address
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "newBuffer", "(JI)L" + jvmClassName(ByteBuffer.class) + ";");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "newBuffer", "(JI)L" + jvmClassName(ByteBuffer.class) + ";");
// stack: buffer
}
@@ -294,12 +305,12 @@ public class MappedObjectTransformer {
// stack: int, buffer, new, new
pushInt(super.mv, mappedType.sizeof);
// stack: int, int, buffer, new, new
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "setup", "(L" + jvmClassName(MappedObject.class) + ";Ljava/nio/ByteBuffer;II)V");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "setup", "(L" + MAPPED_OBJECT_JVM + ";Ljava/nio/ByteBuffer;II)V");
// stack: new
- return;
+ return true;
}
-
- if ( opcode == INVOKEVIRTUAL && "dup".equals(methodName) && className.equals(mappedType.className) && signature.equals("()L" + jvmClassName(MappedObject.class) + ";") ) {
+ } else if ( opcode == INVOKEVIRTUAL ) {
+ if ( "dup".equals(methodName) && signature.equals("()L" + MAPPED_OBJECT_JVM + ";") ) {
// stack: this
super.visitTypeInsn(NEW, className);
// stack: new, this
@@ -307,12 +318,12 @@ public class MappedObjectTransformer {
// stack: new, new, this
super.visitMethodInsn(INVOKESPECIAL, className, "", "()V");
// stack: new, this
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "dup", "(L" + jvmClassName(MappedObject.class) + ";L" + jvmClassName(MappedObject.class) + ";)L" + jvmClassName(MappedObject.class) + ";");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "dup", "(L" + MAPPED_OBJECT_JVM + ";L" + MAPPED_OBJECT_JVM + ";)L" + MAPPED_OBJECT_JVM + ";");
// stack: new
- return;
+ return true;
}
- if ( opcode == INVOKEVIRTUAL && "slice".equals(methodName) && className.equals(mappedType.className) && signature.equals("()L" + jvmClassName(MappedObject.class) + ";") ) {
+ if ( "slice".equals(methodName) && signature.equals("()L" + MAPPED_OBJECT_JVM + ";") ) {
// stack: this
super.visitTypeInsn(NEW, className);
// stack: new, this
@@ -320,46 +331,55 @@ public class MappedObjectTransformer {
// stack: new, new, this
super.visitMethodInsn(INVOKESPECIAL, className, "", "()V");
// stack: new, this
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "slice", "(L" + jvmClassName(MappedObject.class) + ";L" + jvmClassName(MappedObject.class) + ";)L" + jvmClassName(MappedObject.class) + ";");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "slice", "(L" + MAPPED_OBJECT_JVM + ";L" + MAPPED_OBJECT_JVM + ";)L" + MAPPED_OBJECT_JVM + ";");
// stack: new
- return;
+ return true;
}
//
- if ( opcode == INVOKEVIRTUAL && "runViewConstructor".equals(methodName) && className.equals(mappedType.className) && "()V".equals(signature) ) {
+ if ( "runViewConstructor".equals(methodName) && "()V".equals(signature) ) {
// stack: this
super.visitInsn(DUP);
// stack: this, this
super.visitMethodInsn(INVOKEVIRTUAL, className, view_constructor_method, "()V");
// stack: this
- return;
+ return true;
}
//
- if ( opcode == INVOKEVIRTUAL && "copyTo".equals(methodName) && className.equals(mappedType.className) && signature.equals("(L" + jvmClassName(MappedObject.class) + ";)V") ) {
+ if ( "copyTo".equals(methodName) && signature.equals("(L" + MAPPED_OBJECT_JVM + ";)V") ) {
// stack: target, this
pushInt(super.mv, mappedType.sizeof);
// stack: sizeof, target, this
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "copy", "(L" + jvmClassName(MappedObject.class) + ";L" + jvmClassName(MappedObject.class) + ";I)V");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "copy", "(L" + MAPPED_OBJECT_JVM + ";L" + MAPPED_OBJECT_JVM + ";I)V");
// stack: -
- return;
+ return true;
}
- if ( opcode == INVOKEVIRTUAL && "copyRange".equals(methodName) && className.equals(mappedType.className) && signature.equals("(L" + jvmClassName(MappedObject.class) + ";I)V") ) {
+ if ( "copyRange".equals(methodName) && signature.equals("(L" + MAPPED_OBJECT_JVM + ";I)V") ) {
// stack: instances, target, this
pushInt(super.mv, mappedType.sizeof);
// stack: sizeof, instances, target, this
super.visitInsn(IMUL);
// stack: bytes, target, this
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "copy", "(L" + jvmClassName(MappedObject.class) + ";L" + jvmClassName(MappedObject.class) + ";I)V");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "copy", "(L" + MAPPED_OBJECT_JVM + ";L" + MAPPED_OBJECT_JVM + ";I)V");
// stack: -
- return;
+ return true;
+ }
+
+ if ( "next".equals(methodName) && "()V".equals(signature) ) {
+ // stack: this
+ pushInt(super.mv, mappedType.sizeof);
+ // stack: sizeof, this
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_view_next", "(L" + MAPPED_OBJECT_JVM + ";I)V");
+ // stack: -
+ return true;
}
}
- super.visitMethodInsn(opcode, className, methodName, signature);
+ return false;
}
private static void throwAccessErrorOnReadOnlyField(String className, String fieldName) {
@@ -384,11 +404,11 @@ public class MappedObjectTransformer {
if ( false )
break outer;
else if ( className.equals(jvmClassName(MappedSet2.class)) )
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_views", "(L" + jvmClassName(MappedSet2.class) + ";I)V");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_views", "(L" + jvmClassName(MappedSet2.class) + ";I)V");
else if ( className.equals(jvmClassName(MappedSet3.class)) )
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_views", "(L" + jvmClassName(MappedSet3.class) + ";I)V");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_views", "(L" + jvmClassName(MappedSet3.class) + ";I)V");
else if ( className.equals(jvmClassName(MappedSet4.class)) )
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_views", "(L" + jvmClassName(MappedSet4.class) + ";I)V");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_views", "(L" + jvmClassName(MappedSet4.class) + ";I)V");
else
break outer;
// stack: -
@@ -421,7 +441,7 @@ public class MappedObjectTransformer {
// stack: instance
pushInt(super.mv, mappedSubtype.sizeof);
// stack: sizeof, instance
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "get_view", "(L" + jvmClassName(MappedObject.class) + ";I)I");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "get_view", "(L" + MAPPED_OBJECT_JVM + ";I)I");
// stack: view
return;
}
@@ -429,7 +449,7 @@ public class MappedObjectTransformer {
// stack: view, instance
pushInt(super.mv, mappedSubtype.sizeof);
// stack: sizeof, view, instance
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "put_view", "(L" + jvmClassName(MappedObject.class) + ";II)V");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "put_view", "(L" + MAPPED_OBJECT_JVM + ";II)V");
// stack: -
return;
}
@@ -494,7 +514,7 @@ public class MappedObjectTransformer {
// stack: long, long
super.visitInsn(L2I);
// stack: int, long
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), "newBuffer", "(JI)L" + jvmClassName(ByteBuffer.class) + ";");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, "newBuffer", "(JI)L" + jvmClassName(ByteBuffer.class) + ";");
// stack: buffer
return;
}
@@ -512,7 +532,7 @@ public class MappedObjectTransformer {
// stack: offset, viewAddr, value
super.visitInsn(LADD);
// stack: fieldAddr, value
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), typeName.toLowerCase() + "put", "(" + typeName + "J)V");
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, typeName.toLowerCase() + "put", "(" + typeName + "J)V");
// stack -
return;
@@ -525,7 +545,7 @@ public class MappedObjectTransformer {
// stack: fieldOffset, viewAddr
super.visitInsn(LADD);
// stack: fieldAddr
- super.visitMethodInsn(INVOKESTATIC, jvmClassName(MappedHelper.class), typeName.toLowerCase() + "get", "(J)" + typeName);
+ super.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, typeName.toLowerCase() + "get", "(J)" + typeName);
// stack: value
return;