Package org.jruby.ir.instructions

Examples of org.jruby.ir.instructions.CallBase


        Set<LocalVariable> dirtyVars = new HashSet<LocalVariable>(inDirtyVars);

        for (Instr i : basicBlock.getInstrs()) {
            // Process calls specially -- these are the sites of binding stores!
            if (i instanceof CallBase) {
                CallBase call = (CallBase) i;
                // At this call site, a binding will get allocated if it has not been already!
                Operand o = call.getClosureArg(null);
                if (o != null && o instanceof WrappedIRClosure) {
                    // In this first pass, the current scope and the call's closure are considered
                    // independent of each other which means any variable that is used by the variable
                    // will get spilled into the binding.  This is clearly conservative, but simplifies
                    // the analysis.
                    IRClosure cl = ((WrappedIRClosure) o).getClosure();

                    // If the call is a dataflow barrier, we have to spill everything here
                    boolean spillAllVars = scopeBindingHasEscaped || call.targetRequiresCallersBinding();

                    // - If all variables have to be spilled, then those variables will no longer be dirty after the call site
                    // - If a variable is used in the closure (FIXME: Strictly only those vars that are live at the call site --
                    //   but we dont have this info!), it has to be spilt. So, these variables are no longer dirty after the call site.
                    // - If a variable is (re)defined in the closure, it will always be loaded after the call. So, we have to always
                    //   spill it before the call in the scenario that the closure never gets executed! So, it won't be dirty after
                    //   the call site.
                    Set<LocalVariable> newDirtyVars = new HashSet<LocalVariable>(dirtyVars);
                    for (LocalVariable v : dirtyVars) {
                        if (spillAllVars || cl.usesLocalVariable(v) || cl.definesLocalVariable(v)) {
                            newDirtyVars.remove(v);
                        }
                    }
                    dirtyVars = newDirtyVars;
                } else if (scopeBindingHasEscaped || call.targetRequiresCallersBinding()) { // Call has no closure && it requires stores
                    dirtyVars.clear();
                } else {
                    // All variables not local to the current scope have to be always spilled because of
                    // multi-threading scenarios where some other scope could load this variable concurrently.
                    //
View Full Code Here


        while (instrs.hasNext()) {
            Instr i = instrs.next();

            if (i instanceof CallBase) {
                CallBase call = (CallBase) i;
                Operand o = call.getClosureArg(null);
                if (o != null && o instanceof WrappedIRClosure) {
                    IRClosure cl = ((WrappedIRClosure) o).getClosure();

                    // Add before call -- hence instrs.previous & instrs.next
                    instrs.previous();

                    // If the call is a dataflow barrier, we have to spill everything here
                    boolean spillAllVars = scopeBindingHasEscaped || call.targetRequiresCallersBinding();

                    // Unless we have to spill everything, spill only those dirty variables that are:
                    // - used in the closure (FIXME: Strictly only those vars that are live at the call site -- but we dont have this info!)
                    Set<LocalVariable> newDirtyVars = new HashSet<LocalVariable>(dirtyVars);
                    for (LocalVariable v : dirtyVars) {
                        // We have to spill the var that is defined in the closure as well because the load var pass
                        // will attempt to load the var always.  So, if the call doesn't actually call the closure,
                        // we'll be in trouble in that scenario!
                        if (spillAllVars || cl.usesLocalVariable(v) || cl.definesLocalVariable(v)) {
                            addedStores = true;
                            instrs.add(new StoreLocalVarInstr(getLocalVarReplacement(v, scope, varRenameMap), scope, v));
                            newDirtyVars.remove(v);
                        }
                    }
                    dirtyVars = newDirtyVars;
                    instrs.next();
                } else if (scopeBindingHasEscaped || call.targetRequiresCallersBinding()) { // Call has no closure && it requires stores
                    // Add before call -- hence instrs.previous & instrs.next
                    instrs.previous();
                    for (LocalVariable v : dirtyVars) {
                        addedStores = true;
                        instrs.add(new StoreLocalVarInstr(getLocalVarReplacement(v, scope, varRenameMap), scope, v));
View Full Code Here

            // Right away, clear the variable defined by this instruction -- it doesn't have to be loaded!
            if (i instanceof ResultInstr) reqdLoads.remove(((ResultInstr) i).getResult());

            // Process calls specially -- these are the sites of binding loads!
            if (i instanceof CallBase) {
                CallBase call = (CallBase) i;
                Operand o = call.getClosureArg(null);
                if (o != null && o instanceof WrappedIRClosure) {
                    IRClosure cl = ((WrappedIRClosure) o).getClosure();

                    // Variables defined in the closure do not need to be loaded anymore at
                    // program points before the call, because they will be loaded after the
                    // call completes to fetch the latest value.
                    //
                    // Allocate a new hash-set and modify it to get around ConcurrentModificationException on reqdLoads
                    Set<LocalVariable> newReqdLoads = new HashSet<LocalVariable>(reqdLoads);
                    for (LocalVariable v: reqdLoads) {
                        if (cl.definesLocalVariable(v)) newReqdLoads.remove(v);
                    }
                    reqdLoads = newReqdLoads;
                }

                // In this case, we are going to blindly load everything -- so, at the call site, pending loads dont carry over!
                if (scopeBindingHasEscaped || call.targetRequiresCallersBinding()) {
                    reqdLoads.clear();
                } else {
                    // All variables not defined in the current scope have to be always loaded
                    // because of multi-threading scenarios where some other scope
                    // could update this variable concurrently.
View Full Code Here

            // Right away, clear the variable defined by this instruction -- it doesn't have to be loaded!
            if (i instanceof ResultInstr) reqdLoads.remove(((ResultInstr) i).getResult());

            if (i instanceof CallBase) {
                CallBase call = (CallBase) i;
                Operand o = call.getClosureArg(null);
                if (o != null && o instanceof WrappedIRClosure) {
                    IRClosure cl = ((WrappedIRClosure) o).getClosure();

                    // Only those variables that are defined in the closure, and are in the required loads set
                    // will need to be loaded from the binding after the call!  Rest can wait ..
                    //
                    // Allocate a new hash-set and modify it to get around ConcurrentModificationException on reqdLoads
                    Set<LocalVariable> newReqdLoads = new HashSet<LocalVariable>(reqdLoads);
                    it.next();
                    for (LocalVariable v : reqdLoads) {
                        if (cl.definesLocalVariable(v)) {
                            it.add(new LoadLocalVarInstr(scope, getLocalVarReplacement(v, scope, varRenameMap), v));
                            it.previous();
                            newReqdLoads.remove(v);
                        }
                    }
                    it.previous();
                    reqdLoads = newReqdLoads;
                }

                // In this case, we are going to blindly load everything
                if (scopeBindingHasEscaped || call.targetRequiresCallersBinding()) {
                    it.next();
                    for (LocalVariable v: reqdLoads) {
                        it.add(new LoadLocalVarInstr(scope, getLocalVarReplacement(v, scope, varRenameMap), v));
                        it.previous();
                    }
View Full Code Here

            Instr clonedInstr = i.cloneForInlinedScope(ii);
            if (clonedInstr != null) {
                clonedBB.addInstr(clonedInstr);
                if (clonedInstr instanceof YieldInstr) ii.recordYieldSite(clonedBB, (YieldInstr)clonedInstr);
                if (clonedInstr instanceof CallBase) {
                    CallBase call = (CallBase)clonedInstr;
                    Operand block = call.getClosureArg(null);
                    if (block instanceof WrappedIRClosure) hostScope.addClosure(((WrappedIRClosure)block).getClosure());
                }
            }
        }
View Full Code Here

        for (Instr i: getInstrs()) {
            Instr clonedInstr = i.cloneForInlinedClosure(ii);
            if (clonedInstr != null) {
                clonedBB.addInstr(clonedInstr);
                if (clonedInstr instanceof CallBase) {
                    CallBase call = (CallBase)clonedInstr;
                    Operand block = call.getClosureArg(null);
                    if (block instanceof WrappedIRClosure) hostScope.addClosure(((WrappedIRClosure)block).getClosure());
                }
            }
        }
View Full Code Here

            }

            // Check if 'i' is a call and uses a closure!
            // If so, we need to process the closure for live variable info.
            if (i instanceof CallBase) {
                CallBase c = (CallBase) i;
                Operand  o = c.getClosureArg(null);
                // System.out.println("Processing closure: " + o + "-------");
                if (o != null && o instanceof WrappedIRClosure) {
                    IRClosure cl = ((WrappedIRClosure)o).getClosure();
                    LiveVariablesProblem cl_lvp = (LiveVariablesProblem)cl.getDataFlowSolution(DataFlowConstants.LVP_NAME);
                    if (cl_lvp == null) {
                        cl_lvp = new LiveVariablesProblem(cl, lvp.getNonSelfLocalVars());
                        cl.setDataFlowSolution(cl_lvp.getName(), cl_lvp);
                    }

                    // Collect live local variables at this point.
                    Set<LocalVariable> liveVars = new HashSet<LocalVariable>();
                    for (int j = 0; j < living.size(); j++) {
                        if (living.get(j)) {
                            Variable v = lvp.getVariable(j);
                            if (v instanceof LocalVariable) liveVars.add((LocalVariable)v);
                        }
                    }

                    // Collect variables live on entry of the closure -- they could all be live on exit as well (conservative, but safe).
                    //
                    //   def foo
                    //     i = 0;
                    //     loop { i += 1; break if i > n }
                    //   end
                    //
                    // Here, i is not live outside the closure, but it is clearly live on exit of the closure because
                    // it is reused on the next iteration.  In the absence of information about the call accepting the closure,
                    // we have to assume that all vars live on exit from the closure will be live on entry into the closure as well
                    // because of looping.
                    List<Variable> liveOnEntryBefore = cl_lvp.getVarsLiveOnScopeEntry();
                    for (Variable y: liveOnEntryBefore) {
                        if (y instanceof LocalVariable) liveVars.add((LocalVariable)y);
                    }

                    // Collect variables live out of the exception target node.  Since this call can directly jump to
                    // the rescue block (or scope exit) without executing the rest of the instructions in this bb, we
                    // have a control-flow edge from this call to that block.  Since we dont want to add a
                    // control-flow edge from pretty much every call to the rescuer/exit BB, we are handling it
                    // implicitly here.
                    if (c.canRaiseException()) {
                        BitSet etOut = ((LiveVariableNode)getExceptionTargetNode()).out;
                        for (int k = 0; k < etOut.size(); k++) {
                            if (etOut.get(k)) {
                                Variable v = lvp.getVariable(k);
                                if (v instanceof LocalVariable) liveVars.add((LocalVariable)v);
                            }
                        }
                    }

                    // Run LVA on the closure to propagate current LVA state through the closure
                    // SSS FIXME: Think through this .. Is there any way out of having
                    // to recompute the entire lva for the closure each time through?
                    cl_lvp.setVarsLiveOnScopeExit(liveVars);
                    cl_lvp.compute_MOP_Solution();

                    // Check if liveOnScopeEntry added new vars -- if so, rerun.
                    // NOTE: This is conservative since we are not checking if some vars got deleted.
                    // But, this conservativeness guarantees forward progress of the analysis.
                    boolean changed;
                    List<Variable> liveOnEntryAfter;
                    do {
                        changed = false;
                        liveOnEntryAfter = cl_lvp.getVarsLiveOnScopeEntry();
                        for (Variable y: liveOnEntryAfter) {
                            if (y instanceof LocalVariable) {
                                LocalVariable ly = (LocalVariable)y;
                                if (!liveVars.contains(ly)) {
                                    changed = true;
                                    liveVars.add(ly);
                                }
                            }
                        }

                        if (changed) {
                            cl_lvp.setVarsLiveOnScopeExit(liveVars);
                            cl_lvp.compute_MOP_Solution();
                        }
                    } while (changed);

                    // Merge live on closure entry info into the current problem.
                    markAllVariablesLive(lvp, living, liveOnEntryAfter);
                }

                // If this is a dataflow barrier -- mark all local vars but %self and %block live
                if (scopeBindingHasEscaped || c.targetRequiresCallersBinding()) {
                    // System.out.println(".. call is a data flow barrier ..");
                    // Mark all non-self, non-block local variables live if 'c' is a dataflow barrier!
                    for (Variable x: lvp.getNonSelfLocalVars()) {
                        if (!x.isImplicitBlockArg()) living.set(lvp.getDFVar(x).getId());
                    }
                } else if (c.canRaiseException()) {
                    makeOutExceptionVariablesLiving(living);
                }
            } else if (i.canRaiseException()) {
                makeOutExceptionVariablesLiving(living);
            }
View Full Code Here

            } else {
                // System.out.println("IGNORING! No result!");
            }

            if (i instanceof CallBase) {
                CallBase c = (CallBase) i;
                Operand  o = c.getClosureArg(null);
                if (o != null && o instanceof WrappedIRClosure) {
                    IRClosure cl = ((WrappedIRClosure)o).getClosure();
                    LiveVariablesProblem cl_lvp = (LiveVariablesProblem)cl.getDataFlowSolution(lvp.getName());
                    // Collect variables live on entry and merge that info into the current problem.
                    markAllVariablesLive(lvp, living, cl_lvp.getVarsLiveOnScopeEntry());
                } else if (scopeBindingHasEscaped || c.targetRequiresCallersBinding()) {
                    // Mark all non-self, non-block local variables live if 'c' is a dataflow barrier!
                    for (Variable x: lvp.getNonSelfLocalVars()) {
                        if (!x.isImplicitBlockArg()) living.set(lvp.getDFVar(x).getId());
                    }
                } else if (c.canRaiseException()) {
                    makeOutExceptionVariablesLiving(living);
                }
            } else if (i.canRaiseException()) {
                makeOutExceptionVariablesLiving(living);
            }
View Full Code Here

                receivesClosureArg = true;
            } else if (op == Operation.ZSUPER) {
                this.canCaptureCallersBinding = true;
                this.usesZSuper = true;
            } else if (i instanceof CallBase) {
                CallBase call = (CallBase) i;

                if (call.targetRequiresCallersBinding()) this.bindingHasEscaped = true;

                if (call.canBeEval()) {
                    this.usesEval = true;

                    // If this method receives a closure arg, and this call is an eval that has more than 1 argument,
                    // it could be using the closure as a binding -- which means it could be using pretty much any
                    // variable from the caller's binding!
                    if (receivesClosureArg && (call.getCallArgs().length > 1)) {
                        this.canCaptureCallersBinding = true;
                    }
                }
            } else if (op == Operation.GET_GLOBAL_VAR) {
                GlobalVariable gv = (GlobalVariable)((GetGlobalVariableInstr)i).getSource();
View Full Code Here

            hs = isHotClosure ? hs.getLexicalParent() : hs;
            for (BasicBlock b : hs.getCFG().getBasicBlocks()) {
                for (Instr instr : b.getInstrs()) {
                    if ((instr instanceof CallBase) && !((CallBase)instr).inliningBlocked()) {
                        // System.out.println("checking: " + instr);
                        CallBase call = (CallBase)instr;
                        CallSite cs = call.getCallSite();
                        // System.out.println("callsite: " + cs);
                        if (cs != null && (cs instanceof CachingCallSite)) {
                            CachingCallSite ccs = (CachingCallSite)cs;
                            // SSS FIXME: To use this, CachingCallSite.java needs modification
                            // isPolymorphic or something equivalent needs to be enabled there.
                            if (ccs.isOptimizable()) {
                                CacheEntry ce = ccs.getCache();
                                DynamicMethod tgt = ce.method;
                                if (tgt instanceof InterpretedIRMethod) {
                                    InterpretedIRMethod dynMeth = (InterpretedIRMethod)tgt;
                                    IRScope tgtMethod = dynMeth.getIRMethod();
                                    Instr[] instrs = tgtMethod.getInstrsForInterpretation();
                                    // Dont inline large methods -- 200 is arbitrary
                                    // Can be null if a previously inlined method hasn't been rebuilt
                                    if ((instrs == null) || instrs.length > 150) continue;

                                    RubyModule implClass = dynMeth.getImplementationClass();
                                    int classToken = implClass.getGeneration();
                                    String n = tgtMethod.getName();
                                    boolean inlineCall = false;
                                    if (isHotClosure) {
                                        Operand clArg = call.getClosureArg(null);
                                        inlineCall = (clArg instanceof WrappedIRClosure) && (((WrappedIRClosure)clArg).getClosure() == hc);
                                    } else if (hotScopes.contains(tgtMethod)) {
                                        inlineCall = true;
                                    }
View Full Code Here

TOP

Related Classes of org.jruby.ir.instructions.CallBase

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.