Skip to content

Commit

Permalink
Teach P6opaque about inlining native attrs.
Browse files Browse the repository at this point in the history
  • Loading branch information
jnthn committed Jan 7, 2013
1 parent 7d90a20 commit b16cdd9
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 8 deletions.
19 changes: 18 additions & 1 deletion src/org/perl6/nqp/sixmodel/REPR.java
@@ -1,5 +1,8 @@
package org.perl6.nqp.sixmodel;

import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.Instruction;
import org.perl6.nqp.runtime.ThreadContext;

/**
Expand Down Expand Up @@ -40,7 +43,7 @@ public void compose(ThreadContext tc, STable st, SixModelObject repr_info) {
* Gets attribute access hint for the representation.
*/
public long hint_for(ThreadContext tc, STable st, SixModelObject class_handle, String name) {
return STable.NO_HINT;
return STable.NO_HINT;
}

/**
Expand Down Expand Up @@ -96,4 +99,18 @@ public void deserialize_repr_data(ThreadContext tc, STable st, SerializationRead
{
// It's fine for this to be unimplemented.
}

/**
* Flattening related functions.
*/
public void inlineStorage(ThreadContext tc, STable st, ClassGen c, ConstantPoolGen cp, String prefix) {
throw new RuntimeException("This representation cannot inline itself into another");
}
public Instruction[] inlineBind(ThreadContext tc, STable st, ClassGen c, ConstantPoolGen cp, String prefix) {
throw new RuntimeException("This representation cannot inline itself into another");
}
public Instruction[] inlineGet(ThreadContext tc, STable st, ClassGen c, ConstantPoolGen cp, String prefix) {
throw new RuntimeException("This representation cannot inline itself into another");
}
}

