private boolean computeRequiresCallersFrameFlag() { if (canBeEval()) return true; // literal closures can be used to capture surrounding binding if (hasLiteralClosure()) return true; if (procNew) return true; String mname = getId(); if (frameReads.size() > 0 || frameWrites.size() > 0) { // Known frame-aware methods. return true; } else if (potentiallySend(mname, argsCount)) { Operand meth = getArg1(); String name; if (meth instanceof Stringable) { name = ((Stringable) meth).getString(); } else { return true; // We don't know -- could be anything } frameReads = MethodIndex.METHOD_FRAME_READS.getOrDefault(name, Collections.EMPTY_SET); frameWrites = MethodIndex.METHOD_FRAME_WRITES.getOrDefault(name, Collections.EMPTY_SET); if (frameReads.size() > 0 || frameWrites.size() > 0) { return true; } } return false; }
public boolean canBeEval() { if (!flagsComputed) computeFlags(); return canBeEval; }
private void computeFlags() { // Order important! flagsComputed = true; canBeEval = computeEvalFlag(); targetRequiresCallersBinding = canBeEval || computeRequiresCallersBindingFlag(); targetRequiresCallersFrame = canBeEval || computeRequiresCallersFrameFlag(); }
private void computeFlags() { // Order important! flagsComputed = true; canBeEval = getEvalFlag(); targetRequiresCallersBinding = canBeEval ? true : computeRequiresCallersBindingFlag(); }
protected CallBase(Operation op, CallType callType, MethAddr methAddr, Operand receiver, Operand[] args, Operand closure) { super(op); this.callSiteId = callSiteCounter++; this.receiver = receiver; this.arguments = args; this.closure = closure; this.methAddr = methAddr; this.callType = callType; this.callSite = getCallSiteFor(callType, methAddr); containsSplat = containsSplat(args); flagsComputed = false; canBeEval = true; targetRequiresCallersBinding = true; dontInline = false; }
String m = c.getId(); Operand r = c.getReceiver(); if (dst != null && c.getArgsCount() == 1 && problem.isUnboxableMethod(m)) { Operand a = c.getArg1(); Class receiverType = getOperandType(tmpState, r); Class argType = getOperandType(tmpState, a); tmpState.unboxedVars.put((Variable)a, unboxedType); } else if (c.targetRequiresCallersBinding()) { hitDFBarrier = true;
@Override public void encode(IRWriterEncoder e) { super.encode(e); e.encode(getCallType().ordinal()); e.encode(getName()); e.encode(getReceiver()); e.encode(calculateArity()); for (Operand arg: getCallArgs()) { e.encode(arg); } if (hasClosure) e.encode(getClosureArg(null)); }
private void compileCallCommon(IRBytecodeAdapter m, CallBase call) { Operand[] args = call.getCallArgs(); BlockPassType blockPassType = BlockPassType.fromIR(call); m.loadContext(); visit(call.getReceiver()); int arity = args.length; m.adapter.invokevirtual(p(RubyArray.class), "toJavaArray", sig(IRubyObject[].class)); arity = -1; } else if (CallBase.containsArgSplat(args)) { throw new NotCompilableException("splat in non-initial argument for normal call is unsupported in JIT"); } else { visit(call.getClosureArg()); m.invokeIRHelper("getBlockFromObject", sig(Block.class, ThreadContext.class, Object.class)); switch (call.getCallType()) { case FUNCTIONAL: case VARIABLE: Variable result = call.getResult(); if (result != null) { jvmStoreLocal(result);
if (targetRequiresCallersBinding()) { modifiedScope = true; flags.add(BINDING_HAS_ESCAPED); modifiedScope |= setIRFlagsFromFrameFields(flags, frameReads); modifiedScope |= setIRFlagsFromFrameFields(flags, frameWrites); if (hasLiteralClosure()) { modifiedScope = true; flags.addAll(IRFlags.REQUIRE_ALL_FRAME_FIELDS); if (canBeEval()) { modifiedScope = true; flags.add(USES_EVAL); if (potentiallySend(getId(), argsCount)) { // ok to look at raw string since we know we are looking for 7bit names. Operand meth = getArg1(); if (meth instanceof StringLiteral) {
if (calledScopes.size() == 1 && !call.inliningBlocked()) { CallSite runtimeCS = call.getCallSite(); if (runtimeCS != null && (runtimeCS instanceof CachingCallSite)) { CachingCallSite ccs = (CachingCallSite)runtimeCS; boolean inlineCall = true; if (isHotClosure) { Operand clArg = call.getClosureArg(null); inlineCall = (clArg instanceof WrappedIRClosure) && (((WrappedIRClosure)clArg).getClosure() == hc);
CallBase call = (CallBase) i; Operand o = call.getClosureArg(null); if (o != null && o instanceof WrappedIRClosure) { boolean spillAllVars = scopeBindingHasEscaped || call.targetRequiresCallersBinding(); } else if (scopeBindingHasEscaped || call.targetRequiresCallersBinding()) { // Call has no closure && it requires stores dirtyVars.clear(); } else {
BasicBlock dstBB = ii.getRenamedBB(destination); if (!ii.canMapArgsStatically()) { dstBB.addInstr(new ToAryInstr((Variable)ii.getArgs(), new Array(call.getCallArgs()), cfg.getScope().getManager().getTrue())); callBB.addInstr(new ModuleVersionGuardInstr(implClass, classToken, call.getReceiver(), failurePathLabel)); failurePathBB.addInstr(call); failurePathBB.addInstr(new JumpInstr(splitBBLabel)); call.blockInlining(); Operand closureArg = call.getClosureArg(null); List yieldSites = ii.getYieldSites(); if (closureArg != null && !yieldSites.isEmpty()) {
Operand o = c.getClosureArg(null); if (c.canRaiseException()) { BitSet etOut = ((LiveVariableNode)getExceptionTargetNode()).out; for (int k = 0; k < etOut.size(); k++) { if (scopeBindingHasEscaped || c.targetRequiresCallersBinding()) { if (!x.isImplicitBlockArg()) living.set(lvp.getDFVar(x).getId()); } else if (c.canRaiseException()) { makeOutExceptionVariablesLiving(living);
@Override public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope dynamicScope, IRubyObject self, Object[] temp) { IRubyObject object = (IRubyObject) getReceiver().retrieve(context, self, currScope, dynamicScope, temp); IRubyObject[] values = prepareArguments(context, self, currScope, dynamicScope, temp); Block preparedBlock = prepareBlock(context, self, currScope, dynamicScope, temp); if (hasLiteralClosure()) { return callSite.callIter(context, self, object, values, preparedBlock); } return callSite.call(context, self, object, values, preparedBlock); }
CallBase call = (CallBase) i; if (call.targetRequiresCallersBinding()) this.bindingHasEscaped = true; if (call.canBeEval()) { this.usesEval = true; if (receivesClosureArg && (call.getCallArgs().length > 1)) { this.canCaptureCallersBinding = true;
Variable callReceiverVar = getReceiverVariable(call.getReceiver()); InlineCloneInfo ii = new InlineCloneInfo(call, cfg, callReceiverVar, scopeToInline); if (call.getReceiver() != callReceiverVar) { dstBB.insertInstr(new CopyInstr(callReceiverVar, call.getReceiver())); beforeInlineBB.addInstr(new ModuleVersionGuardInstr(implClass, classToken, call.getReceiver(), failurePathLabel)); call.blockInlining(); Operand closureArg = call.getClosureArg(null); List yieldSites = ii.getYieldSites(); if (closureArg != null && !yieldSites.isEmpty()) {
public Operand getClosureArg(Operand ifUnspecified) { return hasClosure ? getClosureArg() : ifUnspecified; }
protected CallBase(IRScope scope, Operation op, CallType callType, RubySymbol name, Operand receiver, Operand[] args, Operand closure, boolean potentiallyRefined, CallSite callSite, long callSiteId) { super(op, arrayifyOperands(receiver, args, closure)); this.callSiteId = callSiteId; argsCount = args.length; hasClosure = closure != null; this.name = name; this.callType = callType; this.callSite = callSite == null ? getCallSiteFor(scope, callType, name.idString(), callSiteId, hasLiteralClosure(), potentiallyRefined) : callSite; splatMap = IRRuntimeHelpers.buildSplatMap(args); flagsComputed = false; canBeEval = true; targetRequiresCallersBinding = true; targetRequiresCallersFrame = true; dontInline = false; procNew = false; this.potentiallyRefined = potentiallyRefined; captureFrameReadsAndWrites(); }
private boolean computeRequiresCallersBindingFlag() { if (canBeEval()) return true; String mname = getMethodAddr().getName(); if (mname.equals("lambda")) { return true; return true; } else if (mname.equals("send") || mname.equals("__send__")) { Operand[] args = getCallArgs(); if (args.length >= 1) { Operand meth = args[0];
@Override public String toString() { return "" + getOperation() + "(" + callType + ", " + getMethodAddr() + ", " + receiver + ", " + Arrays.toString(getCallArgs()) + (closure == null ? "" : ", &" + closure) + ")"; }