Package org.jruby.ir.operands

Examples of org.jruby.ir.operands.Variable


            // Simplify instruction and record mapping between target variable and simplified value
            // System.out.println("BEFORE: " + i);
            Operand  val = i.simplifyAndGetResult(s, valueMap);
            // FIXME: This logic can be simplified based on the number of res != null checks only done if doesn't
            Variable res = i instanceof ResultInstr ? ((ResultInstr) i).getResult() : null;

            // System.out.println("AFTER: " + i + "; dst = " + res + "; val = " + val);

            if (res != null && val != null) {
                if (!res.equals(val)) {
                    recordSimplification(res, val, valueMap, simplificationMap);
                }

                if (!i.hasSideEffects()) {
                    if (i instanceof CopyInstr) {
                        if (res.equals(val) && i.canBeDeleted(s)) {
                            i.markDead();
                            instrs.remove();
                        }
                    } else {
                        instrs.set(new CopyInstr(res, val));
                    }
                }
            } else if (res != null && val == null) {
                // If we didn't get a simplified value, remove any existing simplifications for the result
                // to get rid of RAW hazards!
                valueMap.remove(res);
            }

            // Purge all entries in valueMap that have 'res' as their simplified value to take care of RAW scenarios (because we aren't in SSA form yet!)
            if (res != null && !res.equals(val)) {
                List<Variable> simplifiedVars = simplificationMap.get(res);
                if (simplifiedVars != null) {
                    for (Variable v: simplifiedVars) {
                        valueMap.remove(v);
                    }
View Full Code Here


                // Only scopes that have unrescued exceptions need a GEB.
                //
                // Allocate GEB if necessary for popping
                BasicBlock geb = cfg.getGlobalEnsureBB();
                if (geb == null) {
                    Variable exc = scope.createTemporaryVariable();
                    geb = new BasicBlock(cfg, Label.getGlobalEnsureBlockLabel());
                    geb.addInstr(new ReceiveJRubyExceptionInstr(exc)); // JRuby Implementation exception handling
                    geb.addInstr(new ThrowExceptionInstr(exc));
                    cfg.addGlobalEnsureBB(geb);
                }
View Full Code Here

    private void collectNonLocalDirtyVars(IRClosure cl, Set<LocalVariable> vars, int minDepth) {
        for (BasicBlock bb: cl.cfg().getBasicBlocks()) {
            for (Instr i: bb.getInstrs()) {
                // Collect local vars belonging to an outer scope dirtied here
                if (i instanceof ResultInstr) {
                    Variable res = ((ResultInstr)i).getResult();
                    if (res instanceof LocalVariable && ((LocalVariable)res).getScopeDepth() > minDepth) {
                        vars.add((LocalVariable)res);
                    }
                }
View Full Code Here

                     }
                     uses.add(i);
                 }
            }
            if (i instanceof ResultInstr) {
                Variable v = ((ResultInstr)i).getResult();
                if (v instanceof TemporaryVariable) {
                     TemporaryVariable tv = (TemporaryVariable)v;
                     List<Instr> defs = tmpVarDefs.get(tv);
                     if (defs == null) {
                         defs = new ArrayList<Instr>();
                         tmpVarDefs.put(tv, defs);
                     }
                     defs.add(i);
                }
            }
        }

        // Pass 2: Transform code and do additional analysis:
        // * If the result of this instr. has not been used, mark it dead
        // * Find copies where constant values are set
        Map<TemporaryVariable, Variable> removableCopies = new HashMap<TemporaryVariable, Variable>();
        ListIterator<Instr> instrs = s.getInstrs().listIterator();
        while (instrs.hasNext()) {
            Instr i = instrs.next();

            if (i instanceof ResultInstr) {
                Variable v = ((ResultInstr)i).getResult();
                if (v instanceof TemporaryVariable) {
                    // Deal with this code pattern:
                    //    %v = ...
                    // %v not used anywhere
                    List<Instr> uses = tmpVarUses.get((TemporaryVariable)v);
                    List<Instr> defs = tmpVarDefs.get((TemporaryVariable)v);
                    if (uses == null) {
                        if (i instanceof CopyInstr) {
                            i.markDead();
                            instrs.remove();
                        } else if (i instanceof CallInstr) {
                            instrs.set(((CallInstr)i).discardResult());
                        } else {
                            i.markUnusedResult();
                        }
                    }
                    // Deal with this code pattern:
                    //    %v = <some-operand>
                    //    .... %v ...
                    // %v not used or defined anywhere else
                    // So, %v can be replaced by the operand
                    else if ((uses.size() == 1) && (defs != null) && (defs.size() == 1) && (i instanceof CopyInstr)) {
                        Instr soleUse = uses.get(0);
                        // Conservatively avoid optimizing return values since
                        // intervening cloned ensure block code can modify the
                        // copy source (if it is a variable).
                        //
                        // Ex:
                        //    v = 1
                        //    %v_1 = v
                        // L1:
                        //    v = 2
                        //    return %v_1 <-- cannot be replaced with v
                        //    ....
                        if (!(soleUse instanceof ReturnInstr)) {
                            CopyInstr ci = (CopyInstr)i;
                            Operand src = ci.getSource();
                            i.markDead();
                            instrs.remove();

                            // Fix up use
                            Map<Operand, Operand> copyMap = new HashMap<Operand, Operand>();
                            copyMap.put(v, src);
                            soleUse.simplifyOperands(copyMap, true);
                        }
                    }
                }
                // Deal with this code pattern:
                //    1: %v = ... (not a copy)
                //    2: x = %v
                // If %v is not used anywhere else, the result of 1. can be updated to use x and 2. can be removed
                //
                // NOTE: consider this pattern:
                //    %v = <operand> (copy instr)
                //    x = %v
                // This code will have been captured in the previous if branch which would have deleted %v = 5
                // Hence the check for whether the src def instr is dead
                else if (i instanceof CopyInstr) {
                    CopyInstr ci = (CopyInstr)i;
                    Operand src = ci.getSource();
                    if (src instanceof TemporaryVariable) {
                        TemporaryVariable vsrc = (TemporaryVariable)src;
                        List<Instr> uses = tmpVarUses.get(vsrc);
                        List<Instr> defs = tmpVarDefs.get(vsrc);
                        if ((uses.size() == 1) && (defs.size() == 1)) {
                            Instr soleDef = defs.get(0);
                            if (!soleDef.isDead()) {
                                // Fix up def
                                ((ResultInstr)soleDef).updateResult(ci.getResult());
                                ci.markDead();
                                instrs.remove();
                            }
                        }
                    }
                }
            }
        }

        // Pass 3: Compute last use of temporary variables -- this effectively is the
        // end of the live range that started with its first definition. This implicitly
        // encodes the live range of the temporary variable.
        //
        // These live ranges are valid because these instructions are generated from an AST
        // and they haven't been rearranged yet.  In addition, since temporaries are used to
        // communicate results from lower levels to higher levels in the tree, a temporary
        // defined outside a loop cannot be used within the loop.  So, the first definition
        // of a temporary and the last use of the temporary delimit its live range.
        //
        // Caveat
        // ------
        // %current-scope and %current-module are the two "temporary" variables that violate
        // this contract right now since they are used everywhere in the scope.
        // So, in the presence of loops, we:
        // - either assume that the live range of these  variables extends to
        //   the end of the outermost loop in which they are used
        // - or we do not rename %current-scope and %current-module in such scopes.
        //
        // SSS FIXME: For now, we just extend the live range of these vars all the
        // way to the end of the scope!
        //
        // NOTE: It is sufficient to just track last use for renaming purposes.
        // At the first definition, we allocate a variable which then starts the live range
        Map<TemporaryVariable, Integer> lastVarUseOrDef = new HashMap<TemporaryVariable, Integer>();
        int iCount = -1;
        for (Instr i: s.getInstrs()) {
            iCount++;

            // update last use/def
            if (i instanceof ResultInstr) {
                Variable v = ((ResultInstr)i).getResult();
                if (v instanceof TemporaryVariable) lastVarUseOrDef.put((TemporaryVariable)v, iCount);
            }

            // update last use/def
            for (Variable v: i.getUsedVariables()) {
                if (v instanceof TemporaryVariable) lastVarUseOrDef.put((TemporaryVariable)v, iCount);
            }
        }

        // If the scope has loops, extend live range of %current-module and %current-scope
        // to end of scope (see note earlier).
        if (s.hasLoops()) {
            lastVarUseOrDef.put((TemporaryVariable)s.getCurrentScopeVariable(), iCount);
            lastVarUseOrDef.put((TemporaryVariable)s.getCurrentModuleVariable(), iCount);
        }

        // Pass 4: Reallocate temporaries based on last uses to minimize # of unique vars.
        // Replace all single use operands with constants they were assigned to.
        // Using operand -> operand signature because simplifyOperands works on operands
        Map<Operand, Operand>   newVarMap    = new HashMap<Operand, Operand>();
        List<TemporaryVariable> freeVarsList = new ArrayList<TemporaryVariable>();
        iCount = -1;
        s.resetTemporaryVariables();

        for (Instr i: s.getInstrs()) {
            iCount++;

            // Assign new vars
            Variable result = null;
            if (i instanceof ResultInstr) {
                result = ((ResultInstr)i).getResult();
                if (result instanceof TemporaryVariable) allocVar(result, s, freeVarsList, newVarMap);
            }
            for (Variable v: i.getUsedVariables()) {
View Full Code Here

        for (BasicBlock b: s.getCFG().getBasicBlocks()) {
            ListIterator<Instr> instrs = b.getInstrs().listIterator();
            while (instrs.hasNext()) {
                Instr i = instrs.next();
                if (i instanceof ResultInstr) {
                    Variable v = ((ResultInstr) i).getResult();
                    // %self is local to every scope and never crosses scope boundaries and need not be spilled/refilled
                    if (v instanceof LocalVariable && !v.isSelf()) {
                        LocalVariable lv = (LocalVariable)v;
                        if (lv.getScopeDepth() == 0) {
                            // Make sure there is a replacement tmp-var allocated for lv
                            setupLocalVarReplacement(lv, s, varRenameMap);
                        } else {
                            parentScopeNeeded = true;
                            decrementScopeDepth(lv, s, varRenameMap);
                        }
                    }
                }

                for (Variable v : i.getUsedVariables()) {
                    if (v instanceof LocalVariable && !v.isSelf()) {
                        LocalVariable lv = (LocalVariable)v;
                        if (lv.getScopeDepth() == 0) {
                            // SSS FIXME: Ugly/Dirty! Some abstraction is broken.
                            // If we hit a load/store instr for a local-var and we
                            // eliminated the dynscope for it, we no longer need the
View Full Code Here

                // with a COPY of the break-value into the call's result var.
                // Ex: v = foo { ..; break n; ..}.  So, "break n" is replaced with "v = n"
                // The CFG for the closure will be such that after break, control goes to the
                // scope exit block.  So, we know that after the copy, we'll continue with the
                // instruction after the call.
                Variable v = ii.getCallResultVariable();
                return (v == null) ? null : new CopyInstr(v, returnValue.cloneForInlining(ii));
            }

            return new BreakInstr(returnValue.cloneForInlining(ii), scopeName);
        } else {
View Full Code Here

        InlineCloneInfo ii = (InlineCloneInfo) info;
        if (ii.isClosure()) {
            if (ii.getHostScope() instanceof IRMethod) {
                // Treat like inlining of a regular method-return
                Variable v = ii.getCallResultVariable();
                return v == null ? null : new CopyInstr(v, returnValue.cloneForInlining(ii));
            }

            return new NonlocalReturnInstr(returnValue.cloneForInlining(ii), methodName);
        } else {
View Full Code Here

     */
    public Set<LocalVariable> addLiveLocalVars(Set<LocalVariable> list, BitSet living) {
        for (int j = 0; j < living.size(); j++) {
            if (!living.get(j)) continue;

            Variable v = getVariable(j);
            if (v instanceof LocalVariable) list.add((LocalVariable) v);
        }

        return list;
    }
View Full Code Here

        BitSet liveIn = getFlowGraphNode(getScope().cfg().getEntryBB()).getLiveOutBitSet();

        for (int i = 0; i < liveIn.size(); i++) {
            if (!liveIn.get(i)) continue;

            Variable v = getVariable(i);
            liveVars.add(v);
            // System.out.println("variable " + v + " is live on entry!");
        }

        return liveVars;
View Full Code Here

        InlineCloneInfo ii = (InlineCloneInfo) info;

        if (ii.isClosure()) return new CopyInstr(ii.getYieldResult(), returnValue.cloneForInlining(ii));

        Variable v = ii.getCallResultVariable();
        return v == null ? null : new CopyInstr(v, returnValue.cloneForInlining(ii));
    }
View Full Code Here

TOP

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

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.