114 changes: 113 additions & 1 deletion src/org/perl6/nqp/sixmodel/reprs/P6Opaque.java
Expand Up @@ -92,6 +92,23 @@ public void compose(ThreadContext tc, STable st, SixModelObject repr_info) {
int[] bindBoxedMatch = new int[attrHashes.size()];
InstructionHandle[] bindBoxedTargets = new InstructionHandle[attrHashes.size()];

/* bind_attribute_native */
InstructionList bindNativeIl = new InstructionList();
MethodGen bindNativeMeth = new MethodGen(Constants.ACC_PUBLIC, Type.VOID,
new Type[] {
Type.getType("Lorg/perl6/nqp/runtime/ThreadContext;"),
Type.getType("Lorg/perl6/nqp/sixmodel/SixModelObject;"),
Type.STRING, Type.LONG
},
new String[] { "tc" , "class_handle", "name", "hint" },
"bind_attribute_native", className, bindNativeIl, cp);
bindNativeIl.append(InstructionFactory.createLoad(Type.LONG, 4));
bindNativeIl.append(InstructionConstants.L2I);
if (attrHashes.size() > 0)
bindNativeIl.append(InstructionFactory.createBranchInstruction((short)0xa7, null)); // dummy
int[] bindNativeMatch = new int[attrHashes.size()];
InstructionHandle[] bindNativeTargets = new InstructionHandle[attrHashes.size()];

/* get_attribute_boxed */
InstructionList getBoxedIl = new InstructionList();
MethodGen getBoxedMeth = new MethodGen(Constants.ACC_PUBLIC,
Expand All @@ -110,6 +127,24 @@ public void compose(ThreadContext tc, STable st, SixModelObject repr_info) {
int[] getBoxedMatch = new int[attrHashes.size()];
InstructionHandle[] getBoxedTargets = new InstructionHandle[attrHashes.size()];

/* get_attribute_native */
InstructionList getNativeIl = new InstructionList();
MethodGen getNativeMeth = new MethodGen(Constants.ACC_PUBLIC,
Type.VOID,
new Type[] {
Type.getType("Lorg/perl6/nqp/runtime/ThreadContext;"),
Type.getType("Lorg/perl6/nqp/sixmodel/SixModelObject;"),
Type.STRING, Type.LONG
},
new String[] { "tc" , "class_handle", "name", "hint" },
"get_attribute_native", className, getNativeIl, cp);
getNativeIl.append(InstructionFactory.createLoad(Type.LONG, 4));
getNativeIl.append(InstructionConstants.L2I);
if (attrHashes.size() > 0)
getNativeIl.append(InstructionFactory.createBranchInstruction((short)0xa7, null)); // dummy
int[] getNativeMatch = new int[attrHashes.size()];
InstructionHandle[] getNativeTargets = new InstructionHandle[attrHashes.size()];

/* Now add all of the required fields and fill out the methods. */
for (int i = 0; i < attrHashes.size(); i++) {
SixModelObject attr = attrHashes.get(i);
Expand Down Expand Up @@ -139,9 +174,45 @@ public void compose(ThreadContext tc, STable st, SixModelObject repr_info) {
getBoxedTargets[i] = getBoxedIl.getEnd();
getBoxedIl.append(f.createFieldAccess(className, fg.getName(), fg.getType(), Constants.GETFIELD));
getBoxedIl.append(InstructionConstants.ARETURN);

/* Native variants should just throw. */
bindNativeMatch[i] = i;
bindNativeIl.append(InstructionConstants.ALOAD_0);
bindNativeTargets[i] = bindNativeIl.getEnd();
bindNativeIl.append(f.createInvoke(className, "badNative", Type.VOID, new Type[] { }, Constants.INVOKEVIRTUAL));
getNativeMatch[i] = i;
getNativeIl.append(InstructionConstants.ALOAD_0);
getNativeTargets[i] = getNativeIl.getEnd();
getNativeIl.append(f.createInvoke(className, "badNative", Type.VOID, new Type[] { }, Constants.INVOKEVIRTUAL));
}
else {
throw new RuntimeException("P6opaque native attributes NYI");
/* Generate field prefix and have target REPR install the field. */
String prefix = "field_" + i;
type.st.REPR.inlineStorage(tc, type.st, c, cp, prefix);

/* Install bind/get instructions. */
Instruction[] bindInstructions = type.st.REPR.inlineBind(tc, type.st, c, cp, prefix);
bindNativeMatch[i] = i;
bindNativeIl.append(bindInstructions[0]);
bindNativeTargets[i] = bindNativeIl.getEnd();
for (int j = 1; j < bindInstructions.length; j++)
bindNativeIl.append(bindInstructions[j]);
Instruction[] getInstructions = type.st.REPR.inlineGet(tc, type.st, c, cp, prefix);
getNativeMatch[i] = i;
getNativeIl.append(getInstructions[0]);
getNativeTargets[i] = getNativeIl.getEnd();
for (int j = 1; j < getInstructions.length; j++)
getNativeIl.append(getInstructions[j]);

/* Reference variants should just throw. */
bindBoxedMatch[i] = i;
bindBoxedIl.append(InstructionConstants.ALOAD_0);
bindBoxedTargets[i] = bindBoxedIl.getEnd();
bindBoxedIl.append(f.createInvoke(className, "badReference", Type.VOID, new Type[] { }, Constants.INVOKEVIRTUAL));
getBoxedMatch[i] = i;
getBoxedIl.append(InstructionConstants.ALOAD_0);
getBoxedTargets[i] = getBoxedIl.getEnd();
getBoxedIl.append(f.createInvoke(className, "badReference", Type.VOID, new Type[] { }, Constants.INVOKEVIRTUAL));
}

/* If this is a box/unbox target, make sure it gets the appropriate
Expand Down Expand Up @@ -172,6 +243,26 @@ public void compose(ThreadContext tc, STable st, SixModelObject repr_info) {
c.addMethod(bindBoxedMeth.getMethod());
bindBoxedIl.dispose();

/* Finish bind_native_attribute. */
InstructionHandle bindNativeTsPos = bindNativeIl.getStart().getNext().getNext();
bindNativeIl.append(InstructionConstants.ALOAD_0);
if (attrHashes.size() > 0)
bindNativeTsPos.setInstruction(
new TABLESWITCH(bindNativeMatch, bindNativeTargets, bindNativeIl.getEnd()));
bindNativeIl.append(InstructionConstants.ALOAD_2);
bindNativeIl.append(InstructionFactory.createLoad(Type.STRING, 3));
bindNativeIl.append(f.createInvoke(
className, "resolveAttribute", Type.INT,
new Type[] { Type.getType("Lorg/perl6/nqp/sixmodel/SixModelObject;"), Type.STRING },
Constants.INVOKEVIRTUAL));
if (attrHashes.size() > 0)
bindNativeIl.append(InstructionFactory.createBranchInstruction((short)Constants.GOTO, bindNativeTsPos));
else
bindNativeIl.append(InstructionConstants.RETURN);
bindNativeMeth.setMaxStack();
c.addMethod(bindNativeMeth.getMethod());
bindNativeIl.dispose();

/* Finish get_boxed_attribute. */
InstructionHandle getBoxedTsPos = getBoxedIl.getStart().getNext().getNext();
getBoxedIl.append(InstructionConstants.ALOAD_0);
Expand All @@ -194,6 +285,27 @@ public void compose(ThreadContext tc, STable st, SixModelObject repr_info) {
c.addMethod(getBoxedMeth.getMethod());
getBoxedIl.dispose();

/* Finish get_native_attribute. */
InstructionHandle getNativeTsPos = getNativeIl.getStart().getNext().getNext();
getNativeIl.append(InstructionConstants.ALOAD_0);
if (attrHashes.size() > 0)
getNativeTsPos.setInstruction(
new TABLESWITCH(getNativeMatch, getNativeTargets, getNativeIl.getEnd()));
getNativeIl.append(InstructionConstants.ALOAD_2);
getNativeIl.append(InstructionFactory.createLoad(Type.STRING, 3));
getNativeIl.append(f.createInvoke(
className, "resolveAttribute", Type.INT,
new Type[] { Type.getType("Lorg/perl6/nqp/sixmodel/SixModelObject;"), Type.STRING },
Constants.INVOKEVIRTUAL));
if (attrHashes.size() > 0)
getNativeIl.append(InstructionFactory.createBranchInstruction((short)Constants.GOTO, getNativeTsPos));
else {
getNativeIl.append(InstructionConstants.RETURN);
}
getNativeMeth.setMaxStack();
c.addMethod(getNativeMeth.getMethod());
getNativeIl.dispose();

/* Finally, add empty constructor and generate the JVM storage class. */
c.addEmptyConstructor(Constants.ACC_PUBLIC);
// Uncomment the following line to help debug the code-gen.
Expand Down
14 changes: 8 additions & 6 deletions src/org/perl6/nqp/sixmodel/reprs/P6OpaqueBaseInstance.java
@@ -1,6 +1,4 @@
package org.perl6.nqp.sixmodel.reprs;

import org.perl6.nqp.runtime.ThreadContext;
import org.perl6.nqp.sixmodel.SixModelObject;

public class P6OpaqueBaseInstance extends SixModelObject {
Expand All @@ -17,8 +15,12 @@ public final int resolveAttribute(SixModelObject classHandle, String name) {
}
throw new RuntimeException("No such attribute '" + name + "' for this object");
}
public void bind_attribute_boxed(ThreadContext tc,SixModelObject class_handle,
String name, long hint, SixModelObject value) {
throw new RuntimeException("OOPS");
}

public void badNative() {
throw new RuntimeException("Cannot access a reference attribute as a native attribute");
}

public void badReference() {
throw new RuntimeException("Cannot access a native attribute as a reference attribute");
}
}

0 comments on commit b16cdd9

Please sign in to comment.