@Override public Object execute(VirtualFrame frame) { while (true) { getContext().getSafepointManager().poll(); Object result; try { result = tryPart.execute(frame); } catch (ControlFlowException exception) { controlFlowProfile.enter(); throw exception; } catch (RaiseException exception) { raiseExceptionProfile.enter(); try { return handleException(frame, exception); } catch (RetryException e) { continue; } } finally { clearExceptionVariableNode.execute(frame); } elseProfile.enter(); elsePart.executeVoid(frame); return result; } }
// TODO Figure out how to distinguish f(,,a) from f(a) - RMissing is used in both contexts @RBuiltin( name = "nargs", kind = PRIMITIVE, parameterNames = {}) public abstract class NArgs extends RBuiltinNode { private final BranchProfile isPromiseProfile = BranchProfile.create(); @Specialization protected int doNArgs(VirtualFrame frame) { int result = 0; if (RArguments.getFunction(frame) == null) { return RRuntime.INT_NA; } int l = RArguments.getArgumentsLength(frame); for (int i = 0; i < l; i++) { Object arg = RArguments.getArgument(frame, i); if (arg instanceof RPromise) { isPromiseProfile.enter(); RPromise promise = (RPromise) arg; if (!promise.isDefault()) { result++; } } else if (arg instanceof RArgsValuesAndNames) { result += ((RArgsValuesAndNames) arg).getLength(); } else if (!(arg instanceof RMissing)) { result++; } } return result; } }
@Override public Object execute(VirtualFrame frame) { if (CompilerDirectives.injectBranchProbability( getBranchProbability(), condition.executeBoolean(frame))) { if (CompilerDirectives.inInterpreter()) { thenCount++; } thenProfile.enter(); return thenBody.execute(frame); } else { if (CompilerDirectives.inInterpreter()) { elseCount++; } elseProfile.enter(); return elseBody.execute(frame); } }
@Override public Object execute(VirtualFrame frame) { if (RubyArguments.getUserArgumentsCount(frame.getArguments()) < minimum) { defaultValueProfile.enter(); return defaultValue.execute(frame); } else { return RubyArguments.getUserArgument(frame.getArguments(), index); } }
@Specialization public Object callNamedFunctionWithPackage( String name, RArgsValuesAndNames args, String packageName) { controlVisibility(); SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName); if (symbolInfo == null) { errorProfile.enter(); throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name); } return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall(symbolInfo.address, symbolInfo.symbol, args.getArguments()); }
@Specialization public Object callNamedFunctionWithPackage( String name, RArgsValuesAndNames args, String packageName) { controlVisibility(); SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName); if (symbolInfo == null) { errorProfile.enter(); throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name); } Object list = encodeArgumentPairList(args, symbolInfo.symbol); // TODO: provide proper values for the CALL, OP and RHO parameters return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall(symbolInfo.address, symbolInfo.symbol, new Object[] {CALL, OP, list, RHO}); }
@Specialization protected RList c( String f, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") RMissing rPackage, @SuppressWarnings("unused") RMissing encoding, // @Cached("create()") BranchProfile errorProfile) { controlVisibility(); SymbolInfo symbolInfo = DLL.findRegisteredSymbolinInDLL(f, null, ""); if (symbolInfo == null) { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, f); } return DotC.dispatch( this, symbolInfo.address, symbolInfo.symbol, naok, dup, args.getArguments()); }
@Override public Object execute(VirtualFrame frame) { while (true) { try { final Object result = tryPart.execute(frame); elsePart.executeVoid(frame); return result; } catch (ControlFlowException exception) { controlFlowProfile.enter(); throw exception; } catch (RuntimeException exception) { CompilerDirectives.transferToInterpreter(); try { return handleException(frame, exception); } catch (RetryException e) { continue; } } } }
@Specialization protected int doNArgs(VirtualFrame frame) { int result = 0; if (RArguments.getFunction(frame) == null) { return RRuntime.INT_NA; } int l = RArguments.getArgumentsLength(frame); for (int i = 0; i < l; i++) { Object arg = RArguments.getArgument(frame, i); if (arg instanceof RPromise) { isPromiseProfile.enter(); RPromise promise = (RPromise) arg; if (!promise.isDefault()) { result++; } } else if (arg instanceof RArgsValuesAndNames) { result += ((RArgsValuesAndNames) arg).getLength(); } else if (!(arg instanceof RMissing)) { result++; } } return result; }
@RBuiltin( name = ".Call.graphics", kind = RBuiltinKind.PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}) public abstract static class DotCallGraphics extends LookupAdapter { private final BranchProfile errorProfile = BranchProfile.create(); @Override public Object[] getDefaultParameterValues() { return new Object[] {RMissing.instance, RArgsValuesAndNames.EMPTY, RMissing.instance}; } @Override protected RExternalBuiltinNode lookupBuiltin(RList f) { switch (lookupName(f)) { default: return null; } } @SuppressWarnings("unused") @Specialization( limit = "1", guards = {"cached == f", "builtin != null"}) protected Object doExternal( RList f, RArgsValuesAndNames args, RMissing packageName, // @Cached("f") RList cached, // @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) { controlVisibility(); return builtin.call(args); } @Specialization public Object callNamedFunction( VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall( getAddressFromSymbolInfo(frame, symbol), getNameFromSymbolInfo(frame, symbol), args.getArguments()); } @Specialization public Object callNamedFunction( String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) { return callNamedFunctionWithPackage(name, args, null); } @Specialization public Object callNamedFunctionWithPackage( String name, RArgsValuesAndNames args, String packageName) { controlVisibility(); SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName); if (symbolInfo == null) { errorProfile.enter(); throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name); } return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall(symbolInfo.address, symbolInfo.symbol, args.getArguments()); } @Fallback protected Object dotCallFallback( Object fobj, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) { throw fallback(fobj); } }
@RBuiltin( name = ".External.graphics", kind = RBuiltinKind.PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}) public abstract static class DotExternalGraphics extends LookupAdapter { private final BranchProfile errorProfile = BranchProfile.create(); @Override protected RExternalBuiltinNode lookupBuiltin(RList f) { if (FastROptions.UseInternalGraphics.getBooleanValue()) { switch (lookupName(f)) { case "C_mtext": return new GraphicsCCalls.C_mtext(); case "C_plotXY": return new C_PlotXY(); } } return null; } @SuppressWarnings("unused") @Specialization( limit = "1", guards = {"cached == f", "builtin != null"}) protected Object doExternal( RList f, RArgsValuesAndNames args, RMissing packageName, // @Cached("f") RList cached, // @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) { controlVisibility(); return builtin.call(args); } @Specialization public Object callNamedFunction( VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { String name = getNameFromSymbolInfo(frame, symbol); Object list = encodeArgumentPairList(args, name); return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall(getAddressFromSymbolInfo(frame, symbol), name, new Object[] {list}); } @Specialization public Object callNamedFunction( String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) { return callNamedFunctionWithPackage(name, args, null); } @Specialization public Object callNamedFunctionWithPackage( String name, RArgsValuesAndNames args, String packageName) { controlVisibility(); SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName); if (symbolInfo == null) { errorProfile.enter(); throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name); } Object list = encodeArgumentPairList(args, symbolInfo.symbol); return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall(symbolInfo.address, symbolInfo.symbol, new Object[] {list}); } @Fallback protected Object fallback( Object f, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) { throw fallback(f); } }
@RBuiltin( name = ".External2", kind = RBuiltinKind.PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}) public abstract static class DotExternal2 extends LookupAdapter { private static final Object CALL = "call"; private static final Object OP = "op"; private static final Object RHO = "rho"; private final BranchProfile errorProfile = BranchProfile.create(); @Override protected RExternalBuiltinNode lookupBuiltin(RList f) { if (FastROptions.UseInternalGraphics.getBooleanValue()) { switch (lookupName(f)) { case "C_par": return new C_Par(); } } String name = lookupName(f); switch (name) { // tools case "writetable": return new WriteTable(); case "typeconvert": return TypeConvertNodeGen.create(); case "C_parseRd": return C_ParseRdNodeGen.create(); default: return null; } } @SuppressWarnings("unused") @Specialization( limit = "1", guards = {"cached == f", "builtin != null"}) protected Object doExternal( RList f, RArgsValuesAndNames args, RMissing packageName, // @Cached("f") RList cached, // @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) { controlVisibility(); return builtin.call(args); } @Specialization public Object callNamedFunction( VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { String name = getNameFromSymbolInfo(frame, symbol); Object list = encodeArgumentPairList(args, name); // TODO: provide proper values for the CALL, OP and RHO parameters return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall( getAddressFromSymbolInfo(frame, symbol), name, new Object[] {CALL, OP, list, RHO}); } @Specialization public Object callNamedFunction( String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) { return callNamedFunctionWithPackage(name, args, null); } @Specialization public Object callNamedFunctionWithPackage( String name, RArgsValuesAndNames args, String packageName) { controlVisibility(); SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName); if (symbolInfo == null) { errorProfile.enter(); throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name); } Object list = encodeArgumentPairList(args, symbolInfo.symbol); // TODO: provide proper values for the CALL, OP and RHO parameters return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall(symbolInfo.address, symbolInfo.symbol, new Object[] {CALL, OP, list, RHO}); } @Fallback protected Object fallback( Object f, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) { throw fallback(f); } }
@RBuiltin( name = ".External", kind = RBuiltinKind.PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}) public abstract static class DotExternal extends LookupAdapter { private final BranchProfile errorProfile = BranchProfile.create(); @Override protected RExternalBuiltinNode lookupBuiltin(RList f) { String name = lookupName(f); if (FastROptions.UseInternalGraphics.getBooleanValue()) { switch (name) { case "PDF": return new DevicesCCalls.C_PDF(); case "devoff": return new DevicesCCalls.C_DevOff(); case "devcur": return new DevicesCCalls.C_DevCur(); } } switch (name) { case "compcases": return new CompleteCases(); // utils case "countfields": return new CountFields(); case "readtablehead": return new ReadTableHead(); case "rnorm": return RnormNodeGen.create(); case "runif": return RunifNodeGen.create(); case "qgamma": return QgammaNodeGen.create(); case "download": return new Download(); case "unzip": case "Rprof": case "Rprofmem": case "addhistory": case "loadhistory": case "savehistory": case "dataentry": case "dataviewer": case "edit": case "fileedit": case "selectlist": return new UnimplementedExternal(name); default: return null; } } @SuppressWarnings("unused") @Specialization( limit = "1", guards = {"cached == f", "builtin != null"}) protected Object doExternal( RList f, RArgsValuesAndNames args, RMissing packageName, // @Cached("f") RList cached, // @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) { controlVisibility(); return builtin.call(args); } @Specialization public Object callNamedFunction( VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { String name = getNameFromSymbolInfo(frame, symbol); Object list = encodeArgumentPairList(args, name); return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall(getAddressFromSymbolInfo(frame, symbol), name, new Object[] {list}); } @Specialization public Object callNamedFunction( String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) { return callNamedFunctionWithPackage(name, args, null); } @Specialization public Object callNamedFunctionWithPackage( String name, RArgsValuesAndNames args, String packageName) { controlVisibility(); SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName); if (symbolInfo == null) { errorProfile.enter(); throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name); } Object list = encodeArgumentPairList(args, symbolInfo.symbol); return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall(symbolInfo.address, symbolInfo.symbol, new Object[] {list}); } @Fallback protected Object fallback( Object f, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) { throw fallback(f); } }
/** * Handles the generic case, but also many special case functions that are called from the default * packages. */ @RBuiltin( name = ".Call", kind = RBuiltinKind.PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}) public abstract static class DotCall extends LookupAdapter { private final BranchProfile errorProfile = BranchProfile.create(); @Override public Object[] getDefaultParameterValues() { return new Object[] {RMissing.instance, RArgsValuesAndNames.EMPTY, RMissing.instance}; } @Override protected RExternalBuiltinNode lookupBuiltin(RList f) { String name = lookupName(f); switch (name) { // methods case "R_initMethodDispatch": return R_initMethodDispatchNodeGen.create(); case "R_methodsPackageMetaName": return R_methodsPackageMetaNameNodeGen.create(); case "R_set_method_dispatch": return R_set_method_dispatchNodeGen.create(); case "R_M_setPrimitiveMethods": return R_M_setPrimitiveMethodsNodeGen.create(); case "R_getClassFromCache": return R_getClassFromCacheNodeGen.create(); case "R_clear_method_selection": case "R_dummy_extern_place": case "R_el_named": return new UnimplementedExternal(name); case "R_externalptr_prototype_object": return R_externalPtrPrototypeObjectNodeGen.create(); case "R_getGeneric": return R_getGenericNodeGen.create(); case "R_get_slot": return R_getSlotNodeGen.create(); case "R_hasSlot": return new UnimplementedExternal(name); case "R_identC": return R_identCNodeGen.create(); case "R_methods_test_MAKE_CLASS": case "R_methods_test_NEW": case "R_missingArg": case "R_nextMethodCall": return R_nextMethodCallNodeGen.create(); case "R_quick_method_check": case "R_selectMethod": case "R_set_el_named": return new UnimplementedExternal(name); case "R_set_slot": return R_setSlotNodeGen.create(); case "R_standardGeneric": return new UnimplementedExternal(name); case "do_substitute_direct": return SubstituteDirectNodeGen.create(); case "Rf_allocS4Object": case "R_get_primname": return new UnimplementedExternal(name); case "new_object": return NewObjectNodeGen.create(); // stats case "fft": return new Fft(); case "cov": return new Covcor(false); case "cor": return new Covcor(true); case "SplineCoef": return SplineCoefNodeGen.create(); case "SplineEval": return SplineEvalNodeGen.create(); case "cutree": case "isoreg": case "monoFC_m": case "numeric_deriv": case "nls_iter": case "setup_starma": case "free_starma": case "set_trans": case "arma0fa": case "get_s2": case "get_resid": case "Dotrans": case "arma0_kfore": case "Starma_method": case "Invtrans": case "Gradtrans": case "ARMAtoMA": case "KalmanLike": case "KalmanFore": case "KalmanSmooth": case "ARIMA_undoPars": case "ARIMA_transPars": case "ARIMA_Invtrans": case "ARIMA_Gradtrans": case "ARIMA_Like": case "ARIMA_CSS": case "TSconv": case "getQ0": case "getQ0bis": case "port_ivset": case "port_nlminb": case "port_nlsb": case "logit_link": case "logit_linkinv": case "logit_mu_eta": case "binomial_dev_resids": case "rWishart": case "Cdqrls": case "Cdist": case "updateform": case "mvfft": case "nextn": case "r2dtable": case "cfilter": case "rfilter": case "lowess": case "DoubleCentre": case "BinDist": case "Rsm": case "tukeyline": case "runmed": case "influence": case "pSmirnov2x": case "pKolmogorov2x": case "pKS2": case "ksmooth": case "Approx": case "ApproxTest": case "LogLin": case "pAnsari": case "qAnsari": case "pKendall": case "pRho": case "SWilk": case "bw_den": case "bw_ucv": case "bw_bcv": case "bw_phi4": case "bw_phi6": case "acf": case "pacf1": case "ar2ma": case "Burg": case "intgrt_vec": case "pp_sum": case "Fexact": case "Fisher_sim": case "chisq_sim": case "d2x2xk": return new UnimplementedExternal(name); // tools case "doTabExpand": return DoTabExpandNodeGen.create(); case "codeFilesAppend": return CodeFilesAppendNodeGen.create(); case "Rmd5": return Rmd5NodeGen.create(); case "dirchmod": return DirChmodNodeGen.create(); case "delim_match": case "C_getfmts": case "check_nonASCII": case "check_nonASCII2": case "ps_kill": case "ps_sigs": case "ps_priority": case "startHTTPD": case "stopHTTPD": case "C_deparseRd": return new UnimplementedExternal(name); // utils case "crc64": return Crc64NodeGen.create(); case "flushconsole": return new Flushconsole(); case "menu": return MenuNodeGen.create(); case "nsl": case "objectSize": case "processevents": case "octsize": case "sockconnect": case "sockread": case "sockclose": case "sockopen": case "socklisten": case "sockwrite": return new UnimplementedExternal(name); // grDevices case "cairoProps": return CairoPropsNodeGen.create(); case "makeQuartzDefault": return new MakeQuartzDefault(); // grid case "L_initGrid": return InitGridNodeGen.create(); default: return null; } } @SuppressWarnings("unused") @Specialization( limit = "1", guards = {"cached == f", "builtin != null"}) protected Object doExternal( RList f, RArgsValuesAndNames args, RMissing packageName, // @Cached("f") RList cached, // @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) { controlVisibility(); return builtin.call(args); } @Specialization public Object callNamedFunction( VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { controlVisibility(); return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall( getAddressFromSymbolInfo(frame, symbol), getNameFromSymbolInfo(frame, symbol), args.getArguments()); } @Specialization public Object callNamedFunction( String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) { return callNamedFunctionWithPackage(name, args, null); } @Specialization public Object callNamedFunctionWithPackage( String name, RArgsValuesAndNames args, String packageName) { controlVisibility(); SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName); if (symbolInfo == null) { errorProfile.enter(); throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name); } return RFFIFactory.getRFFI() .getCallRFFI() .invokeCall(symbolInfo.address, symbolInfo.symbol, args.getArguments()); } @Fallback protected Object dotCallFallback( Object fobj, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) { throw fallback(fobj); } }
/** * {@link WriteSuperFrameVariableNode} captures a write to a variable in some parent frame. * * <p>The state starts out a "unresolved" and transforms to "resolved". */ @SuppressWarnings("unused") @NodeChildren({ @NodeChild(value = "enclosingFrame", type = AccessEnclosingFrameNode.class), @NodeChild(value = "frameSlotNode", type = FrameSlotNode.class) }) @NodeField(name = "mode", type = Mode.class) public abstract class WriteSuperFrameVariableNode extends WriteSuperFrameVariableNodeHelper { private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile(); private final BranchProfile invalidateProfile = BranchProfile.create(); private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile(); protected abstract FrameSlotNode getFrameSlotNode(); public abstract Mode getMode(); public static WriteVariableNode create(String name, RNode rhs, Mode mode) { return new UnresolvedWriteSuperFrameVariableNode(name, rhs, mode); } @Specialization(guards = "isLogicalKind(frame, frameSlot)") protected void doLogical( VirtualFrame frame, byte value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { FrameSlotChangeMonitor.setByteAndInvalidate( enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile); } @Specialization(guards = "isIntegerKind(frame, frameSlot)") protected void doInteger( VirtualFrame frame, int value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { FrameSlotChangeMonitor.setIntAndInvalidate( enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile); } @Specialization(guards = "isDoubleKind(frame, frameSlot)") protected void doDouble( VirtualFrame frame, double value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { FrameSlotChangeMonitor.setDoubleAndInvalidate( enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile); } @Specialization protected void doObject( VirtualFrame frame, Object value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { MaterializedFrame profiledFrame = enclosingFrameProfile.profile(enclosingFrame); Object newValue = shareObjectValue( profiledFrame, frameSlot, storedObjectProfile.profile(value), getMode(), true); FrameSlotChangeMonitor.setObjectAndInvalidate( profiledFrame, frameSlot, newValue, true, invalidateProfile); } public static class UnresolvedWriteSuperFrameVariableNode extends WriteSuperFrameVariableNodeHelper { @Child private RNode rhs; private final String symbol; private final BaseWriteVariableNode.Mode mode; public UnresolvedWriteSuperFrameVariableNode( String symbol, RNode rhs, BaseWriteVariableNode.Mode mode) { this.rhs = rhs; this.symbol = symbol; this.mode = mode; } @Override public String getName() { return symbol; } @Override public RNode getRhs() { return rhs; } @Override public void execute(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame) { CompilerDirectives.transferToInterpreterAndInvalidate(); if (getName().isEmpty()) { throw RError.error(this, RError.Message.ZERO_LENGTH_VARIABLE); } final WriteSuperFrameVariableNodeHelper writeNode; if (REnvironment.isGlobalEnvFrame(enclosingFrame)) { /* * we've reached the global scope, do unconditional write. if this is the first node * in the chain, needs the rhs and enclosingFrame nodes */ AccessEnclosingFrameNode enclosingFrameNode = RArguments.getEnclosingFrame(frame) == enclosingFrame ? new AccessEnclosingFrameNode() : null; writeNode = WriteSuperFrameVariableNodeGen.create( getRhs(), enclosingFrameNode, FrameSlotNode.create( findOrAddFrameSlot( enclosingFrame.getFrameDescriptor(), symbol, FrameSlotKind.Illegal)), getName(), mode); } else { WriteSuperFrameVariableNode actualWriteNode = WriteSuperFrameVariableNodeGen.create( null, null, FrameSlotNode.create(symbol), this.getName(), mode); writeNode = new WriteSuperFrameVariableConditionalNode( actualWriteNode, new UnresolvedWriteSuperFrameVariableNode(symbol, null, mode), getRhs()); } replace(writeNode).execute(frame, value, enclosingFrame); } @Override public void execute(VirtualFrame frame, Object value) { CompilerDirectives.transferToInterpreterAndInvalidate(); MaterializedFrame enclosingFrame = RArguments.getEnclosingFrame(frame); if (enclosingFrame != null) { execute(frame, value, enclosingFrame); } else { // we're in global scope, do a local write instead replace(UnresolvedWriteLocalFrameVariableNodeGen.create(getRhs(), symbol, mode)) .execute(frame, value); } } } public static class WriteSuperFrameVariableConditionalNode extends WriteSuperFrameVariableNodeHelper { @Child private WriteSuperFrameVariableNode writeNode; @Child private WriteSuperFrameVariableNodeHelper nextNode; @Child private RNode rhs; private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile(); private final ConditionProfile hasValueProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile nullSuperFrameProfile = ConditionProfile.createBinaryProfile(); WriteSuperFrameVariableConditionalNode( WriteSuperFrameVariableNode writeNode, WriteSuperFrameVariableNodeHelper nextNode, RNode rhs) { this.writeNode = writeNode; this.nextNode = nextNode; this.rhs = rhs; } @Override public Object getName() { return writeNode.getName(); } @Override public RNode getRhs() { return rhs; } @Override public void execute(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame) { MaterializedFrame profiledEnclosingFrame = enclosingFrameProfile.profile(enclosingFrame); if (hasValueProfile.profile(writeNode.getFrameSlotNode().hasValue(profiledEnclosingFrame))) { writeNode.execute(frame, value, profiledEnclosingFrame); } else { MaterializedFrame superFrame = RArguments.getEnclosingFrame(profiledEnclosingFrame); if (nullSuperFrameProfile.profile(superFrame == null)) { // Might be the case if "{ x <<- 42 }": This is in globalEnv! superFrame = REnvironment.globalEnv().getFrame(); } nextNode.execute(frame, value, superFrame); } } @Override public void execute(VirtualFrame frame, Object value) { assert RArguments.getEnclosingFrame(frame) != null; execute(frame, value, RArguments.getEnclosingFrame(frame)); } } }
/** * Represents a block of code run with exception handlers. There's no {@code try} keyword in Ruby - * it's implicit - but it's similar to a try statement in any other language. */ public class TryNode extends RubyNode { @Child protected ExceptionTranslatingNode tryPart; @Children final RescueNode[] rescueParts; @Child protected RubyNode elsePart; @Child protected WriteInstanceVariableNode clearExceptionVariableNode; private final BranchProfile elseProfile = BranchProfile.create(); private final BranchProfile controlFlowProfile = BranchProfile.create(); private final BranchProfile raiseExceptionProfile = BranchProfile.create(); public TryNode( RubyContext context, SourceSection sourceSection, ExceptionTranslatingNode tryPart, RescueNode[] rescueParts, RubyNode elsePart) { super(context, sourceSection); this.tryPart = tryPart; this.rescueParts = rescueParts; this.elsePart = elsePart; clearExceptionVariableNode = new WriteInstanceVariableNode( context, sourceSection, "$!", new ObjectLiteralNode( context, sourceSection, context.getCoreLibrary().getGlobalVariablesObject()), new ObjectLiteralNode(context, sourceSection, context.getCoreLibrary().getNilObject()), true); } @Override public Object execute(VirtualFrame frame) { while (true) { getContext().getSafepointManager().poll(); Object result; try { result = tryPart.execute(frame); } catch (ControlFlowException exception) { controlFlowProfile.enter(); throw exception; } catch (RaiseException exception) { raiseExceptionProfile.enter(); try { return handleException(frame, exception); } catch (RetryException e) { continue; } } finally { clearExceptionVariableNode.execute(frame); } elseProfile.enter(); elsePart.executeVoid(frame); return result; } } @ExplodeLoop private Object handleException(VirtualFrame frame, RaiseException exception) { CompilerAsserts.neverPartOfCompilation(); notDesignedForCompilation(); getContext() .getCoreLibrary() .getGlobalVariablesObject() .getOperations() .setInstanceVariable( getContext().getCoreLibrary().getGlobalVariablesObject(), "$!", exception.getRubyException()); for (RescueNode rescue : rescueParts) { if (rescue.canHandle(frame, exception.getRubyException())) { return rescue.execute(frame); } } throw exception; } }