Converted sizeof and align to methods.

Override more methods in MappedObject subclasses, foreach is now 4 times faster.
This commit is contained in:
Ioannis Tsakpinis 2011-07-22 20:09:01 +00:00
parent 20b9d3f89f
commit 896e363979
10 changed files with 184 additions and 122 deletions

View File

@ -60,8 +60,8 @@ public class MappedObjectTests1 {
{
MappedFloat vecs1 = MappedFloat.malloc(1234);
assert (vecs1.sizeof == MappedFloat.SIZEOF);
assert (vecs1.sizeof * 1234 == vecs1.backingByteBuffer().capacity());
assert (vecs1.getSizeof() == MappedFloat.SIZEOF);
assert (vecs1.getSizeof() * 1234 == vecs1.backingByteBuffer().capacity());
assert (MappedFloat.SIZEOF * 1234 == vecs1.backingByteBuffer().capacity());
}

View File

@ -44,7 +44,7 @@ public class MappedObjectTests2 {
System.out.println(vecs.viewAddress); // test read-access
System.out.println(vecs.align); // test read-access
System.out.println(vecs.getAlign()); // test read-access
System.out.println(MappedVec3.SIZEOF); // test read-access
}
@ -91,7 +91,7 @@ public class MappedObjectTests2 {
vecs.view = 1;
long a2 = vecs.viewAddress;
assert (a2 - a1 == MappedVec3.SIZEOF);
assert (a2 - a1 == vecs.sizeof);
assert (a2 - a1 == vecs.getSizeof());
vecs.view = 0;
}
}

View File

@ -58,7 +58,7 @@ final class MappedForeach<T extends MappedObject> implements Iterable<T> {
}
public T next() {
MappedHelper.put_view(mapped, this.index++, mapped.sizeof);
mapped.setViewAddress(mapped.getViewAddress(this.index++));
return mapped;
}

View File

