Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.ir.instructions;
  
  import org.jruby.Ruby;
  import org.jruby.RubyProc;
 
 import java.util.List;
 import java.util.Map;
 
 public abstract class CallBase extends Instr implements Specializeable {
     private static long callSiteCounter = 1;
 
     public final long callSiteId;
     protected Operand   receiver;
     protected Operand[] arguments;
     protected Operand   closure;
     protected MethAddr methAddr;
     protected CallSite callSite;
     private final CallType callType;
 
     private boolean flagsComputed;
     private boolean canBeEval;
     private boolean targetRequiresCallersBinding;    // Does this call make use of the caller's binding?
     public HashMap<DynamicMethodIntegerprofile;
     private boolean dontInline;
     private boolean containsSplat;
 
     protected CallBase(Operation opCallType callTypeMethAddr methAddrOperand receiverOperand[] argsOperand closure) {
         super(op);
 
         this. = ++;
         this. = receiver;
         this. = args;
         this. = closure;
         this. = methAddr;
         this. = callType;
         this. = getCallSiteFor(callTypemethAddr);
          = containsSplat(args);
          = false;
          = true;
          = true;
          = false;
 
     }
 
     public Operand[] getOperands() {
         return buildAllArgs(getMethodAddr(), );
     }
 
     public MethAddr getMethodAddr() {
         return ;
     }
 
     public Operand getClosureArg(Operand ifUnspecified) {
         return  == null ? ifUnspecified : ;
     }
 
     public Operand getReceiver() {
         return ;
     }
 
     public Operand[] getCallArgs() {
         return ;
     }
 
     public CallSite getCallSite() {
         return ;
     }
 
     public CallType getCallType() {
         return ;
     }
 
     public void blockInlining() {
          = true;
     }
 
     public boolean inliningBlocked() {
        return ;
    }
    private static CallSite getCallSiteFor(CallType callTypeMethAddr methAddr) {
        assert callType != null"Calltype should never be null";
        String name = methAddr.getName();
        switch (callType) {
            case return MethodIndex.getCallSite(name);
            case return MethodIndex.getFunctionalCallSite(name);
            case return MethodIndex.getVariableCallSite(name);
            case return MethodIndex.getSuperCallSite();
            case :
        }
        return null// fallthrough for unknown
    }
    public boolean hasClosure() {
        return  != null;
    }
    public boolean isAllConstants() {
        for (int i = 0; i < .i++) {
            if (!([iinstanceof ImmutableLiteral)) return false;
        }
        return true;
    }
    public boolean isAllFixnums() {
        for (int i = 0; i < .i++) {
            if (!([iinstanceof Fixnum)) return false;
        }
        return true;
    }

    
Interpreter can ask the instruction if it knows how to make a more efficient instruction for direct interpretation.

Returns:
itself or more efficient but semantically equivalent instr
        return this;
    }
    @Override
    public void simplifyOperands(Map<OperandOperandvalueMapboolean force) {
        // FIXME: receiver should never be null (checkArity seems to be one culprit)
        if ( != null = .getSimplifiedOperand(valueMapforce);
         = (MethAddr).getSimplifiedOperand(valueMapforce);
        for (int i = 0; i < .i++) {
            [i] = [i].getSimplifiedOperand(valueMapforce);
        }
        // Recompute containsSplat flag
        if ( != null = .getSimplifiedOperand(valueMapforce);
         = false// Forces recomputation of flags
        // recompute whenever instr operands change! (can this really change though?)
    }
    public Operand[] cloneCallArgs(InlinerInfo ii) {
        int i = 0;
        Operand[] clonedArgs = new Operand[.];
        for (Operand a) {
            clonedArgs[i++] = a.cloneForInlining(ii);
        }
        return clonedArgs;
    }
    public boolean isRubyInternalsCall() {
        return false;
    }
    public boolean isStaticCallTarget() {
        return false;
    }
    // SSS: Unused method
    // Can this call lead to ruby code getting modified?
    // If we don't know what method we are calling, we assume it can (pessimistic, but safe!)
    public boolean canModifyCode() {
        return true;
    }
    // SSS FIXME: Are all bases covered?
    // How about aliasing of 'call', 'eval', 'send', 'module_eval', 'class_eval', 'instance_eval'?
    private boolean getEvalFlag() {
        // ENEBO: This could be made into a recursive two-method thing so then: send(:send, :send, :send, :send, :eval, "Hosed") works
        String mname = getMethodAddr().getName();
        // checking for "call" is conservative.  It can be eval only if the receiver is a Method
        if (mname.equals("call") || mname.equals("eval") || mname.equals("module_eval") || mname.equals("class_eval") || mname.equals("instance_eval")) return true;
        // Calls to 'send' where the first arg is either unknown or is eval or send (any others?)
        if (mname.equals("send") || mname.equals("__send__")) {
            Operand[] args = getCallArgs();
            if (args.length >= 2) {
                Operand meth = args[0];
                if (!(meth instanceof StringLiteral)) return true// We don't know
                String name = ((StringLiteralmeth).;
                if (   name.equals("call")
                    || name.equals("eval")
                    || mname.equals("module_eval")
                    || mname.equals("class_eval")
                    || mname.equals("instance_eval")
                    || name.equals("send")
                    || name.equals("__send__")) return true;
            }
        }
        return false// All checks passed
    }
    private boolean computeRequiresCallersBindingFlag() {
        if (canBeEval()) return true;
        // Conservative -- assuming that the callee will save the closure
        // and use it at a later point.
        if ( != nullreturn true;
        String mname = getMethodAddr().getName();
        if (mname.equals("lambda")) {
            return true;
SSS: Not required currently. You cannot Proc.new without passing it a closure which means it will be captured by the check earlier. } else if (mname.equals("new")) { Operand object = getReceiver(); // SSS FIXME: This check is incorrect -- something has gone // wrong with the numerous fixes to IR code since this check was written. // // Unknown receiver -- could be Proc!! if (!(object instanceof CurrentScope)) return true; IRScope c = ((CurrentScope) object).getScope(); if (c != null && c instanceof IRClassBody && c.getName().equals("Proc")) return true;
        } else if (mname.equals("binding")) {
            return true;
        } else if (mname.equals("send") || mname.equals("__send__")) {
            Operand[] args = getCallArgs();
            if (args.length >= 1) {
                Operand meth = args[0];
                if (!(meth instanceof StringLiteral)) return true// We don't know -- could be "binding"
                String name = ((StringLiteralmeth).;
                if (name.equals("binding")) return true;
            }
        }
        // SSS FIXME: Are all bases covered?  What about aliases?
        return false;  // All checks done -- dont need one
    }
    private void computeFlags() {
        // Order important!
         = true;
         = getEvalFlag();
    }
    public boolean canBeEval() {
        if (!computeFlags();
        return ;
    }
    public boolean targetRequiresCallersBinding() {
        if (!computeFlags();
        return ;
    }
    // Regexp and IO calls can do this -- and since we do not know at IR-build time
    // what the call target is, we have to conservatively assume yes
    public boolean canSetDollarVars() {
        return true;
    }
    @Override
    public String toString() {
        return "" + getOperation()  + "(" +  + ", " + getMethodAddr() + ", " +  +
                ", " + Arrays.toString(getCallArgs()) +
                ( == null ? "" : ", &" + ) + ")";
    }
    protected static boolean containsSplat(Operand[] arguments) {
        for (int i = 0; i < arguments.lengthi++) {
            if (arguments[iinstanceof Splatreturn true;
        }
        return false;
    }
    private static Operand[] buildAllArgs(Operand methAddrOperand receiverOperand[] callArgsOperand closure) {
        Operand[] allArgs = new Operand[callArgs.length + 2 + ((closure != null) ? 1 : 0)];
        assert methAddr != null : "METHADDR is null";
        assert receiver != null : "RECEIVER is null";
        allArgs[0] = methAddr;
        allArgs[1] = receiver;
        for (int i = 0; i < callArgs.lengthi++) {
            assert callArgs[i] != null : "ARG " + i + " is null";
            allArgs[i + 2] = callArgs[i];
        }
        if (closure != nullallArgs[callArgs.length + 2] = closure;
        return allArgs;
    }
    @Override
    public Object interpret(ThreadContext contextDynamicScope dynamicScopeIRubyObject selfObject[] tempBlock block) {
        IRubyObject object = (IRubyObject.retrieve(contextselfdynamicScopetemp);
        IRubyObject[] values = prepareArguments(contextselfdynamicScopetemp);
        Block preparedBlock = prepareBlock(contextselfdynamicScopetemp);
        return .call(contextselfobjectvaluespreparedBlock);
    }
    protected IRubyObject[] prepareArguments(ThreadContext contextIRubyObject selfOperand[] argumentsDynamicScope dynamicScopeObject[] temp) {
        return  ?
                prepareArgumentsComplex(contextselfargumentsdynamicScopetemp) :
                prepareArgumentsSimple(contextselfargumentsdynamicScopetemp);
    }
    protected IRubyObject[] prepareArgumentsSimple(ThreadContext contextIRubyObject selfOperand[] argsDynamicScope currDynScopeObject[] temp) {
        IRubyObject[] newArgs = new IRubyObject[args.length];
        for (int i = 0; i < args.lengthi++) {
            newArgs[i] = (IRubyObjectargs[i].retrieve(contextselfcurrDynScopetemp);
        }
        return newArgs;
    }
    protected IRubyObject[] prepareArgumentsComplex(ThreadContext contextIRubyObject selfOperand[] argsDynamicScope currDynScopeObject[] temp) {
        // SSS: For regular calls, IR builder never introduces splats except as the first argument
        // But when zsuper is converted to SuperInstr with known args, splats can appear anywhere
        // in the list.  So, this looping handles both these scenarios, although if we wanted to
        // optimize for CallInstr which has splats only in the first position, we could do that.
        List<IRubyObjectargList = new ArrayList<IRubyObject>();
        for (int i = 0; i < args.lengthi++) {
            IRubyObject rArg = (IRubyObject)args[i].retrieve(contextselfcurrDynScopetemp);
            if (args[iinstanceof Splat) {
                argList.addAll(Arrays.asList(((RubyArray)rArg).toJavaArray()));
            } else {
                argList.add(rArg);
            }
        }
        return argList.toArray(new IRubyObject[argList.size()]);
    }
    protected Block prepareBlock(ThreadContext contextIRubyObject selfDynamicScope currDynScopeObject[] temp) {
        if ( == nullreturn .;
        Object value = .retrieve(contextselfcurrDynScopetemp);
        Block block;
        if (value instanceof Block) {
            block = (Blockvalue;
        } else if (value instanceof RubyProc) {
            block = ((RubyProcvalue).getBlock();
        } else if (value instanceof RubyMethod) {
            block = ((RubyProc)((RubyMethod)value).to_proc(contextnull)).getBlock();
        } else if ((value instanceof IRubyObject) && ((IRubyObject)value).isNil()) {
            block = .;
        } else if (value instanceof IRubyObject) {
            block = ((RubyProc)TypeConverter.convertToType((IRubyObject)valuecontext.runtime.getProc(), "to_proc"true)).getBlock();
        } else {
            throw new RuntimeException("Unhandled case in CallInstr:prepareBlock.  Got block arg: " + value);
        }
        // ENEBO: This came from duplicated logic from SuperInstr....
        // Blocks passed in through calls are always normal blocks, no matter where they came from
        block.type = ..;
        return block;
    }
New to GrepCode? Check out our FAQ X