Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Working asm based P6Opaque.
  • Loading branch information
donaldh committed Mar 5, 2013
1 parent d5207b0 commit 9f4368e
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 60 deletions.
4 changes: 2 additions & 2 deletions Makefile
Expand Up @@ -28,7 +28,7 @@ all: $(NQPLIBS)

bin: $(JAVAS)
$(PERL) -MExtUtils::Command -e mkpath bin
$(JAVAC) -source 1.7 -cp 3rdparty/asm/asm-4.1.jar:3rdparty/bcel/bcel-5.2.jar -d bin $(JAVAS)
$(JAVAC) -source 1.7 -cp 3rdparty/asm/asm-debug-all-4.1.jar:3rdparty/bcel/bcel-5.2.jar -g -d bin $(JAVAS)

test: all
$(PROVE) --exec=$(NQP) t/jast/*.t t/qast/*.t
Expand All @@ -37,7 +37,7 @@ nqptest: all
$(PROVE) --exec="$(NQP) nqp-jvm-cc.nqp" t/nqp/*.t

selftest: all
$(PROVE) --exec="java -cp .:bin:3rdparty/asm/asm-4.1.jar:3rdparty/bcel/bcel-5.2.jar NQPJVM" t/nqp/*.t
$(PROVE) --exec="java -cp .:bin:3rdparty/asm/asm-debug-all-4.1.jar:3rdparty/bcel/bcel-5.2.jar NQPJVM" t/nqp/*.t

clean:
$(PERL) -MExtUtils::Command -e rm_rf bin *.pir *.pbc *.class *.dump
Expand Down
6 changes: 3 additions & 3 deletions src/org/perl6/nqp/sixmodel/REPR.java
Expand Up @@ -110,13 +110,13 @@ public void deserialize_repr_data(ThreadContext tc, STable st, SerializationRead
public void inlineStorage(ThreadContext tc, STable st, ClassWriter cw, String prefix) {
throw new RuntimeException("This representation cannot inline itself into another");
}
public void inlineBind(ThreadContext tc, STable st, MethodVisitor mv, String prefix) {
public void inlineBind(ThreadContext tc, STable st, MethodVisitor mv, String className, String prefix) {
throw new RuntimeException("This representation cannot inline itself into another");
}
public void inlineGet(ThreadContext tc, STable st, MethodVisitor mv, String prefix) {
public void inlineGet(ThreadContext tc, STable st, MethodVisitor mv, String className, String prefix) {
throw new RuntimeException("This representation cannot inline itself into another");
}
public void generateBoxingMethods(ThreadContext tc, STable st, ClassWriter cw, String prefix) {
public void generateBoxingMethods(ThreadContext tc, STable st, ClassWriter cw, String className, String prefix) {
throw new RuntimeException("This representation does not support being a box target");
}
public void deserialize_inlined(ThreadContext tc, STable st, SerializationReader reader,
Expand Down
79 changes: 63 additions & 16 deletions src/org/perl6/nqp/sixmodel/reprs/P6Opaque.java
Expand Up @@ -116,7 +116,7 @@ private void addDelegation(MethodVisitor mv, String methodName,
// Type smoType = Type.getType("Lorg/perl6/nqp/sixmodel/SixModelObject;");

mv.visitVarInsn(Opcodes.ALOAD, 0); // this
mv.visitFieldInsn(Opcodes.GETFIELD, "org/perl6/nqp/sixmodel/repr/P6OopaqueBaseInstance", "delegate",
mv.visitFieldInsn(Opcodes.GETFIELD, "org/perl6/nqp/sixmodel/reprs/P6OpaqueBaseInstance", "delegate",
"Lorg/perl6/nqp/sixmodel/SixModelObject;");
mv.visitInsn(Opcodes.DUP);

Expand All @@ -134,8 +134,8 @@ private void addDelegation(MethodVisitor mv, String methodName,
Type.getMethodDescriptor(retType, argTypes));

mv.visitInsn(retType == Type.VOID_TYPE ? Opcodes.RETURN : Opcodes.ARETURN);
mv.visitInsn(Opcodes.POP);
mv.visitLabel(label);
mv.visitInsn(Opcodes.POP);

// il.append(InstructionConstants.THIS);
// il.append(f.createFieldAccess(P6OpaqueBaseInstance.class.getName(), "delegate", smoType, Constants.GETFIELD));
Expand Down Expand Up @@ -168,6 +168,25 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
cw.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, className, null,
"org/perl6/nqp/sixmodel/reprs/P6OpaqueBaseInstance", null);

/* fields */
for (int i = 0; i < attrInfoList.size(); i++) {
AttrInfo attr = attrInfoList.get(i);

/* Is it a reference type or not? */
StorageSpec ss = attr.st.REPR.get_storage_spec(tc, attr.st);
if (ss.inlineable == StorageSpec.REFERENCE) {
/* Add field. */
String field = "field_" + i;
String desc = "Lorg/perl6/nqp/sixmodel/SixModelObject;";
cw.visitField(Opcodes.ACC_PUBLIC, field, desc, null, null);
}
else {
/* Generate field prefix and have target REPR install the field. */
String prefix = "field_" + i;
attr.st.REPR.inlineStorage(tc, attr.st, cw, prefix);
}
}

