// // This can help use eliminate writes to %block that are not used since this is // a special local-variable, not programmer-defined local-variable public void computeScopeFlags() { if (flagsComputed) { return; } // init canModifyCode = true; canCaptureCallersBinding = false; usesZSuper = false; usesEval = false; usesBackrefOrLastline = false; // NOTE: bindingHasEscaped is the crucial flag and it effectively is // unconditionally true whenever it has a call that receives a closure. // See CallInstr.computeRequiresCallersBindingFlag bindingHasEscaped = (this instanceof IREvalScript); // for eval scopes, bindings are considered escaped ... hasBreakInstrs = false; hasNonlocalReturns = false; canReceiveBreaks = false; canReceiveNonlocalReturns = false; // recompute flags -- we could be calling this method different times // definitely once after ir generation and local optimizations propagates constants locally // but potentially at a later time after doing ssa generation and constant propagation if (cfg == null) { computeScopeFlags(false, getInstrs()); } else { boolean receivesClosureArg = false; for (BasicBlock b : cfg.getBasicBlocks()) { receivesClosureArg = computeScopeFlags(receivesClosureArg, b.getInstrs()); } } // Compute flags for nested closures (recursively) and set derived flags. for (IRClosure cl : getClosures()) { cl.computeScopeFlags(); if (cl.hasBreakInstrs || cl.canReceiveBreaks) { canReceiveBreaks = true; } if (cl.hasNonlocalReturns || cl.canReceiveNonlocalReturns) { canReceiveNonlocalReturns = true; } if (cl.usesZSuper()) { usesZSuper = true; } } flagsComputed = true; }