Search in sources :

Example 56 with Label

use of org.mvel2.asm.Label in project mvel by mvel.

the class GeneratorAdapter method mark.

/**
 * Marks the current code position with a new label.
 *
 * @return the label that was created to mark the current code position.
 */
public Label mark() {
    Label label = new Label();
    mv.visitLabel(label);
    return label;
}
Also used : Label(org.mvel2.asm.Label)

Example 57 with Label

use of org.mvel2.asm.Label in project mvel by mvel.

the class JSRInlinerAdapter method visitJumpInsn.

/**
 * Detects a JSR instruction and sets a flag to indicate we will need to do
 * inlining.
 */
@Override
public void visitJumpInsn(final int opcode, final Label lbl) {
    super.visitJumpInsn(opcode, lbl);
    LabelNode ln = ((JumpInsnNode) instructions.getLast()).label;
    if (opcode == JSR && !subroutineHeads.containsKey(ln)) {
        subroutineHeads.put(ln, new BitSet());
    }
}
Also used : LabelNode(org.mvel2.asm.tree.LabelNode) BitSet(java.util.BitSet) JumpInsnNode(org.mvel2.asm.tree.JumpInsnNode)

Example 58 with Label

use of org.mvel2.asm.Label in project mvel by mvel.

the class JSRInlinerAdapter method emitSubroutine.

/**
 * Emits one instantiation of one subroutine, specified by
 * <code>instant</code>. May add new instantiations that are invoked by this
 * one to the <code>worklist</code> parameter, and new try/catch blocks to
 * <code>newTryCatchBlocks</code>.
 *
 * @param instant
 *            the instantiation that must be performed.
 * @param worklist
 *            list of the instantiations that remain to be done.
 * @param newInstructions
 *            the instruction list to which the instantiated code must be
 *            appended.
 * @param newTryCatchBlocks
 *            the exception handler list to which the instantiated handlers
 *            must be appended.
 */