Type tcType = Type.getType("Lorg/perl6/nqp/runtime/ThreadContext;");
Type smoType = Type.getType("Lorg/perl6/nqp/sixmodel/SixModelObject;");

Expand All @@ -180,6 +199,7 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
String descriptor = Type.getMethodDescriptor(Type.VOID_TYPE,
new Type[] { tcType, smoType, Type.getType(String.class), Type.LONG_TYPE, smoType });
bindBoxedVisitor = cw.visitMethod(Opcodes.ACC_PUBLIC, "bind_attribute_boxed", descriptor, null, null);
bindBoxedVisitor.visitCode();
addDelegation(bindBoxedVisitor, "bind_attribute_boxed", Type.VOID_TYPE,
new Type[] { tcType, smoType, Type.getType(String.class), Type.LONG_TYPE, smoType }, true);

Expand Down Expand Up @@ -223,6 +243,7 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
String descriptor = Type.getMethodDescriptor(Type.VOID_TYPE,
new Type[] { tcType, smoType, Type.getType(String.class), Type.LONG_TYPE });
bindNativeVisitor = cw.visitMethod(Opcodes.ACC_PUBLIC, "bind_attribute_native", descriptor, null, null);
bindNativeVisitor.visitCode();
addDelegation(bindNativeVisitor, "bind_attribute_native", Type.VOID_TYPE,
new Type[] { tcType, smoType, Type.getType(String.class), Type.LONG_TYPE }, false);

Expand All @@ -236,7 +257,6 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
}
bindNativeSwitch = new Label();
bindNativeVisitor.visitLabel(bindNativeSwitch);
bindNativeDefault = new Label();
bindNativeVisitor.visitTableSwitchInsn(0, attrInfoList.size() - 1, bindNativeDefault, bindNativeLabels);
}
}
Expand Down Expand Up @@ -267,6 +287,7 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
String descriptor = Type.getMethodDescriptor(smoType,
new Type[] { tcType, smoType, Type.getType(String.class), Type.LONG_TYPE });
getBoxedVisitor = cw.visitMethod(Opcodes.ACC_PUBLIC, "get_attribute_boxed", descriptor, null, null);
getBoxedVisitor.visitCode();
addDelegation(getBoxedVisitor, "get_attribute_boxed", smoType,
new Type[] { tcType, smoType, Type.getType(String.class), Type.LONG_TYPE }, false);

Expand Down Expand Up @@ -311,6 +332,7 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
String descriptor = Type.getMethodDescriptor(Type.VOID_TYPE,
new Type[] { tcType, smoType, Type.getType(String.class), Type.LONG_TYPE });
getNativeVisitor = cw.visitMethod(Opcodes.ACC_PUBLIC, "get_attribute_native", descriptor, null, null);
getNativeVisitor.visitCode();
addDelegation(getNativeVisitor, "get_attribute_native", Type.VOID_TYPE,
new Type[] { tcType, smoType, Type.getType(String.class), Type.LONG_TYPE }, false);

