Package org.jruby.compiler.ir.operands

Examples of org.jruby.compiler.ir.operands.Label


            // Now for the rest
        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();
                LocalAsgnNode n = (LocalAsgnNode)optArgs.get(j);
                Variable av = s.getLocalVariable(n.getName());
                s.addInstr(new ReceiveOptionalArgumentInstr(av, argIndex));
                s.addInstr(new BNEInstr(av, Nil.NIL, l)); // if 'av' is not null, go to default
                build(n, s);
View Full Code Here


        // Push a new ensure block info node onto the stack of ensure block
        EnsureBlockInfo ebi = new EnsureBlockInfo(m);
        _ensureBlockStack.push(ebi);

        Label rBeginLabel = m.getNewLabel();
        Label rEndLabel   = ebi.end;
        List<Label> rescueLabels = new ArrayList<Label>() { };

        // Start of region
        m.addInstr(new LABEL_Instr(rBeginLabel));
        m.addInstr(new ExceptionRegionStartMarkerInstr(rBeginLabel, rEndLabel, rescueLabels));

        // Generate IR for Code being protected
        Operand  rv = (bodyNode instanceof RescueNode) ? buildRescueInternal(bodyNode, m, rBeginLabel) : build(bodyNode, m);

        // End of protected region
        m.addInstr(new ExceptionRegionEndMarkerInstr());

        // Jump to start of ensure block -- dont bother if we had a return in the protected body
        if (rv != U_NIL)
            m.addInstr(new SET_RETADDR_Instr(ebi.returnAddr, rEndLabel));

        // Pop the current ensure block info node *BEFORE* generating the ensure code for this block itself!
        _ensureBlockStack.pop();

        // Generate the ensure block now
        m.addInstr(new LABEL_Instr(ebi.start));

        // Two cases:
        // 1. Ensure block has no explicit return => the result of the entire ensure expression is the result of the protected body.
        // 2. Ensure block has an explicit return => the result of the protected body is ignored.
        Operand ensureRetVal = (ensureNode.getEnsureNode() == null) ? Nil.NIL : build(ensureNode.getEnsureNode(), m);
        if (ensureRetVal == null)   // null => there was a return from within the ensure block!
            rv = null;

        m.addInstr(new JUMP_INDIRECT_Instr(ebi.returnAddr));

        // Now build the dummy rescue block that:
        // * catches all exceptions thrown by the body
        // * jumps to the ensure block code
        // * returns back (via set_retaddr instr)
        // * rethrows the caught exception
        Label dummyRescueBlockLabel = m.getNewLabel();
        Label rethrowExcLabel = m.getNewLabel();
        rescueLabels.add(dummyRescueBlockLabel);
        Variable exc = m.getNewTemporaryVariable();
        m.addInstr(new LABEL_Instr(dummyRescueBlockLabel));
        m.addInstr(new RECV_EXCEPTION_Instr(exc));
        m.addInstr(new SET_RETADDR_Instr(ebi.returnAddr, rethrowExcLabel));