@ -55,11 +55,9 @@ public class MappedHelper {
if ( LWJGLUtil.CHECKS && align <= 0 )
throw new IllegalArgumentException("invalid alignment");
mo.align = align;
if ( LWJGLUtil.CHECKS && (sizeof <= 0 || sizeof % align != 0) )
throw new IllegalStateException("sizeof not a multiple of alignment");
mo.sizeof = sizeof;
long addr = MemoryUtil.getAddress(buffer);
if ( LWJGLUtil.CHECKS && addr % align != 0 )
@ -107,8 +105,6 @@ public class MappedHelper {
public static MappedObject dup(MappedObject src, MappedObject dst) {
dst.baseAddress = src.baseAddress;
dst.viewAddress = src.viewAddress;
dst.align = src.align;
dst.sizeof = src.sizeof;
dst.preventGC = src.preventGC;
return dst;
}
@ -116,8 +112,6 @@ public class MappedHelper {
public static MappedObject slice(MappedObject src, MappedObject dst) {
dst.baseAddress = src.viewAddress; // !
dst.viewAddress = src.viewAddress;
dst.align = src.align;
dst.sizeof = src.sizeof;
dst.preventGC = src.preventGC;
return dst;
}

View File

@ -50,11 +50,11 @@ import java.nio.ByteBuffer;
*
* @author Riven
*/
public class MappedObject {
public abstract class MappedObject {
static final boolean CHECKS = LWJGLUtil.getPrivilegedBoolean("org.lwjgl.util.mapped.Checks");
public MappedObject() {
protected MappedObject() {
//
}
@ -64,11 +64,8 @@ public class MappedObject {
/** The mapped object view memory address, in bytes. Read-only. */
public long viewAddress;
/** The mapped object memory alignment, in bytes. Read-only. */
public int align;
/** The mapped object memory sizeof, in bytes. Read-only. */
public int sizeof;
/** The mapped buffer. */
ByteBuffer preventGC;
/**
* Holds the value of sizeof of the sub-type of this MappedObject<br>
@ -87,6 +84,12 @@ public class MappedObject {
*/
public int view;
protected final long getViewAddress(final int view) {
// No call-site modification for this, we override in every subclass instead,
// so that we can use it in MappedForeach.
throw new InternalError("type not registered");
}
public final void setViewAddress(final long address) {
if ( CHECKS )
checkAddress(address);
@ -96,8 +99,8 @@ public class MappedObject {
final void checkAddress(final long address) {
final long base = MemoryUtil.getAddress0(preventGC);
final int offset = (int)(address - base);
if ( address < base || preventGC.capacity() < (offset + this.sizeof) )
throw new IndexOutOfBoundsException(Integer.toString(offset / sizeof));
if ( address < base || preventGC.capacity() < (offset + getSizeof()) )
throw new IndexOutOfBoundsException(Integer.toString(offset / getSizeof()));
}
final void checkRange(final int bytes) {
@ -108,6 +111,27 @@ public class MappedObject {
throw new BufferOverflowException();
}
/** The mapped object memory alignment, in bytes. Read-only. */
/**
* Returns the mapped object memory alignment, in bytes.
*
* @return the memory alignment
*/
public final int getAlign() {
// No call-site modification for this, we override in every subclass instead.
throw new InternalError("type not registered");
}
/**
* Returns the mapped object memory sizeof, in bytes.
*
* @return the sizeof value
*/
public final int getSizeof() {
// 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/>
@ -178,22 +202,18 @@ public 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.
*/
public final <T extends MappedObject> void runViewConstructor() {
public final void runViewConstructor() {
// any method that calls this method will have its call-site modified
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
// No call-site modification for this, we override in every subclass instead,
// so that we can use it in MappedSetX.
throw new InternalError("type not registered");
}
/** Moves the current view to the next element. Non-transformed implementation for MappedSets. */
final void nextSet() {
setViewAddress(viewAddress + sizeof);
}
/**
* Copies and amount of <code>SIZEOF</code> bytes, from the current
* mapped object, to the specified mapped object.
@ -232,14 +252,12 @@ public class MappedObject {
throw new InternalError("type not registered");
}
ByteBuffer preventGC;
/**
* Returns the {@link java.nio.ByteBuffer} that backs this mapped object.
*
* @return the backing buffer
*/
public ByteBuffer backingByteBuffer() {
public final ByteBuffer backingByteBuffer() {
return this.preventGC;
}

View File

@ -73,7 +73,9 @@ public class MappedObjectClassLoader extends URLClassLoader {
FORKED = true;
try {
URLClassLoader loader = new MappedObjectClassLoader(mainClass);
MappedObjectClassLoader loader = new MappedObjectClassLoader(mainClass);
loader.loadMappedObject();
Class<?> replacedMainClass = loader.loadClass(mainClass.getName());
Method mainMethod = replacedMainClass.getMethod("main", String[].class);
mainMethod.invoke(null, new Object[] { args });
@ -90,6 +92,28 @@ public class MappedObjectClassLoader extends URLClassLoader {
super(((URLClassLoader)mainClass.getClassLoader()).getURLs());
}
protected synchronized Class<?> loadMappedObject() throws ClassNotFoundException {
final String name = MappedObject.class.getName();
String className = name.replace('.', '/');
if ( MappedObjectTransformer.PRINT_ACTIVITY )
LWJGLUtil.log(MappedObjectClassLoader.class.getSimpleName() + ": " + className);
byte[] bytecode = readStream(this.getResourceAsStream(className.concat(".class")));
long t0 = System.nanoTime();
bytecode = MappedObjectTransformer.transformMappedObject(bytecode);
long t1 = System.nanoTime();
total_time_transforming += (t1 - t0);
if ( MappedObjectTransformer.PRINT_TIMING )
LWJGLUtil.log("transforming " + className + " took " + (t1 - t0) / 1000 + " micros (total: " + (total_time_transforming / 1000 / 1000) + "ms)");
Class<?> clazz = super.defineClass(name, bytecode, 0, bytecode.length);
resolveClass(clazz);
return clazz;
}
private static long total_time_transforming;
@Override
@ -104,10 +128,8 @@ public class MappedObjectClassLoader extends URLClassLoader {
if ( name.startsWith("sunw.") )
return super.loadClass(name, resolve);
// never transform classes in this very package, sub-packages should be transformed
if ( name.startsWith(MAPPEDOBJECT_PACKAGE_PREFIX) )
if ( name.substring(MAPPEDOBJECT_PACKAGE_PREFIX.length()).indexOf('.') == -1 )
return super.loadClass(name, resolve);
if ( name.equals(MappedObjectClassLoader.class.getName()) )
return super.loadClass(name, resolve);
String className = name.replace('.', '/');
@ -116,13 +138,16 @@ public class MappedObjectClassLoader extends URLClassLoader {
byte[] bytecode = readStream(this.getResourceAsStream(className.concat(".class")));
long t0 = System.nanoTime();
bytecode = MappedObjectTransformer.transformMappedAPI(className, bytecode);
long t1 = System.nanoTime();
total_time_transforming += (t1 - t0);
// Classes in this package do not get transformed, but need to go through here because we have transformed MappedObject.
if ( !(name.startsWith(MAPPEDOBJECT_PACKAGE_PREFIX) && name.substring(MAPPEDOBJECT_PACKAGE_PREFIX.length()).indexOf('.') == -1) ) {
long t0 = System.nanoTime();
bytecode = MappedObjectTransformer.transformMappedAPI(className, bytecode);
long t1 = System.nanoTime();
if ( MappedObjectTransformer.PRINT_TIMING )
LWJGLUtil.log("transforming " + className + " took " + (t1 - t0) / 1000 + " micros (total: " + (total_time_transforming / 1000 / 1000) + "ms)");
total_time_transforming += (t1 - t0);
if ( MappedObjectTransformer.PRINT_TIMING )
LWJGLUtil.log("transforming " + className + " took " + (t1 - t0) / 1000 + " micros (total: " + (total_time_transforming / 1000 / 1000) + "ms)");
}
Class<?> clazz = super.defineClass(name, bytecode, 0, bytecode.length);
if ( resolve )

View File

@ -35,6 +35,7 @@ import org.lwjgl.LWJGLUtil;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.*;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.util.TraceClassVisitor;
import java.io.PrintWriter;
@ -76,9 +77,15 @@ public class MappedObjectTransformer {
static final String MAPPED_SET3_JVM = jvmClassName(MappedSet3.class);
static final String MAPPED_SET4_JVM = jvmClassName(MappedSet4.class);
static final String LENGTH_METHOD_NAME = "length$LWJGL";
static final String VIEWADDRESS_METHOD_NAME = "getViewAddress$LWJGL";
static final String VIEW_CONSTRUCTOR_NAME = "constructView$LWJGL";
// Public methods
static final String VIEWADDRESS_METHOD_NAME = "getViewAddress";
static final String NEXT_METHOD_NAME = "next";
static final String ALIGN_METHOD_NAME = "getAlign";
static final String SIZEOF_METHOD_NAME = "getSizeof";
// 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>();
static final Map<Integer, String> INSNTYPE_TO_NAME = new HashMap<Integer, String>();
@ -122,9 +129,6 @@ public class MappedObjectTransformer {
* @param type the mapped object class.
*/
public static void register(Class<?> type) {
if ( MappedObjectClassLoader.FORKED )
return;
final MappedType mapped = type.getAnnotation(MappedType.class);
if ( mapped == null )
throw new InternalError("missing " + MappedType.class.getName() + " annotation");
@ -185,6 +189,34 @@ public class MappedObjectTransformer {
return (int)byteLength;
}
/** Removes final from methods that will be overriden by subclasses. */
static byte[] transformMappedObject(byte[] bytecode) {
final ClassWriter cw = new ClassWriter(0);
ClassVisitor cv = new ClassAdapter(cw) {
private final String[] DEFINALIZE_LIST = {
VIEWADDRESS_METHOD_NAME,
NEXT_METHOD_NAME,
ALIGN_METHOD_NAME,
SIZEOF_METHOD_NAME,
};
public MethodVisitor visitMethod(int access, final String name, final String desc, final String signature, final String[] exceptions) {
for ( String method : DEFINALIZE_LIST ) {
if ( name.equals(method) ) {
access &= ~ACC_FINAL;
break;
}
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
};
new ClassReader(bytecode).accept(cv, 0);
return cw.toByteArray();
}
static byte[] transformMappedAPI(final String className, byte[] bytecode) {
final ClassWriter cw = new ClassWriter(COMPUTE_FRAMES) {
@ -203,8 +235,7 @@ public class MappedObjectTransformer {
if ( className_to_subtype.containsKey(className) ) // Do a first pass to generate address getters
cv = getMethodGenAdapter(className, cv);
//cr.accept(cv, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
new ClassReader(bytecode).accept(cv, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
new ClassReader(bytecode).accept(cv, ClassReader.SKIP_FRAMES);
bytecode = cw.toByteArray();
if ( PRINT_BYTECODE )
@ -218,10 +249,13 @@ public class MappedObjectTransformer {
@Override
public void visitEnd() {
final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className);
generateViewAddressGetter();
generateLengthGetter();
final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className);
generateAlignGetter(mappedSubtype);
generateSizeofGetter();
generateNext();
for ( String fieldName : mappedSubtype.fieldToOffset.keySet() ) {
final Type type = mappedSubtype.fieldToType.get(fieldName);
@ -238,7 +272,7 @@ public class MappedObjectTransformer {
}
private void generateViewAddressGetter() {
MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, VIEWADDRESS_METHOD_NAME, "(L" + className + ";I)J", null, null);
MethodVisitor mv = super.visitMethod(ACC_PUBLIC, VIEWADDRESS_METHOD_NAME, "(I)J", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, MAPPED_OBJECT_JVM, "baseAddress", "J");
@ -266,7 +300,7 @@ public class MappedObjectTransformer {
MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, LENGTH_METHOD_NAME, "(L" + className + ";)I", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, className, "backingByteBuffer", "()L" + jvmClassName(ByteBuffer.class) + ";");
mv.visitMethodInsn(INVOKEVIRTUAL, MAPPED_OBJECT_JVM, "backingByteBuffer", "()L" + jvmClassName(ByteBuffer.class) + ";");
mv.visitMethodInsn(INVOKEVIRTUAL, jvmClassName(ByteBuffer.class), "capacity", "()I");
mv.visitFieldInsn(GETSTATIC, className, "SIZEOF", "I");
mv.visitInsn(IDIV);
@ -275,12 +309,45 @@ public class MappedObjectTransformer {
mv.visitEnd();
}
private void generateAlignGetter(final MappedSubtypeInfo mappedSubtype) {
MethodVisitor mv = super.visitMethod(ACC_PUBLIC, ALIGN_METHOD_NAME, "()I", null, null);
mv.visitCode();
visitIntNode(mv, mappedSubtype.sizeof);
mv.visitInsn(IRETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
private void generateSizeofGetter() {
MethodVisitor mv = super.visitMethod(ACC_PUBLIC, SIZEOF_METHOD_NAME, "()I", null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, className, "SIZEOF", "I");
mv.visitInsn(IRETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
private void generateNext() {
MethodVisitor mv = super.visitMethod(ACC_PUBLIC, NEXT_METHOD_NAME, "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitFieldInsn(GETFIELD, MAPPED_OBJECT_JVM, "viewAddress", "J");
mv.visitFieldInsn(GETSTATIC, className, "SIZEOF", "I");
mv.visitInsn(I2L);
mv.visitInsn(LADD);
mv.visitMethodInsn(INVOKEVIRTUAL, className, "setViewAddress", "(J)V");
mv.visitInsn(RETURN);
mv.visitMaxs(3, 1);
mv.visitEnd();
}
private void generateByteBufferGetter(final MappedSubtypeInfo mappedSubtype, final String fieldName, final Type type) {
MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, getterName(fieldName), "(L" + className + ";I)" + type.getDescriptor(), null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 1);
mv.visitMethodInsn(INVOKESTATIC, className, VIEWADDRESS_METHOD_NAME, "(L" + className + ";I)J");
mv.visitMethodInsn(INVOKEVIRTUAL, className, VIEWADDRESS_METHOD_NAME, "(I)J");
visitIntNode(mv, mappedSubtype.fieldToOffset.get(fieldName).intValue());
mv.visitInsn(I2L);
mv.visitInsn(LADD);
@ -296,13 +363,13 @@ public class MappedObjectTransformer {
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 1);
mv.visitMethodInsn(INVOKESTATIC, className, VIEWADDRESS_METHOD_NAME, "(L" + className + ";I)J");
mv.visitMethodInsn(INVOKEVIRTUAL, className, VIEWADDRESS_METHOD_NAME, "(I)J");
visitIntNode(mv, mappedSubtype.fieldToOffset.get(fieldName).intValue());
mv.visitInsn(I2L);
mv.visitInsn(LADD);
mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, type.getDescriptor().toLowerCase() + "get", "(J)" + type.getDescriptor());
mv.visitInsn(type.getOpcode(IRETURN));
mv.visitMaxs(2, 2);
mv.visitMaxs(3, 2);
mv.visitEnd();
}
@ -331,13 +398,13 @@ public class MappedObjectTransformer {
mv.visitVarInsn(load, 2);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 1);
mv.visitMethodInsn(INVOKESTATIC, className, VIEWADDRESS_METHOD_NAME, "(L" + className + ";I)J");
mv.visitMethodInsn(INVOKEVIRTUAL, className, VIEWADDRESS_METHOD_NAME, "(I)J");
visitIntNode(mv, mappedSubtype.fieldToOffset.get(fieldName).intValue());
mv.visitInsn(I2L);
mv.visitInsn(LADD);
mv.visitMethodInsn(INVOKESTATIC, MAPPED_HELPER_JVM, type.getDescriptor().toLowerCase() + "put", "(" + type.getDescriptor() + "J)V");
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitMaxs(4, 3);
mv.visitEnd();
}
@ -415,12 +482,14 @@ public class MappedObjectTransformer {
@Override
public void visitEnd() {
if ( needsTransformation ) // Early-out for methods that do not touch a mapped object.
if ( needsTransformation ) { // Early-out for methods that do not touch a mapped object.
//System.err.println("\nTRANSFORMING: " + className + "." + name + desc);
try {
transformMethod(analyse());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// Pass the instruction stream to the adapter's MethodVisitor
accept(mv);
@ -433,8 +502,6 @@ public class MappedObjectTransformer {
}
private void transformMethod(final Frame<BasicValue>[] frames) {
//System.err.println("\nTRANSFORMING: " + className + " - " + name + desc);
final InsnList instructions = this.instructions;
final Map<Integer, MappedSubtypeInfo> arrayVars = new HashMap<Integer, MappedSubtypeInfo>();
@ -540,10 +607,6 @@ public class MappedObjectTransformer {
break;
}
if ( "next".equals(methodInsn.name) && "()V".equals(methodInsn.desc) ) {
i = replace(instructions, i, methodInsn, generateNextInstructions(mappedType));
break;
}
break;
case INVOKESPECIAL:
// super() in VIEW_CONSTRUCTOR_NAME, remove
@ -567,18 +630,6 @@ public class MappedObjectTransformer {
return i;
}
private static InsnList generateNextInstructions(final MappedSubtypeInfo mappedType) {
final InsnList list = new InsnList();
// stack: this
list.add(getIntNode(mappedType.sizeof));
// stack: sizeof, this
list.add(new MethodInsnNode(INVOKESTATIC, MAPPED_HELPER_JVM, "put_view_next", "(L" + MAPPED_OBJECT_JVM + ";I)V"));
// stack: -
return list;
}
private static InsnList generateCopyRangeInstructions(final MappedSubtypeInfo mappedType) {
final InsnList list = new InsnList();
@ -705,9 +756,6 @@ public class MappedObjectTransformer {
if ( "view".equals(fieldInsn.name) )
return generateViewInstructions(fieldInsn, mappedSubtype);
if ( "align".equals(fieldInsn.name) || "sizeof".equals(fieldInsn.name) )
return generateAlignSizeofInstructions(fieldInsn, mappedSubtype);
if ( "baseAddress".equals(fieldInsn.name) || "viewAddress".equals(fieldInsn.name) ) {
return generateAddressInstructions(fieldInsn);
}
@ -806,29 +854,6 @@ public class MappedObjectTransformer {
throw new InternalError();
}
private static InsnList generateAlignSizeofInstructions(final FieldInsnNode fieldInsn, final MappedSubtypeInfo mappedSubtype) {
if ( !"I".equals(fieldInsn.desc) )
throw new InternalError();
if ( fieldInsn.getOpcode() == GETFIELD ) {
final InsnList list = new InsnList();
// stack: instance
list.add(new InsnNode(POP));
// stack: -
if ( "sizeof".equals(fieldInsn.name) )
list.add(getIntNode(mappedSubtype.sizeof));
else if ( "align".equals(fieldInsn.name) )
list.add(getIntNode(mappedSubtype.align));
// stack: int
return list;
}
if ( fieldInsn.getOpcode() == PUTFIELD )
throwAccessErrorOnReadOnlyField(fieldInsn.owner, fieldInsn.name);
throw new InternalError();
}
private static InsnList generateAddressInstructions(final FieldInsnNode fieldInsn) {
if ( !"J".equals(fieldInsn.desc) )
throw new IllegalStateException();
@ -961,7 +986,7 @@ public class MappedObjectTransformer {
nextInsn = getter;
continue;
} else if ( stackSize < loadStackSize )
throw new ClassFormatError("Invalid .asArray() usage detected: " + getOpcodeName(nextInsn));
throw new ClassFormatError("Invalid " + mappedSubtype.className + " view array usage detected: " + getOpcodeName(nextInsn));
}
instructions.remove(aaLoadInsn);

View File

@ -44,13 +44,13 @@ public class MappedSet2 {
public int view;
void view(int view) {
MappedHelper.put_view(this.a, view, this.a.sizeof);
MappedHelper.put_view(this.b, view, this.b.sizeof);
a.setViewAddress(a.getViewAddress(view));
b.setViewAddress(b.getViewAddress(view));
}
public void next() {
this.a.nextSet();
this.b.nextSet();
this.a.next();
this.b.next();
}
}

View File

@ -45,15 +45,15 @@ public class MappedSet3 {
public int view;
void view(int view) {
MappedHelper.put_view(this.a, view, this.a.sizeof);
MappedHelper.put_view(this.b, view, this.b.sizeof);
MappedHelper.put_view(this.c, view, this.c.sizeof);
a.setViewAddress(a.getViewAddress(view));
b.setViewAddress(b.getViewAddress(view));
c.setViewAddress(c.getViewAddress(view));
}
public void next() {
this.a.nextSet();
this.b.nextSet();
this.c.nextSet();
this.a.next();
this.b.next();
this.c.next();
}
}

View File

@ -46,16 +46,16 @@ public class MappedSet4 {
public int view;
void view(int view) {
MappedHelper.put_view(this.a, view, this.a.sizeof);
MappedHelper.put_view(this.b, view, this.b.sizeof);
MappedHelper.put_view(this.c, view, this.c.sizeof);
MappedHelper.put_view(this.d, view, this.d.sizeof);
a.setViewAddress(a.getViewAddress(view));
b.setViewAddress(b.getViewAddress(view));
c.setViewAddress(c.getViewAddress(view));
d.setViewAddress(d.getViewAddress(view));
}
public void next() {
this.a.nextSet();
this.b.nextSet();
this.c.nextSet();
this.d.nextSet();
this.a.next();
this.b.next();
this.c.next();
this.d.next();
}
}