Expand Down Expand Up @@ -361,7 +383,7 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf

String field = "field_" + i;
String desc = "Lorg/perl6/nqp/sixmodel/SixModelObject;";
cw.visitField(Opcodes.ACC_PUBLIC, field, desc, null, null);
// cw.visitField(Opcodes.ACC_PUBLIC, field, desc, null, null);

/* Add bind code. */
// bindBoxedMatch[i] = i;
Expand All @@ -373,7 +395,7 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf

bindBoxedVisitor.visitLabel(bindBoxedLabels[i]);
bindBoxedVisitor.visitVarInsn(Opcodes.ALOAD, 0);
//TOOD createLoad
bindBoxedVisitor.visitVarInsn(Opcodes.ALOAD, 6);
bindBoxedVisitor.visitFieldInsn(Opcodes.PUTFIELD, className, field, desc);
bindBoxedVisitor.visitInsn(Opcodes.RETURN);

Expand Down Expand Up @@ -403,6 +425,7 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
getBoxedVisitor.visitJumpInsn(Opcodes.IFNONNULL, end);
getBoxedVisitor.visitInsn(Opcodes.POP);
getBoxedVisitor.visitVarInsn(Opcodes.ALOAD, 0);
getBoxedVisitor.visitIntInsn(Opcodes.BIPUSH, i);
String methodDesc = "(I)Lorg/perl6/nqp/sixmodel/SixModelObject;";
getBoxedVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, "autoViv", methodDesc);
getBoxedVisitor.visitLabel(end);
Expand All @@ -426,17 +449,21 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
bindNativeVisitor.visitLabel(bindNativeLabels[i]);
bindNativeVisitor.visitVarInsn(Opcodes.ALOAD, 0);
bindNativeVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, "badNative", "()V");