private void emitSubroutine(final Instantiation instant, final List<Instantiation> worklist, final InsnList newInstructions, final List<TryCatchBlockNode> newTryCatchBlocks, final List<LocalVariableNode> newLocalVariables) {
    LabelNode duplbl = null;
    if (LOGGING) {
        log("--------------------------------------------------------");
        log("Emitting instantiation of subroutine " + instant.subroutine);
    }
    // labels and jump targets as we go:
    for (int i = 0, c = instructions.size(); i < c; i++) {
        AbstractInsnNode insn = instructions.get(i);
        Instantiation owner = instant.findOwner(i);
        // Always remap labels:
        if (insn.getType() == AbstractInsnNode.LABEL) {
            // Translate labels into their renamed equivalents.
            // Avoid adding the same label more than once. Note
            // that because we own this instruction the gotoTable
            // and the rangeTable will always agree.
            LabelNode ilbl = (LabelNode) insn;
            LabelNode remap = instant.rangeLabel(ilbl);
            if (LOGGING) {
                // TODO use of default toString().
                log("Translating lbl #" + i + ':' + ilbl + " to " + remap);
            }
            if (remap != duplbl) {
                newInstructions.add(remap);
                duplbl = remap;
            }
            continue;
        }
        // that do not invoke each other.
        if (owner != instant) {
            continue;
        }
        if (LOGGING) {
            log("Emitting inst #" + i);
        }
        if (insn.getOpcode() == RET) {
            // Translate RET instruction(s) to a jump to the return label
            // for the appropriate instantiation. The problem is that the
            // subroutine may "fall through" to the ret of a parent
            // subroutine; therefore, to find the appropriate ret label we
            // find the lowest subroutine on the stack that claims to own
            // this instruction. See the class javadoc comment for an
            // explanation on why this technique is safe (note: it is only
            // safe if the input is verifiable).
            LabelNode retlabel = null;
            for (Instantiation p = instant; p != null; p = p.previous) {
                if (p.subroutine.get(i)) {
                    retlabel = p.returnLabel;
                }
            }
            if (retlabel == null) {
                // code.
                throw new RuntimeException("Instruction #" + i + " is a RET not owned by any subroutine");
            }
            newInstructions.add(new JumpInsnNode(GOTO, retlabel));
        } else if (insn.getOpcode() == JSR) {
            LabelNode lbl = ((JumpInsnNode) insn).label;
            BitSet sub = subroutineHeads.get(lbl);
            Instantiation newinst = new Instantiation(instant, sub);
            LabelNode startlbl = newinst.gotoLabel(lbl);
            if (LOGGING) {
                log(" Creating instantiation of subr " + sub);
            }
            // Rather than JSRing, we will jump to the inline version and
            // push NULL for what was once the return value. This hack
            // allows us to avoid doing any sort of data flow analysis to
            // figure out which instructions manipulate the old return value
            // pointer which is now known to be unneeded.
            newInstructions.add(new InsnNode(ACONST_NULL));
            newInstructions.add(new JumpInsnNode(GOTO, startlbl));
            newInstructions.add(newinst.returnLabel);
            // Insert this new instantiation into the queue to be emitted
            // later.
            worklist.add(newinst);
        } else {
            newInstructions.add(insn.clone(instant));
        }
    }
    // Emit try/catch blocks that are relevant to this method.
    for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext(); ) {
        TryCatchBlockNode trycatch = it.next();
        if (LOGGING) {
            // TODO use of default toString().
            log("try catch block original labels=" + trycatch.start + '-' + trycatch.end + "->" + trycatch.handler);
        }
        final LabelNode start = instant.rangeLabel(trycatch.start);
        final LabelNode end = instant.rangeLabel(trycatch.end);
        // Ignore empty try/catch regions
        if (start == end) {
            if (LOGGING) {
                log(" try catch block empty in this subroutine");
            }
            continue;
        }
        final LabelNode handler = instant.gotoLabel(trycatch.handler);
        if (LOGGING) {
            // TODO use of default toString().
            log(" try catch block new labels=" + start + '-' + end + "->" + handler);
        }
        if (start == null || end == null || handler == null) {
            throw new RuntimeException("Internal error!");
        }
        newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler, trycatch.type));
    }
    for (Iterator<LocalVariableNode> it = localVariables.iterator(); it.hasNext(); ) {
        LocalVariableNode lvnode = it.next();
        if (LOGGING) {
            log("local var " + lvnode.name);
        }
        final LabelNode start = instant.rangeLabel(lvnode.start);
        final LabelNode end = instant.rangeLabel(lvnode.end);
        if (start == end) {
            if (LOGGING) {
                log("  local variable empty in this sub");
            }
            continue;
        }
        newLocalVariables.add(new LocalVariableNode(lvnode.name, lvnode.desc, lvnode.signature, start, end, lvnode.index));
    }
}
Also used : LabelNode(org.mvel2.asm.tree.LabelNode) InsnNode(org.mvel2.asm.tree.InsnNode) TableSwitchInsnNode(org.mvel2.asm.tree.TableSwitchInsnNode) AbstractInsnNode(org.mvel2.asm.tree.AbstractInsnNode) JumpInsnNode(org.mvel2.asm.tree.JumpInsnNode) LookupSwitchInsnNode(org.mvel2.asm.tree.LookupSwitchInsnNode) TryCatchBlockNode(org.mvel2.asm.tree.TryCatchBlockNode) BitSet(java.util.BitSet) JumpInsnNode(org.mvel2.asm.tree.JumpInsnNode) AbstractInsnNode(org.mvel2.asm.tree.AbstractInsnNode) LocalVariableNode(org.mvel2.asm.tree.LocalVariableNode)

Example 59 with Label

use of org.mvel2.asm.Label in project mvel by mvel.

the class LocalVariablesSorter method visitLocalVariableAnnotation.

@Override
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) {
    Type t = Type.getType(desc);
    int[] newIndex = new int[index.length];
    for (int i = 0; i < newIndex.length; ++i) {
        newIndex[i] = remap(index[i], t);
    }
    return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end, newIndex, desc, visible);
}
Also used : Type(org.mvel2.asm.Type)

Example 60 with Label

use of org.mvel2.asm.Label in project drools by kiegroup.

the class ASMConsequenceStubBuilder method createStubConsequence.

