Package org.jruby.ir.operands

Examples of org.jruby.ir.operands.Label


        // Now for opt args
        if (opt > 0) {
            ListNode optArgs = argsNode.getOptArgs();
            for (int j = 0; j < opt; j++, argIndex++) {
                // Jump to 'l' if this arg is not null.  If null, fall through and build the default value!
                Label l = s.getNewLabel();
                OptArgNode n = (OptArgNode)optArgs.get(j);
                String argName = n.getName();
                Variable av = s.getNewLocalVariable(argName, 0);
                if (s instanceof IRMethod) ((IRMethod)s).addArgDesc("opt", argName);
                // You need at least required+j+1 incoming args for this opt arg to get an arg at all
View Full Code Here


                return buildDefinitionCheck(s, new BackrefIsMatchDataInstr(s.getNewTemporaryVariable()), "global-variable");
            }
            case DREGEXPNODE:
            case DSTRNODE: {
                Operand v = super.buildVersionSpecificGetDefinitionIR(node, s);
                Label doneLabel = s.getNewLabel();
                Variable tmpVar = getValueInTemporaryVariable(s, v);
                s.addInstr(BNEInstr.create(tmpVar, manager.getNil(), doneLabel));
                s.addInstr(new CopyInstr(tmpVar, new StringLiteral("expression")));
                s.addInstr(new LabelInstr(doneLabel));
                return tmpVar;
            }
            case NOTNODE: {
                Operand v = buildGetDefinitionBase(((NotNode)node).getConditionNode(), s);
                Label doneLabel = s.getNewLabel();
                Variable tmpVar = getValueInTemporaryVariable(s, v);
                s.addInstr(BEQInstr.create(tmpVar, manager.getNil(), doneLabel));
                s.addInstr(new CopyInstr(tmpVar, new StringLiteral("method")));
                s.addInstr(new LabelInstr(doneLabel));
                return tmpVar;
            }
            case NTHREFNODE: {
            // SSS FIXME: Is there a reason to do this all with low-level IR?
            // Can't this all be folded into a Java method that would be part
            // of the runtime library, which then can be used by buildDefinitionCheck method above?
            // This runtime library would be used both by the interpreter & the compiled code!

                /* -------------------------------------------------------------------------------------
                 * We have to generate IR for this:
                 *    v = backref; (!(v instanceof RubyMatchData) || v.group(n).nil?) ? nil : "global-variable"
                 *
                 * which happens to be identical to: (where nthRef implicitly fetches backref again!)
                 *    v = backref; (!(v instanceof RubyMatchData) || nthRef(n).nil?) ? nil : "global-variable"
                 *
                 * I am using the second form since it let us encode it in fewer IR instructions.
                 * But, note that this second form is not as clean as the first one plus it fetches backref twice!
                 * ------------------------------------------------------------------------------------- */
                int n = ((NthRefNode) node).getMatchNumber();
                Label undefLabel = s.getNewLabel();
                Variable tmpVar = s.getNewTemporaryVariable();
                s.addInstr(new BackrefIsMatchDataInstr(tmpVar));
                s.addInstr(BEQInstr.create(tmpVar, manager.getFalse(), undefLabel));
                // SSS FIXME:
                // - Can/should I use BEQInstr(new NthRef(n), manager.getNil(), undefLabel)? instead of .nil? & compare with flag?
View Full Code Here

    public IRScope getNewLexicalParentForClosure() {
        return inClosureCloneMode ? clonedClosure : getInlineHostScope();
    }

    public Label getRenamedLabel(Label l) {
        Label newLbl = this.lblRenameMap.get(l);
        if (newLbl == null) {
           newLbl = inClosureCloneMode ? l.clone() : getInlineHostScope().getNewLabel();
           this.lblRenameMap.put(l, newLbl);
        }
        return newLbl;
View Full Code Here

        System.out.println("source instrs:" + scope.getCFG().toStringInstrs());
*/

        // Host method data init
        InlinerInfo ii = new InlinerInfo(call, cfg);
        Label splitBBLabel = hostScope.getNewLabel();
        BasicBlock splitBB;

        // Inlinee method data init
        CFG methodCFG = scope.getCFG();
        BasicBlock mEntry = methodCFG.getEntryBB();
        BasicBlock mExit = methodCFG.getExitBB();
        List<BasicBlock> methodBBs = new ArrayList<BasicBlock>();
        for (BasicBlock b: methodCFG.getBasicBlocks()) methodBBs.add(b);

        // Check if we are inlining a recursive method
        if (hostScope.getNearestMethod() == scope) {
            // 1. clone self
            // SSS: FIXME: We need a clone-graph api method in cfg and graph
            CFG selfClone = cloneSelf(ii);

            // 2. add callee bbs and their edges
            // SSS: FIXME: We need a swallow-graph api method in cfg and graph
            for (BasicBlock b : selfClone.getBasicBlocks()) {
                cfg.addBasicBlock(b);
                for (Edge<BasicBlock> e : selfClone.getOutgoingEdges(b)) {
                    cfg.addEdge(b, e.getDestination().getData(), e.getType());
                }
            }
        } else {
            // 2. clone callee and add it to the host cfg
            for (BasicBlock b : methodCFG.getBasicBlocks()) {
                if (b != mEntry && b != mExit) {
                    cfg.addBasicBlock(b.cloneForInlinedMethod(ii));
                }
            }
            for (BasicBlock x : methodCFG.getBasicBlocks()) {
                if (x != mEntry && x != mExit) {
                    BasicBlock rx = ii.getRenamedBB(x);
                    for (Edge<BasicBlock> e : methodCFG.getOutgoingEdges(x)) {
                        BasicBlock b = e.getDestination().getData();
                        if (b != mExit) cfg.addEdge(rx, ii.getRenamedBB(b), e.getType());
                    }
                }
            }
        }

        // 3. split callsite bb, move outbound edges from callsite bb to split bb, and unhook call bb
        splitBB = callBB.splitAtInstruction(call, splitBBLabel, false);
        cfg.addBasicBlock(splitBB);
        for (Edge<BasicBlock> e : cfg.getOutgoingEdges(callBB)) {
            cfg.addEdge(splitBB, e.getDestination().getData(), e.getType());
        }
        cfg.removeAllOutgoingEdgesForBB(callBB);

        // 4a. Hook up entry edges
        assert methodCFG.outDegree(mEntry) == 2: "Entry BB of inlinee method does not have outdegree 2: " + methodCFG.toStringGraph();
        for (Edge<BasicBlock> e : methodCFG.getOutgoingEdges(mEntry)) {
            BasicBlock destination = e.getDestination().getData();
            if (destination != mExit) {
                BasicBlock dstBB = ii.getRenamedBB(destination);
                if (!ii.canMapArgsStatically()) {
                    dstBB.addInstr(new ToAryInstr((Variable)ii.getArgs(), new Array(call.getCallArgs()), cfg.getScope().getManager().getTrue()));
                }
                cfg.addEdge(callBB, dstBB, CFG.EdgeType.FALL_THROUGH);
            }
        }

        // 4b. Hook up exit edges
        for (Edge<BasicBlock> e : methodCFG.getIncomingEdges(mExit)) {
            BasicBlock source = e.getSource().getData();
            if (source != mEntry) {
                BasicBlock clonedSource = ii.getRenamedBB(source);
                if (e.getType() == EdgeType.EXCEPTION) {
                    // e._src has an explicit throw that returns from the callee
                    // after inlining, if the caller instruction has a rescuer, then the
                    // throw has to be captured by the rescuer as well.
                    BasicBlock rescuerOfSplitBB = cfg.getRescuerBBFor(splitBB);
                    if (rescuerOfSplitBB != null) {
                        cfg.addEdge(clonedSource, rescuerOfSplitBB, EdgeType.EXCEPTION);
                    } else {
                        cfg.addEdge(clonedSource, cfg.getExitBB(), EdgeType.EXIT);                       
                    }
                } else {
                    cfg.addEdge(clonedSource, splitBB, e.getType());
                }
            }
        }

        // SSS FIXME: Are these used anywhere post-CFG building?
        // 5. Clone exception regions
        List<ExceptionRegion> exceptionRegions = cfg.getOutermostExceptionRegions();
        for (ExceptionRegion r : methodCFG.getOutermostExceptionRegions()) {
            exceptionRegions.add(r.cloneForInlining(ii));
        }

        // 6. Update bb rescuer map
        // 6a. splitBB will be protected by the same bb as callBB
        BasicBlock callBBrescuer = cfg.getRescuerBBFor(callBB);
        if (callBBrescuer != null) cfg.setRescuerBB(splitBB, callBBrescuer);

        BasicBlock callBBensurer = cfg.getEnsurerBBFor(callBB);
        if (callBBensurer != null) cfg.setEnsurerBB(splitBB, callBBensurer);

        // 6b. remap existing protections for bbs in mcfg to their renamed bbs.
        // 6c. bbs in mcfg that aren't protected by an existing bb will be protected by callBBrescuer.
        for (BasicBlock x : methodBBs) {
            if (x != mEntry && x != mExit) {
                BasicBlock xRenamed = ii.getRenamedBB(x);
                BasicBlock xProtector = methodCFG.getRescuerBBFor(x);
                if (xProtector != null) {
                    cfg.setRescuerBB(xRenamed, ii.getRenamedBB(xProtector));
                } else if (callBBrescuer != null) {
                    cfg.setRescuerBB(xRenamed, callBBrescuer);
                }

                BasicBlock xEnsurer = methodCFG.getEnsurerBBFor(x);
                if (xEnsurer != null) {
                    cfg.setEnsurerBB(xRenamed, ii.getRenamedBB(xEnsurer));
                } else if (callBBensurer != null) {
                    cfg.setEnsurerBB(xRenamed, callBBensurer);
                }
            }
        }

        // 7. Add inline guard that verifies that the method inlined is the same
        // that gets called in future invocations.  In addition to the guard, add
        // a failure path code.
        Label failurePathLabel = hostScope.getNewLabel();
        callBB.addInstr(new ModuleVersionGuardInstr(implClass, classToken, call.getReceiver(), failurePathLabel));

        BasicBlock failurePathBB = new BasicBlock(cfg, failurePathLabel);
        cfg.addBasicBlock(failurePathBB);
        failurePathBB.addInstr(call);
View Full Code Here

        int numberOfLabels = bbs.size();
        int ipc = 0; // synthetic, used for debug traces that show which instr failed
        for (int i = 0; i < numberOfLabels; i++) {
            BasicBlock bb = bbs.get(i);
            org.objectweb.asm.Label start = jvm.methodData().getLabel(bb.getLabel());
            Label rescueLabel = exceptionTable.get(bb);
            org.objectweb.asm.Label end = null;

            m.mark(start);

            boolean newEnd = false;
View Full Code Here

     * @return the new Label
     */
    public Label getRenamedLabel(Label label) {
        if (Label.UNRESCUED_REGION_LABEL.equals(label)) return label; // Special case -- is there a way to avoid this?

        Label newLabel = this.labelRenameMap.get(label);
        if (newLabel == null) {
            newLabel = getRenamedLabelSimple(label);
            this.labelRenameMap.put(label, newLabel);
        }
        return newLabel;
View Full Code Here

        boolean nextBBIsFallThrough = true;
        for (Instr i : instrs) {
            // System.out.println("Processing: " + i);
            Operation iop = i.getOperation();
            if (iop == Operation.LABEL) {
                Label l = ((LabelInstr) i).label;
                newBB = createBB(l, nestedExceptionRegions);
                // Jump instruction bbs dont add an edge to the succeeding bb by default
                if (nextBBIsFallThrough) graph.addEdge(currBB, newBB, EdgeType.FALL_THROUGH);
                currBB = newBB;
                bbEnded = false;
                nextBBIsFallThrough = true;

                // Add forward reference edges
                List<BasicBlock> frefs = forwardRefs.get(l);
                if (frefs != null) {
                    for (BasicBlock b : frefs) {
                        graph.addEdge(b, newBB, EdgeType.REGULAR);
                    }
                }
            } else if (bbEnded && iop != Operation.EXC_REGION_END) {
                newBB = createBB(nestedExceptionRegions);
                // Jump instruction bbs dont add an edge to the succeeding bb by default
                if (nextBBIsFallThrough) graph.addEdge(currBB, newBB, EdgeType.FALL_THROUGH); // currBB cannot be null!
                currBB = newBB;
                bbEnded = false;
                nextBBIsFallThrough = true;
            }

            if (i instanceof ExceptionRegionStartMarkerInstr) {
                // We dont need the instruction anymore -- so it is not added to the CFG.
                ExceptionRegionStartMarkerInstr ersmi = (ExceptionRegionStartMarkerInstr) i;
                ExceptionRegion rr = new ExceptionRegion(ersmi.firstRescueBlockLabel, currBB);
                rr.addBB(currBB);
                allExceptionRegions.add(rr);

                if (!nestedExceptionRegions.empty()) {
                    nestedExceptionRegions.peek().addNestedRegion(rr);
                }

                nestedExceptionRegions.push(rr);
            } else if (i instanceof ExceptionRegionEndMarkerInstr) {
                // We dont need the instruction anymore -- so it is not added to the CFG.
                nestedExceptionRegions.pop().setEndBB(currBB);
            } else if (iop.endsBasicBlock()) {
                bbEnded = true;
                currBB.addInstr(i);
                Label tgt;
                nextBBIsFallThrough = false;
                if (i instanceof BranchInstr) {
                    tgt = ((BranchInstr) i).getJumpTarget();
                    nextBBIsFallThrough = true;
                } else if (i instanceof JumpInstr) {
                    tgt = ((JumpInstr) i).getJumpTarget();
                } else if (iop.isReturn()) { // BREAK, RETURN, CLOSURE_RETURN
                    tgt = null;
                    returnBBs.add(currBB);
                } else if (i instanceof ThrowExceptionInstr) {
                    tgt = null;
                    exceptionBBs.add(currBB);
                } else {
                    throw new RuntimeException("Unhandled case in CFG builder for basic block ending instr: " + i);
                }

                if (tgt != null) addEdge(currBB, tgt, forwardRefs);
            } else if (iop != Operation.LABEL) {
                currBB.addInstr(i);
            }

            if (i instanceof CallBase) { // Build CFG for the closure if there exists one
                Operand closureArg = ((CallBase) i).getClosureArg(getScope().getManager().getNil());
                if (closureArg instanceof WrappedIRClosure) {
                    ((WrappedIRClosure) closureArg).getClosure().buildCFG();
                }
            }
        }

        // Process all rescued regions
        for (ExceptionRegion rr: allExceptionRegions) {
            // When this exception region represents an unrescued region
            // from a copied ensure block, we have a dummy label
            Label rescueLabel = rr.getFirstRescueBlockLabel();
            if (!Label.UNRESCUED_REGION_LABEL.equals(rescueLabel)) {
                BasicBlock firstRescueBB = bbMap.get(rescueLabel);
                // Mark the BB as a rescue entry BB
                firstRescueBB.markRescueEntryBB();
View Full Code Here

TOP

Related Classes of org.jruby.ir.operands.Label

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.