getNativeVisitor.visitLabel(getNativeLabels[i]);
getNativeVisitor.visitVarInsn(Opcodes.ALOAD, 0);
getNativeVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, "badNative", "()V");
}
else {
/* Generate field prefix and have target REPR install the field. */
String prefix = "field_" + i;
attr.st.REPR.inlineStorage(tc, attr.st, cw, prefix);
// attr.st.REPR.inlineStorage(tc, attr.st, cw, prefix);

/* Install bind/get instructions. */
bindNativeVisitor.visitLabel(bindNativeLabels[i]);
attr.st.REPR.inlineBind(tc, attr.st, bindNativeVisitor, prefix);
attr.st.REPR.inlineBind(tc, attr.st, bindNativeVisitor, className, prefix);
getNativeVisitor.visitLabel(getNativeLabels[i]);
attr.st.REPR.inlineGet(tc, attr.st, getNativeVisitor, prefix);
attr.st.REPR.inlineGet(tc, attr.st, getNativeVisitor, className, prefix);

// Instruction[] bindInstructions = attr.st.REPR.inlineBind(tc, attr.st, c, prefix);
// bindNativeMatch[i] = i;
Expand Down Expand Up @@ -477,7 +504,7 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
if (attr.boxTarget) {
if (ss.inlineable == StorageSpec.REFERENCE)
throw new RuntimeException("A box_target must not have a reference type attribute");
attr.st.REPR.generateBoxingMethods(tc, attr.st, cw, "field_" + i);
attr.st.REPR.generateBoxingMethods(tc, attr.st, cw, className, "field_" + i);
}

/* If it's a positional or associative delegate, give it the methods
Expand Down Expand Up @@ -518,6 +545,8 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
bindBoxedVisitor.visitJumpInsn(Opcodes.GOTO, bindBoxedSwitch);
else
bindBoxedVisitor.visitInsn(Opcodes.RETURN);
bindBoxedVisitor.visitMaxs(0, 0);
bindBoxedVisitor.visitEnd();

/* Finish bind_native_attribute. */
// bindNativeIl.append(InstructionConstants.ALOAD_0);
Expand Down Expand Up @@ -548,6 +577,8 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
bindNativeVisitor.visitJumpInsn(Opcodes.GOTO, bindNativeSwitch);
else
bindNativeVisitor.visitInsn(Opcodes.RETURN);
bindNativeVisitor.visitMaxs(0, 0);
bindNativeVisitor.visitEnd();

/* Finish get_boxed_attribute. */
// getBoxedIl.append(InstructionConstants.ALOAD_0);
Expand Down Expand Up @@ -580,7 +611,9 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
getBoxedVisitor.visitJumpInsn(Opcodes.GOTO, getBoxedSwitch);
else
getBoxedVisitor.visitInsn(Opcodes.ACONST_NULL);
getBoxedVisitor.visitInsn(Opcodes.RETURN);
getBoxedVisitor.visitInsn(Opcodes.ARETURN);
getBoxedVisitor.visitMaxs(0, 0);
getBoxedVisitor.visitEnd();

/* Finish get_native_attribute. */
// getNativeIl.append(InstructionConstants.ALOAD_0);
Expand Down Expand Up @@ -613,17 +646,31 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
else
getNativeVisitor.visitInsn(Opcodes.RETURN);

getNativeVisitor.visitMaxs(6, 6);
getNativeVisitor.visitEnd();

/* Finally, add empty constructor and generate the JVM storage class. */
// c.addEmptyConstructor(Constants.ACC_PUBLIC);

MethodVisitor constructor = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
constructor.visitCode();
constructor.visitVarInsn(Opcodes.ALOAD, 0);
constructor.visitMethodInsn(Opcodes.INVOKESPECIAL,
"org/perl6/nqp/sixmodel/reprs/P6OpaqueBaseInstance", "<init>", "()V");
constructor.visitInsn(Opcodes.RETURN);
constructor.visitMaxs(1, 1);
constructor.visitEnd();

// Uncomment the following line to help debug the code-gen.
//try { c.getJavaClass().dump(className + ".class"); } catch (Exception e) { }
// byte[] classCompiled = c.getJavaClass().getBytes();
// ((P6OpaqueREPRData)st.REPRData).jvmClass = new ByteClassLoader(classCompiled).findClass(className);

cw.visitEnd();

byte[] classCompiled = cw.toByteArray();
File f = new File(className + ".class");
try {
FileOutputStream fos = new FileOutputStream(f);
FileOutputStream fos = new FileOutputStream(new File(className + ".class"));
fos.write(classCompiled);
fos.close();
} catch (IOException e) {
Expand All @@ -634,14 +681,14 @@ private void generateJVMType(ThreadContext tc, STable st, List<AttrInfo> attrInf
}

private void generateDelegateMethod(ThreadContext tc, ClassWriter cw, String className, String field, String methodName) {
Type smoType = Type.getType("Lorg/perl6/nqp/sixmodel/SixModelObject;");

String desc = Type.getMethodDescriptor(smoType);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, methodName, desc, null, null);
String desc = "Lorg/perl6/nqp/sixmodel/SixModelObject;";

MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, methodName, "()"+desc, null, null);

mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, className, field, desc);
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(0, 0);
// methIl.append(InstructionConstants.ALOAD_0);
// methIl.append(f.createFieldAccess(c.getClassName(), field, smoType, Constants.GETFIELD));
// methIl.append(InstructionConstants.ARETURN);
Expand Down
21 changes: 13 additions & 8 deletions src/org/perl6/nqp/sixmodel/reprs/P6int.java
Expand Up @@ -39,13 +39,14 @@ public void inlineStorage(ThreadContext tc, STable st, ClassWriter cw, String pr
cw.visitField(Opcodes.ACC_PUBLIC, prefix, "J", null, null);
}

