Package org.jruby.ir.operands

Examples of org.jruby.ir.operands.Label


                entryBB.addInstr(new PushBindingInstr(scope));

                // Allocate GEB if necessary for popping binding
                if (geb == null && (scopeHasLocalVarStores || scopeHasUnrescuedExceptions)) {
                    Variable exc = scope.getNewTemporaryVariable();
                    geb = new BasicBlock(cfg, new Label("_GLOBAL_ENSURE_BLOCK"));
                    geb.addInstr(new ReceiveExceptionInstr(exc, false)); // No need to check type since it is not used before rethrowing
                    geb.addInstr(new ThrowExceptionInstr(exc));
                    cfg.addGlobalEnsureBB(geb);
                }
View Full Code Here


        // Allocate global-ensure block, if necessary
        BasicBlock geb = null;
        if ((mightRequireGlobalEnsureBlock == true) && !dirtyVars.isEmpty()) {
            Variable exc = cfgScope.getNewTemporaryVariable();
            geb = new BasicBlock(cfg, new Label("_GLOBAL_ENSURE_BLOCK"));
            geb.addInstr(new ReceiveExceptionInstr(exc, false)); // No need to check type since it is not used before rethrowing
            for (LocalVariable v : dirtyVars) {
                Operand value = varRenameMap.get(v);
                if (value == null) {
                    value = cfgScope.getNewTemporaryVariable("%t_" + v.getName());
View Full Code Here

        boolean bbEnded = false;
        boolean nextBBIsFallThrough = true;
        for (Instr i : instrs) {
            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) {
// SSS: Do we need this anymore?
//                currBB.addInstr(i);
                ExceptionRegionStartMarkerInstr ersmi = (ExceptionRegionStartMarkerInstr) i;
                ExceptionRegion rr = new ExceptionRegion(ersmi.firstRescueBlockLabel, ersmi.ensureBlockLabel);
                rr.addBB(currBB);
                allExceptionRegions.add(rr);

                if (nestedExceptionRegions.empty()) {
                    outermostERs.add(rr);
                } else {
                    nestedExceptionRegions.peek().addNestedRegion(rr);
                }

                nestedExceptionRegions.push(rr);
            } else if (i instanceof ExceptionRegionEndMarkerInstr) {
// SSS: Do we need this anymore?
//                currBB.addInstr(i);
                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 if (i instanceof JumpIndirectInstr) {
                    tgt = null;
                    Set<Label> retAddrs = retAddrMap.get(((JumpIndirectInstr) i).getJumpTarget());
                    for (Label l : retAddrs) {
                        addEdge(currBB, l, forwardRefs);
                    }
                    // Record the target bb for the retaddr var for any set_addr instrs that appear later and use the same retaddr var
                    retAddrTargetMap.put(((JumpIndirectInstr) i).getJumpTarget(), 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 SetReturnAddressInstr) {
                Variable v = ((SetReturnAddressInstr) i).getResult();
                Label tgtLbl = ((SetReturnAddressInstr) i).getReturnAddr();
                BasicBlock tgtBB = retAddrTargetMap.get(v);
                // If we have the target bb, add the edge
                // If not, record it for fixup later
                if (tgtBB != null) {
                    addEdge(tgtBB, tgtLbl, forwardRefs);
View Full Code Here

                EnsureBlockInfo ebi = ebArray[i];

                //
                if (ebi.innermostLoop != loop) break;

                Label retLabel = s.getNewLabel();
                if (ebi.savedGlobalException != null) {
                    s.addInstr(new PutGlobalVarInstr("$!", ebi.savedGlobalException));
                }
                s.addInstr(new SetReturnAddressInstr(ebi.returnAddr, retLabel));
                s.addInstr(new JumpInstr(ebi.start));
View Full Code Here

            return build(andNode.getSecondNode(), s);
        } else if (andNode.getFirstNode().getNodeType().alwaysFalse()) {
            // build first node only and return its value
            return build(andNode.getFirstNode(), s);
        } else {
            Label    l   = s.getNewLabel();
            Operand  v1  = build(andNode.getFirstNode(), s);
            Variable ret = getValueInTemporaryVariable(s, v1);
            s.addInstr(BEQInstr.create(v1, manager.getFalse(), l));
            Operand  v2  = build(andNode.getSecondNode(), s);
            s.addInstr(new CopyInstr(ret, v2));
View Full Code Here

        // Once the break instruction executes, control exits this scope
        return UnexecutableNil.U_NIL;
    }

    private void handleNonlocalReturnInMethod(IRScope s) {
        Label rBeginLabel = s.getNewLabel();
        Label rEndLabel   = s.getNewLabel();
        Label gebLabel    = s.getNewLabel();

        // protect the entire body as it exists now with the global ensure block
        s.addInstrAtBeginning(new ExceptionRegionStartMarkerInstr(rBeginLabel, rEndLabel, gebLabel, gebLabel));
        s.addInstr(new ExceptionRegionEndMarkerInstr());
View Full Code Here

            // No protection needed -- add the call and return
            s.addInstr((Instr)callInstr);
            return;
        }

        Label rBeginLabel = s.getNewLabel();
        Label rEndLabel   = s.getNewLabel();
        Label rescueLabel = s.getNewLabel();

        // Protected region
        s.addInstr(new ExceptionRegionStartMarkerInstr(rBeginLabel, rEndLabel, null, rescueLabel));
        s.addInstr(callInstr);
        s.addInstr(new JumpInstr(rEndLabel));
View Full Code Here

        //     when true <blah>
        //     when false <blah>
        //   end
        if (value == null) value = UndefinedValue.UNDEFINED;

        Label     endLabel  = s.getNewLabel();
        boolean   hasElse   = (caseNode.getElseNode() != null);
        Label     elseLabel = s.getNewLabel();
        Variable  result    = s.getNewTemporaryVariable();

        List<Label> labels = new ArrayList<Label>();
        Map<Label, Node> bodies = new HashMap<Label, Node>();

        // build each "when"
        for (Node aCase : caseNode.getCases().childNodes()) {
            WhenNode whenNode = (WhenNode)aCase;
            Label bodyLabel = s.getNewLabel();

            Variable eqqResult = s.getNewTemporaryVariable();
            labels.add(bodyLabel);
            Operand v1, v2;
            if (whenNode.getExpressionNodes() instanceof ListNode) {
                // SSS FIXME: Note about refactoring:
                // - BEQInstr has a quick implementation when the second operand is a boolean literal
                //   If it can be fixed to do this even on the first operand, we can switch around
                //   v1 and v2 in the UndefinedValue scenario and DRY out this code.
                // - Even with this asymmetric implementation of BEQInstr, you might be tempted to
                //   switch around v1 and v2 in the else case.  But, that is equivalent to this Ruby code change:
                //      (v1 == value) instead of (value == v1)
                //   It seems that they should be identical, but the first one is v1.==(value) and the second one is
                //   value.==(v1).  This is just fine *if* the Ruby programmer has implemented an algebraically
                //   symmetric "==" method on those objects.  If not, then, the results might be unexpected where the
                //   code (intentionally or otherwise) relies on this asymmetry of "==".  While it could be argued
                //   that this a Ruby code bug, we will just try to preserve the order of the == check as it appears
                //   in the Ruby code.
                if (value == UndefinedValue.UNDEFINED)  {
                    v1 = build(whenNode.getExpressionNodes(), s);
                    v2 = manager.getTrue();
                } else {
                    v1 = value;
                    v2 = build(whenNode.getExpressionNodes(), s);
                }
            } else {
                s.addInstr(new EQQInstr(eqqResult, build(whenNode.getExpressionNodes(), s), value));
                v1 = eqqResult;
                v2 = manager.getTrue();
            }
            s.addInstr(BEQInstr.create(v1, v2, bodyLabel));

            // SSS FIXME: This doesn't preserve original order of when clauses.  We could consider
            // preserving the order (or maybe not, since we would have to sort the constants first
            // in any case) for outputing jump tables in certain situations.
            //
            // add body to map for emitting later
            bodies.put(bodyLabel, whenNode.getBodyNode());
        }

        // Jump to else in case nothing matches!
        s.addInstr(new JumpInstr(elseLabel));

        // build "else" if it exists
        if (hasElse) {
            labels.add(elseLabel);
            bodies.put(elseLabel, caseNode.getElseNode());
        }

        // now emit bodies while preserving when clauses order
        for (Label whenLabel: labels) {
            s.addInstr(new LabelInstr(whenLabel));
            Operand bodyValue = build(bodies.get(whenLabel), s);
            // bodyValue can be null if the body ends with a return!
            if (bodyValue != null) {
               // SSS FIXME: Do local optimization of break results (followed by a copy & jump) to short-circuit the jump right away
               // rather than wait to do it during an optimization pass when a dead jump needs to be removed.  For this, you have
               // to look at what the last generated instruction was.
               Label tgt = endLabel;
               s.addInstr(new CopyInstr(result, bodyValue));
               s.addInstr(new JumpInstr(tgt));
            }
        }

View Full Code Here

    private Operand protectCodeWithRescue(IRScope m, CodeBlock protectedCode, Object[] protectedCodeArgs, CodeBlock rescueBlock, Object[] rescueBlockArgs) {
        // This effectively mimics a begin-rescue-end code block
        // Except this catches all exceptions raised by the protected code

        Variable rv = m.getNewTemporaryVariable();
        Label rBeginLabel = m.getNewLabel();
        Label rEndLabel   = m.getNewLabel();
        Label rescueLabel = m.getNewLabel();

        // Protected region code
        m.addInstr(new LabelInstr(rBeginLabel));
        m.addInstr(new ExceptionRegionStartMarkerInstr(rBeginLabel, rEndLabel, null, rescueLabel));
        Object v1 = protectedCode.run(protectedCodeArgs); // YIELD: Run the protected code block
        m.addInstr(new CopyInstr(rv, (Operand)v1));
        m.addInstr(new JumpInstr(rEndLabel));
        m.addInstr(new ExceptionRegionEndMarkerInstr());

        // SSS FIXME: Create an 'Exception' operand type to eliminate the constant lookup below
        // We could preload a set of constant objects that are preloaded at boot time and use them
        // directly in IR when we know there is no lookup involved.
        //
        // new Operand type: CachedClass(String name)?
        //
        // Some candidates: Exception, StandardError, Fixnum, Object, Boolean, etc.
        // So, when they are referenced, they are fetched directly from the runtime object
        // which probably already has cached references to these constants.
        //
        // But, unsure if this caching is safe ... so, just an idea here for now.

        // Rescue code
        Label caughtLabel = m.getNewLabel();
        Variable exc = m.getNewTemporaryVariable();
        Variable excType = m.getNewTemporaryVariable();

        // Receive 'exc' and verify that 'exc' is of ruby-type 'Exception'
        m.addInstr(new LabelInstr(rescueLabel));
View Full Code Here

            return buildVersionSpecificGetDefinitionIR(node, s);
        }
    }

    protected Variable buildDefnCheckIfThenPaths(IRScope s, Label undefLabel, Operand defVal) {
        Label defLabel = s.getNewLabel();
        Variable tmpVar = getValueInTemporaryVariable(s, defVal);
        s.addInstr(new JumpInstr(defLabel));
        s.addInstr(new LabelInstr(undefLabel));
        s.addInstr(new CopyInstr(tmpVar, manager.getNil()));
        s.addInstr(new LabelInstr(defLabel));
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.