Ejemplo n.º 1
0
// 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;
  }
}
Ejemplo n.º 2
0
  @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);
    }
  }
Ejemplo n.º 3
0
  @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);
    }
  }
Ejemplo n.º 4
0
  @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);
    }
  }
Ejemplo n.º 5
0
  @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);
    }
  }
Ejemplo n.º 6
0
  /**
   * 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);
    }
  }
Ejemplo n.º 7
0
/**
 * {@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));
    }
  }
}
Ejemplo n.º 8
0
/**
 * 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;
  }
}