public void inlineBind(ThreadContext tc, STable st, MethodVisitor mv, String prefix) {
public void inlineBind(ThreadContext tc, STable st, MethodVisitor mv, String className, String prefix) {
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitInsn(Opcodes.ICONST_0 + ThreadContext.NATIVE_INT);
mv.visitFieldInsn(Opcodes.PUTFIELD, "org/perl6/nqp/runtime/ThreadContext", "native_type", "I");
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitFieldInsn(Opcodes.GETFIELD, "org/perl6/nqp/runtime/ThreadContext", "native_i", "L");
mv.visitFieldInsn(Opcodes.PUTFIELD, "org/perl6/nqp/sixmodel/reprs/P6int", prefix, "J");
mv.visitFieldInsn(Opcodes.GETFIELD, "org/perl6/nqp/runtime/ThreadContext", "native_i", "J");
mv.visitFieldInsn(Opcodes.PUTFIELD, className, prefix, "J");
mv.visitInsn(Opcodes.RETURN);

// InstructionFactory f = new InstructionFactory(cp);
Expand All @@ -61,13 +62,15 @@ public void inlineBind(ThreadContext tc, STable st, MethodVisitor mv, String pre
// return ins;
}

public void inlineGet(ThreadContext tc, STable st, MethodVisitor mv, String prefix) {
public void inlineGet(ThreadContext tc, STable st, MethodVisitor mv, String className, String prefix) {
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitInsn(Opcodes.DUP);
mv.visitInsn(Opcodes.ICONST_0 + ThreadContext.NATIVE_INT);
mv.visitFieldInsn(Opcodes.PUTFIELD, "org/perl6/nqp/runtime/ThreadContext", "native_type", "I");
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, "org/perl6/nqp/sixmodel/reprs/P6int", prefix, "J");
mv.visitFieldInsn(Opcodes.GETFIELD, className, prefix, "J");
mv.visitFieldInsn(Opcodes.PUTFIELD, "org/perl6/nqp/runtime/ThreadContext", "native_i", "J");
mv.visitInsn(Opcodes.RETURN);

// InstructionFactory f = new InstructionFactory(cp);
// Instruction[] ins = new Instruction[8];
Expand All @@ -82,7 +85,7 @@ public void inlineGet(ThreadContext tc, STable st, MethodVisitor mv, String pref
// return ins;
}

public void generateBoxingMethods(ThreadContext tc, STable st, ClassWriter cw, String prefix) {
public void generateBoxingMethods(ThreadContext tc, STable st, ClassWriter cw, String className, String prefix) {
// InstructionFactory f = new InstructionFactory(cp);
//
// InstructionList getIl = new InstructionList();
Expand All @@ -100,8 +103,9 @@ public void generateBoxingMethods(ThreadContext tc, STable st, ClassWriter cw, S
String getDesc = "(Lorg/perl6/nqp/runtime/ThreadContext;)J";
MethodVisitor getMeth = cw.visitMethod(Opcodes.ACC_PUBLIC, "get_int", getDesc, null, null);
getMeth.visitVarInsn(Opcodes.ALOAD, 0);
getMeth.visitFieldInsn(Opcodes.GETFIELD, "org/perl6/nqp/sixmodel/reprs/P6int", prefix, "J");
getMeth.visitFieldInsn(Opcodes.GETFIELD, className, prefix, "J");
getMeth.visitInsn(Opcodes.LRETURN);
getMeth.visitMaxs(0, 0);

// InstructionList setIl = new InstructionList();
// MethodGen setMeth = new MethodGen(Constants.ACC_PUBLIC, Type.VOID,
Expand All @@ -120,8 +124,9 @@ public void generateBoxingMethods(ThreadContext tc, STable st, ClassWriter cw, S
MethodVisitor setMeth = cw.visitMethod(Opcodes.ACC_PUBLIC, "set_int", setDesc, null, null);
setMeth.visitVarInsn(Opcodes.ALOAD, 0);
setMeth.visitVarInsn(Opcodes.LLOAD, 2);
setMeth.visitFieldInsn(Opcodes.PUTFIELD, "org/perl6/nqp/sixmodel/reprs/P6int", prefix, "J");
setMeth.visitFieldInsn(Opcodes.PUTFIELD, className, prefix, "J");
setMeth.visitInsn(Opcodes.RETURN);
setMeth.visitMaxs(0, 0);
}

public SixModelObject deserialize_stub(ThreadContext tc, STable st) {
Expand Down

0 comments on commit 9f4368e

Please sign in to comment.