private void createStubConsequence(final ClassGenerator generator, final InvokerDataProvider data, final Map<String, Object> vars) {
    generator.setInterfaces(ConsequenceStub.class, CompiledInvoker.class).addField(ACC_PRIVATE + ACC_VOLATILE, "consequence", Consequence.class);
    generator.addMethod(ACC_PUBLIC, "getName", generator.methodDescr(String.class), new ClassGenerator.MethodBody() {

        public void body(MethodVisitor mv) {
            push((String) vars.get("consequenceName"));
            // return the first object on the stack
            mv.visitInsn(ARETURN);
        }
    }).addMethod(ACC_PUBLIC, "getNotPatterns", generator.methodDescr(Boolean[].class), new ClassGenerator.MethodBody() {

        public void body(MethodVisitor mv) {
            returnAsArray((Boolean[]) vars.get("notPatterns"));
        }
    }).addMethod(ACC_PUBLIC, "evaluate", generator.methodDescr(null, KnowledgeHelper.class, WorkingMemory.class), new String[] { "java/lang/Exception" }, new ClassGenerator.MethodBody() {

        public void body(MethodVisitor mv) {
            Label syncStart = new Label();
            Label syncEnd = new Label();
            Label l1 = new Label();
            Label l2 = new Label();
            mv.visitTryCatchBlock(syncStart, l1, l2, null);
            Label l3 = new Label();
            mv.visitTryCatchBlock(l2, l3, l2, null);
            getFieldFromThis("consequence", Consequence.class);
            mv.visitJumpInsn(IFNONNULL, syncEnd);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitInsn(DUP);
            mv.visitVarInsn(ASTORE, 3);
            // synchronized(this) {
            mv.visitInsn(MONITORENTER);
            mv.visitLabel(syncStart);
            getFieldFromThis("consequence", Consequence.class);
            // if (consequence == null) ...
            Label ifNotInitialized = new Label();
            mv.visitJumpInsn(IFNONNULL, ifNotInitialized);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 2);
            // ... ConsequenceGenerator.generate(this, knowledgeHelper, workingMemory)
            invokeStatic(ConsequenceGenerator.class, "generate", null, ConsequenceStub.class, KnowledgeHelper.class, WorkingMemory.class);
            mv.visitLabel(ifNotInitialized);
            mv.visitVarInsn(ALOAD, 3);
            mv.visitInsn(MONITOREXIT);
            mv.visitLabel(l1);
            mv.visitJumpInsn(GOTO, syncEnd);
            mv.visitLabel(l2);
            mv.visitVarInsn(ASTORE, 4);
            mv.visitVarInsn(ALOAD, 3);
            mv.visitInsn(MONITOREXIT);
            mv.visitLabel(l3);
            mv.visitVarInsn(ALOAD, 4);
            mv.visitInsn(ATHROW);
            mv.visitLabel(syncEnd);
            // } end of synchronized
            getFieldFromThis("consequence", Consequence.class);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 2);
            invokeInterface(Consequence.class, "evaluate", null, KnowledgeHelper.class, WorkingMemory.class);
            mv.visitInsn(RETURN);
        }
    }).addMethod(ACC_PUBLIC, "setConsequence", generator.methodDescr(null, Consequence.class), new ClassGenerator.MethodBody() {

        public void body(MethodVisitor mv) {
            putFieldInThisFromRegistry("consequence", Consequence.class, 1);
            mv.visitInsn(RETURN);
        }
    });
}
Also used : ClassGenerator(org.drools.core.rule.builder.dialect.asm.ClassGenerator) Label(org.mvel2.asm.Label) ConsequenceStub(org.drools.core.rule.builder.dialect.asm.ConsequenceStub) Consequence(org.drools.core.spi.Consequence) CompiledInvoker(org.drools.core.spi.CompiledInvoker) MethodVisitor(org.mvel2.asm.MethodVisitor)

Aggregations

Label (org.mvel2.asm.Label)97 MethodVisitor (org.mvel2.asm.MethodVisitor)49 FieldDefinition (org.drools.core.factmodel.FieldDefinition)24 Map (java.util.Map)18 Type (org.mvel2.asm.Type)12 IOException (java.io.IOException)10 BitSet (java.util.BitSet)8 FieldVisitor (org.mvel2.asm.FieldVisitor)8 Method (java.lang.reflect.Method)7 CompiledInvoker (org.drools.core.spi.CompiledInvoker)7 TraitableBean (org.drools.core.factmodel.traits.TraitableBean)5 ObjectInput (java.io.ObjectInput)4 ObjectOutput (java.io.ObjectOutput)4 Collection (java.util.Collection)4 Thing (org.drools.core.factmodel.traits.Thing)4 Declaration (org.drools.core.rule.Declaration)4 ClassGenerator (org.drools.core.rule.builder.dialect.asm.ClassGenerator)4 ClassWriter (org.mvel2.asm.ClassWriter)4 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3