View Full Code Here

    //
    public Operand buildIf(final IfNode ifNode, IRScope s) {
        Node actualCondition = skipOverNewlines(s, ifNode.getCondition());

        Variable result     = s.getNewTemporaryVariable();
        Label    falseLabel = s.getNewLabel();
        Label    doneLabel  = s.getNewLabel();
        Operand  thenResult = null;
        s.addInstr(new BEQInstr(build(actualCondition, s), BooleanLiteral.FALSE, falseLabel));

        boolean thenNull = false;
        boolean elseNull = false;
        boolean thenUnil = false;
        boolean elseUnil = false;

        // Build the then part of the if-statement
        if (ifNode.getThenBody() != null) {
            thenResult = build(ifNode.getThenBody(), s);
            if (thenResult != U_NIL) { // thenResult can be U_NIL if then-body ended with a return!
                // Local optimization of break results to short-circuit the jump right away
                // rather than wait to do it during an optimization pass.
                Label tgt = doneLabel;
                if (thenResult instanceof BreakResult) {
                    BreakResult br = (BreakResult)thenResult;
                    thenResult = br._result;
                    tgt = br._jumpTarget;
                }
View Full Code Here

    //    beq(f, false, L)
    //    x = -- build(y) --
    // L:
    //
    public Operand buildOpAsgnAnd(OpAsgnAndNode andNode, IRScope s) {
        Label    l  = s.getNewLabel();
        Operand  v1 = build(andNode.getFirstNode(), s);
        Variable f  = s.getNewTemporaryVariable();
        s.addInstr(new IsTrueInstr(f, v1));
        s.addInstr(new BEQInstr(f, BooleanLiteral.FALSE, l));
        build(andNode.getSecondNode(), s)// This does the assignment!
View Full Code Here

    //    beq(f, true, L)
    //    -- build(x = y) --
    // L:
    //
    public Operand buildOpAsgnOr(final OpAsgnOrNode orNode, IRScope s) {
        Label    l1 = s.getNewLabel();
        Label    l2 = null;
        Variable f = s.getNewTemporaryVariable();
        Operand  v1;
        boolean  needsDefnCheck = needsDefinitionCheck(orNode.getFirstNode());
        if (needsDefnCheck) {
            l2 = s.getNewLabel();
View Full Code Here

    // L:
    //
    public Operand buildOpElementAsgnWithOr(Node node, IRScope s) {
        final OpElementAsgnNode opElementAsgnNode = (OpElementAsgnNode) node;
        Operand array = build(opElementAsgnNode.getReceiverNode(), s);
        Label    l     = s.getNewLabel();
        Variable elt   = s.getNewTemporaryVariable();
        Variable flag  = s.getNewTemporaryVariable();
        List<Operand> args = setupCallArgs(opElementAsgnNode.getArgsNode(), s);
        // SSS FIXME: Verify with Tom that I am not missing something here
        assert args.size() == 1;
View Full Code Here

    // Translate "a[x] &&= n" --> "a[x] = n if is_true(a[x])"
    public Operand buildOpElementAsgnWithAnd(Node node, IRScope s) {
        final OpElementAsgnNode opElementAsgnNode = (OpElementAsgnNode) node;
        Operand array = build(opElementAsgnNode.getReceiverNode(), s);
        Label    l     = s.getNewLabel();
        Variable elt   = s.getNewTemporaryVariable();
        Variable flag  = s.getNewTemporaryVariable();
        List<Operand> args = setupCallArgs(opElementAsgnNode.getArgsNode(), s);
        // SSS FIXME: Verify with Tom that I am not missing something here
        assert args.size() == 1;
View Full Code Here

            // build first node as non-expr and build second node
            build(orNode.getFirstNode(), m);
            return build(orNode.getSecondNode(), m);
        } else {
            Variable ret = m.getNewTemporaryVariable();
            Label    l   = m.getNewLabel();
            Operand  v1  = build(orNode.getFirstNode(), m);
            m.addInstr(new CopyInstr(ret, v1));
            m.addInstr(new BEQInstr(v1, BooleanLiteral.TRUE, l));
            Operand  v2  = build(orNode.getSecondNode(), m);
            m.addInstr(new CopyInstr(ret, v2));
View Full Code Here

        final RescueNode rescueNode = (RescueNode) node;
        boolean noEnsure    = _ensureBlockStack.empty();
        EnsureBlockInfo ebi = noEnsure ? null : _ensureBlockStack.peek();

        // Labels marking start, else, end of the begin-rescue(-ensure)-end block
        Label   rBeginLabel = availableBeginLabel != null ? availableBeginLabel : m.getNewLabel()
        Label   rEndLabel   = noEnsure ? m.getNewLabel() : ebi.end;
        Label   elseLabel   = rescueNode.getElseNode() == null ? null : m.getNewLabel();

        // Only generate the label instruction if we weren't passed in a label
        // Optimization to eliminate extra labels in begin-rescue-ensure-end code
        if (availableBeginLabel == null)
            m.addInstr(new LABEL_Instr(rBeginLabel));

        // Placeholder rescue instruction that tells rest of the compiler passes the boundaries of the rescue block.
        List<Label> rescueBlockLabels = new ArrayList<Label>();
        ExceptionRegionStartMarkerInstr rbStartInstr = new ExceptionRegionStartMarkerInstr(rBeginLabel, rEndLabel, rescueBlockLabels);
        m.addInstr(rbStartInstr);

        // Body
        Operand tmp = Nil.NIL;  // default return value if for some strange reason, we neither have the body node or the else node!
        Variable rv = m.getNewTemporaryVariable();
        if (rescueNode.getBodyNode() != null)
            tmp = build(rescueNode.getBodyNode(), m);

        // Else part of the body -- we simply fall through from the main body if there were no exceptions
        if (elseLabel != null) {
            m.addInstr(new LABEL_Instr(elseLabel));
            tmp = build(rescueNode.getElseNode(), m);
        }

        if (tmp != U_NIL) {
            m.addInstr(new CopyInstr(rv, tmp));

            // No explicit return from the protected body
            // - If we dont have any ensure blocks, simply jump to the end of the rescue block
            // - If we do, get the innermost ensure block, set up the return address to the end of the ensure block, and go execute the ensure code.
            if (noEnsure) {
                m.addInstr(new JumpInstr(rEndLabel));
            }
            else {
                // NOTE: rEndLabel is identical to ebi.end, but less confusing to use rEndLabel since that makes more semantic sense
                m.addInstr(new SET_RETADDR_Instr(ebi.returnAddr, rEndLabel));
                m.addInstr(new JumpInstr(ebi.start));
            }
        }
        else {
            // If the body had an explicit return, the return instruction IR build takes care of setting
            // up execution of all necessary ensure blocks.  So, nothing to do here! 
            //
            // Additionally, the value in 'rv' will never be used, so need to set it to any specific value.
            // So, we can leave it undefined.  If on the other hand, there was an exception in that block,
            // 'rv' will get set in the rescue handler -- see the 'rv' being passed into
            // buildRescueBodyInternal below.  So, in either case, we are good!
        }

        // Since rescued regions are well nested within Ruby, this bare marker is sufficient to
        // let us discover the edge of the region during linear traversal of instructions during cfg construction.
        ExceptionRegionEndMarkerInstr rbEndInstr = new ExceptionRegionEndMarkerInstr();
        m.addInstr(rbEndInstr);

        // Build the actual rescue block(s)
        Label rbLabel = m.getNewLabel(); // Label marking start of the first rescue code.
        rescueBlockLabels.add(rbLabel);
        m.addInstr(new LABEL_Instr(rbLabel));
        buildRescueBodyInternal(m, rescueNode.getRescueNode(), rv, rEndLabel, rescueBlockLabels);

        // End label -- only if there is no ensure block!  With an ensure block, you end at ensureEndLabel.
View Full Code Here

        // SSS: FIXME: Is this correct?
        // Compute all elements of the exception array eagerly
//        Operand excType = (exceptionList == null) ? null : build(exceptionList, m);

        // Compare and branch as necessary!
        Label uncaughtLabel = null;
        if (exceptionList != null) {
            uncaughtLabel = m.getNewLabel();
            Variable eqqResult = m.getNewTemporaryVariable();
            for (Node excType : ((ListNode) exceptionList).childNodes()) {
                m.addInstr(new EQQInstr(eqqResult, build(excType, m), exc));
View Full Code Here

TOP

Related Classes of org.jruby.compiler.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.