// 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; } }
@NodeChild(value = "lexicalParentModule", type = RubyNode.class) public abstract class DefineModuleNode extends RubyNode { private final String name; @Child LookupForExistingModuleNode lookupForExistingModuleNode; private final ConditionProfile needToDefineProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile errorProfile = BranchProfile.create(); public DefineModuleNode(RubyContext context, SourceSection sourceSection, String name) { super(context, sourceSection); this.name = name; } @Specialization(guards = "isRubyModule(lexicalParentModule)") public Object defineModule(VirtualFrame frame, DynamicObject lexicalParentModule) { final RubyConstant constant = lookupForExistingModule(frame, name, lexicalParentModule); final DynamicObject definingModule; if (needToDefineProfile.profile(constant == null)) { definingModule = ModuleNodes.createModule( getContext(), coreLibrary().getModuleClass(), lexicalParentModule, name, this); } else { final Object constantValue = constant.getValue(); if (!RubyGuards.isRubyModule(constantValue) || RubyGuards.isRubyClass(constantValue)) { errorProfile.enter(); throw new RaiseException(coreExceptions().typeErrorIsNotA(name, "module", this)); } definingModule = (DynamicObject) constantValue; } return definingModule; } @Specialization(guards = "!isRubyModule(lexicalParentObject)") public Object defineModuleWrongParent(VirtualFrame frame, Object lexicalParentObject) { throw new RaiseException(coreExceptions().typeErrorIsNotA(lexicalParentObject, "module", this)); } private RubyConstant lookupForExistingModule( VirtualFrame frame, String name, DynamicObject lexicalParent) { if (lookupForExistingModuleNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); lookupForExistingModuleNode = insert(LookupForExistingModuleNodeGen.create(null, null)); } return lookupForExistingModuleNode.executeLookupForExistingModule(frame, name, lexicalParent); } }
@RBuiltin( name = "dimnames", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC) public abstract class DimNames extends RBuiltinNode { private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); private final ConditionProfile nullProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile dataframeProfile = BranchProfile.create(); private final BranchProfile factorProfile = BranchProfile.create(); private final BranchProfile otherProfile = BranchProfile.create(); @Specialization protected RNull getDimNames(@SuppressWarnings("unused") RNull operand) { controlVisibility(); return RNull.instance; } @Specialization protected Object getDimNames(RAbstractContainer container) { controlVisibility(); RList names; if (container instanceof RDataFrame) { dataframeProfile.enter(); names = ((RDataFrame) container).getVector().getDimNames(); } else if (container instanceof RFactor) { factorProfile.enter(); names = ((RFactor) container).getVector().getDimNames(); } else { otherProfile.enter(); names = container.getDimNames(attrProfiles); } return nullProfile.profile(names == null) ? RNull.instance : names; } }
@NodeChildren({ @NodeChild(value = "enclosingFrame", type = AccessEnclosingFrameNode.class), @NodeChild(value = "frameSlotNode", type = FrameSlotNode.class) }) protected abstract static class ResolvedWriteSuperFrameVariableNode extends WriteSuperFrameVariableNode { private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile(); private final BranchProfile invalidateProfile = BranchProfile.create(); private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile(); private final Mode mode; public ResolvedWriteSuperFrameVariableNode(Mode mode) { this.mode = mode; } protected abstract FrameSlotNode getFrameSlotNode(); @Specialization(guards = "isLogicalKind(enclosingFrame, frameSlot)") protected void doLogical(byte value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { FrameSlotChangeMonitor.setByteAndInvalidate( enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile); } @Specialization(guards = "isIntegerKind(enclosingFrame, frameSlot)") protected void doInteger(int value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { FrameSlotChangeMonitor.setIntAndInvalidate( enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile); } @Specialization(guards = "isDoubleKind(enclosingFrame, frameSlot)") protected void doDouble(double value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { FrameSlotChangeMonitor.setDoubleAndInvalidate( enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile); } @Specialization protected void doObject(Object value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { MaterializedFrame profiledFrame = enclosingFrameProfile.profile(enclosingFrame); Object newValue = shareObjectValue( profiledFrame, frameSlot, storedObjectProfile.profile(value), mode, true); FrameSlotChangeMonitor.setObjectAndInvalidate( profiledFrame, frameSlot, newValue, true, invalidateProfile); } }
public class TryNode extends RubyNode { @Child private RubyNode tryPart; @Children private final RescueNode[] rescueParts; @Child private RubyNode elsePart; @Child private SetExceptionVariableNode setExceptionVariableNode; 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; } @Override public Object execute(VirtualFrame frame) { while (true) { Object result; try { result = tryPart.execute(frame); } catch (RaiseException exception) { raiseExceptionProfile.enter(); try { return handleException(frame, exception); } catch (RetryException e) { getContext().getSafepointManager().poll(this); continue; } } catch (ControlFlowException exception) { controlFlowProfile.enter(); throw exception; } elseProfile.enter(); if (elsePart != null) { result = elsePart.execute(frame); } return result; } } @ExplodeLoop private Object handleException(VirtualFrame frame, RaiseException exception) { for (RescueNode rescue : rescueParts) { if (rescue.canHandle(frame, exception.getException())) { return setLastExceptionAndRunRescue(frame, exception, rescue); } } throw exception; } private Object setLastExceptionAndRunRescue( VirtualFrame frame, RaiseException exception, RubyNode rescue) { if (setExceptionVariableNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); setExceptionVariableNode = insert(new SetExceptionVariableNode(getContext())); } return setExceptionVariableNode.setLastExceptionAndRun(frame, exception, rescue); } }
final class PositionsCheckNode extends Node { @Children private final PositionCheckNode[] positionsCheck; private final ElementAccessMode mode; private final BranchProfile errorBranch = BranchProfile.create(); private final VectorLengthProfile selectedPositionsCountProfile = VectorLengthProfile.create(); private final VectorLengthProfile maxOutOfBoundsProfile = VectorLengthProfile.create(); private final ConditionProfile containsNAProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile unsupportedProfile = BranchProfile.create(); private final boolean replace; private final int positionsLength; PositionsCheckNode( ElementAccessMode mode, RType containerType, Object[] positions, boolean exact, boolean replace, boolean recursive) { this.mode = mode; this.replace = replace; this.positionsCheck = new PositionCheckNode[positions.length]; for (int i = 0; i < positions.length; i++) { positionsCheck[i] = PositionCheckNode.createNode( mode, containerType, positions[i], i, positions.length, exact, replace, recursive); } this.positionsLength = positions.length; } public PositionCheckNode getPositionCheckAt(int index) { return positionsCheck[index]; } @ExplodeLoop public boolean isSupported(Object[] positions) { if (positionsCheck.length != positions.length) { unsupportedProfile.enter(); return false; } for (int i = 0; i < positionsCheck.length; i++) { if (!positionsCheck[i].isSupported(positions[i])) { unsupportedProfile.enter(); return false; } } return true; } public int getDimensions() { return positionsCheck.length; } public boolean isSingleDimension() { return positionsCheck.length == 1; } public boolean isMultiDimension() { return positionsCheck.length > 1; } @ExplodeLoop public PositionProfile[] executeCheck( RAbstractContainer vector, int[] vectorDimensions, int vectorLength, Object[] positions) { assert isSupported(positions); verifyDimensions(vectorDimensions); PositionProfile[] statistics = new PositionProfile[positionsLength]; for (int i = 0; i < positionsLength; i++) { Object position = positions[i]; PositionProfile profile = new PositionProfile(); positions[i] = positionsCheck[i].execute(profile, vector, vectorDimensions, vectorLength, position); statistics[i] = profile; } return statistics; } @TruffleBoundary private void print() { System.out.println(positionsCheck.length); } private void verifyDimensions(int[] vectorDimensions) { if (vectorDimensions == null) { if (isMultiDimension()) { errorBranch.enter(); throw dimensionsError(); } } else { if (getDimensions() > vectorDimensions.length || getDimensions() < vectorDimensions.length) { errorBranch.enter(); throw dimensionsError(); } } } private RError dimensionsError() { if (replace) { if (mode.isSubset()) { if (getDimensions() == 2) { return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS_MATRIX); } else { return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS); } } else { return RError.error(this, RError.Message.IMPROPER_SUBSCRIPT); } } else { return RError.error(this, RError.Message.INCORRECT_DIMENSIONS); } } @ExplodeLoop public int getSelectedPositionsCount(PositionProfile[] profiles) { if (positionsCheck.length == 1) { return selectedPositionsCountProfile.profile(profiles[0].selectedPositionsCount); } else { int newSize = 1; for (int i = 0; i < positionsCheck.length; i++) { newSize *= profiles[i].selectedPositionsCount; } return selectedPositionsCountProfile.profile(newSize); } } public int getCachedSelectedPositionsCount() { return selectedPositionsCountProfile.getCachedLength(); } @ExplodeLoop public boolean getContainsNA(PositionProfile[] profiles) { if (positionsCheck.length == 1) { return containsNAProfile.profile(profiles[0].containsNA); } else { boolean containsNA = false; for (int i = 0; i < positionsCheck.length; i++) { containsNA |= profiles[i].containsNA; } return containsNAProfile.profile(containsNA); } } @ExplodeLoop public int getMaxOutOfBounds(PositionProfile[] replacementStatistics) { if (positionsCheck.length == 1) { return maxOutOfBoundsProfile.profile(replacementStatistics[0].maxOutOfBoundsIndex); } else { // impossible to be relevant as position check will throw an error in this case. return 0; } } public boolean isMissing() { return positionsCheck.length == 1 && // (positionsCheck[0].getPositionClass() == RMissing.class || positionsCheck[0].getPositionClass() == REmpty.class || // positionsCheck[0].getPositionClass() == RSymbol.class); } final class PositionProfile { int selectedPositionsCount; int maxOutOfBoundsIndex; boolean containsNA; } }
@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)); } } }
/** * The {@code .Internal} builtin. In {@code .Internal(func(args))} we have an AST where the * RCallNode.Uninitialized and the function child should be a {@link ReadVariableNode} node with * symbol {@code func}. We want to rewrite the AST as if the {@code func} had been called directly. * However, we must do this in a non-destructive way otherwise deparsing and serialization will * fail. * * <p>A note on {@link RInstrumentableNode}. Since both the {@code .Internal} and the argument are * {@link RCallNode}s both may have been wrapped. The call to {@link RASTUtils#unwrap} will go * through any {@code RNodeWrapper} and the rewrite will remove one level of wrapping. However the * parent of the the {@code .Internal}, which will be an {@code RNodeWrapper}, will remain so any * instrumentation at that level will remain in place. */ @TypeSystemReference(EmptyTypeSystemFlatLayout.class) @NodeInfo(cost = NONE) @RBuiltin( name = ".Internal", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"call"}, nonEvalArgs = 0, behavior = COMPLEX) public abstract class Internal extends RBuiltinNode { private final BranchProfile errorProfile = BranchProfile.create(); @Child private RNode builtinCallNode; @Specialization protected Object doInternal(@SuppressWarnings("unused") RMissing x) { errorProfile.enter(); throw RError.error(this, RError.Message.ARGUMENTS_PASSED_0_1, getRBuiltin().name()); } @Specialization protected Object doInternal(VirtualFrame frame, RPromise x) { if (builtinCallNode == null) { RNode call = (RNode) x.getRep(); RNode operand = (RNode) RASTUtils.unwrap(call); if (!(operand instanceof RCallNode)) { errorProfile.enter(); throw RError.error(this, RError.Message.INVALID_INTERNAL); } RCallNode callNode = (RCallNode) operand; RNode func = callNode.getFunctionNode(); String name = ((ReadVariableNode) func).getIdentifier(); RFunction function = RContext.lookupBuiltin(name); if (function == null || function.isBuiltin() && function.getRBuiltin().getKind() != RBuiltinKind.INTERNAL) { errorProfile.enter(); if (function == null && notImplemented(name)) { throw RInternalError.unimplemented(".Internal " + name); } throw RError.error(this, RError.Message.NO_SUCH_INTERNAL, name); } // .Internal function is validated CompilerDirectives.transferToInterpreterAndInvalidate(); builtinCallNode = insert(RCallNode.createInternalCall(callNode, function)); } return builtinCallNode.execute(frame); } private static boolean notImplemented(String name) { for (String internal : NOT_IMPLEMENTED) { if (internal.equals(name)) { return true; } } return false; } // TODO check this; it is out of date private static final String[] NOT_IMPLEMENTED = new String[] { ".addTryHandlers", "interruptsSuspended", "restart", "backsolve", "max.col", "row", "all.names", "comment", "`comment<-`", "list2env", "tcrossprod", "lbeta", "beta", "lchoose", "choose", "dchisq", "pchisq", "qchisq", "dexp", "pexp", "qexp", "dgeom", "pgeom", "qgeom", "dpois", "ppois", "qpois", "dt", "pt", "qt", "dsignrank", "psignrank", "qsignrank", "besselJ", "besselY", "psigamma", "dbeta", "pbeta", "qbeta", "dbinom", "pbinom", "qbinom", "dcauchy", "pcauchy", "qcauchy", "df", "pf", "qf", "dgamma", "pgamma", "qgamma", "dlnorm", "plnorm", "qlnorm", "dlogis", "plogis", "qlogis", "dnbinom", "pnbinom", "qnbinom", "dnorm", "pnorm", "qnorm", "dunif", "punif", "qunif", "dweibull", "pweibull", "qweibull", "dnchisq", "pnchisq", "qnchisq", "dnt", "pnt", "qnt", "dwilcox", "pwilcox", "qwilcox", "besselI", "besselK", "dnbinom_mu", "pnbinom_mu", "qnbinom_mu", "dhyper", "phyper", "qhyper", "dnbeta", "pnbeta", "qnbeta", "dnf", "pnf", "qnf", "dtukey", "ptukey", "qtukey", "rchisq", "rexp", "rgeom", "rpois", "rt", "rsignrank", "rbeta", "rbinom", "rcauchy", "rf", "rgamma", "rlnorm", "rlogis", "rnbinom", "rnbinom_mu", "rnchisq", "rnorm", "runif", "rweibull", "rwilcox", "rhyper", "sample2", "format.info", "grepRaw", "regexec", "adist", "aregexec", "chartr", "intToBits", "rawToBits", "packBits", "utf8ToInt", "intToUtf8", "strtrim", "eapply", "machine", "save", "saveToConn", "dput", "dump", "prmatrix", "gcinfo", "gctorture", "gctorture2", "memory.profile", "recordGraphics", "sys.calls", "sys.on.exit", "rank", "builtins", "bodyCode", "rapply", "islistfactor", "inspect", "mem.limits", "merge", "capabilitiesX11", "Cstack_info", "file.show", "file.choose", "polyroot", "mkCode", "bcClose", "is.builtin.internal", "disassemble", "bcVersion", "load.from.file", "save.to.file", "growconst", "putconst", "getconst", "enableJIT", "setNumMathThreads", "setMaxNumMathThreads", "isatty", "isIncomplete", "pipe", "fifo", "bzfile", "xzfile", "unz", "truncate", "rawConnection", "rawConnectionValue", "sockSelect", "gzcon", "memCompress", "memDecompress", "mkUnbound", "env.profile", "setTimeLimit", "setSessionTimeLimit", "icuSetCollate", "lazyLoadDBflush", "findInterval", "pretty", "crc64", "rowsum_matrix", "rowsum_df", "setS4Object", "traceOnOff", "La_qr_cmplx", "La_rs_cmplx", "La_rg_cmplx", "La_rs", "La_rs_cmplx", "La_dlange", "La_dgecon", "La_dtrcon", "La_zgecon", "La_ztrcon", "La_solve_cmplx", "La_chol2inv", "qr_qy_real", "qr_coef_cmplx", "qr_qy_cmpl", "La_svd", "La_svd_cmplx" }; }
abstract class PositionCheckNode extends Node { protected final Class<?> positionClass; protected final int dimensionIndex; protected final int numDimensions; protected final VectorLengthProfile positionLengthProfile = VectorLengthProfile.create(); protected final BranchProfile error = BranchProfile.create(); protected final boolean replace; protected final RType containerType; @Child private PositionCastNode castNode; @Child private RLengthNode positionLengthNode = RLengthNode.create(); @Child private PositionCharacterLookupNode characterLookup; PositionCheckNode( ElementAccessMode mode, RType containerType, Object positionValue, int dimensionIndex, int numDimensions, boolean exact, boolean replace) { this.positionClass = positionValue.getClass(); this.dimensionIndex = dimensionIndex; this.numDimensions = numDimensions; this.replace = replace; this.containerType = containerType; this.castNode = PositionCastNode.create(mode, replace); if (positionValue instanceof String || positionValue instanceof RAbstractStringVector) { boolean useNAForNotFound = !replace && isListLike(containerType) && mode.isSubscript(); characterLookup = new PositionCharacterLookupNode( mode, numDimensions, dimensionIndex, useNAForNotFound, exact); } } protected static boolean isListLike(RType type) { switch (type) { case Language: case DataFrame: case Expression: case PairList: case List: return true; } return false; } public boolean isIgnoreDimension() { return positionClass == RMissing.class; } public Class<?> getPositionClass() { return positionClass; } public final boolean isSupported(Object object) { return object.getClass() == positionClass; } public static PositionCheckNode createNode( ElementAccessMode mode, RType containerType, Object position, int positionIndex, int numDimensions, boolean exact, boolean replace, boolean recursive) { if (mode.isSubset()) { return PositionCheckSubsetNodeGen.create( mode, containerType, position, positionIndex, numDimensions, exact, replace); } else { return PositionCheckSubscriptNodeGen.create( mode, containerType, position, positionIndex, numDimensions, exact, replace, recursive); } } protected boolean isMultiDimension() { return numDimensions > 1; } public final Object execute( PositionProfile profile, RAbstractContainer vector, int[] vectorDimensions, int vectorLength, Object position) { Object castPosition = castNode.execute(positionClass.cast(position)); int dimensionLength; if (numDimensions == 1) { dimensionLength = vectorLength; } else { assert vectorDimensions != null; assert vectorDimensions.length == numDimensions; dimensionLength = vectorDimensions[dimensionIndex]; } if (characterLookup != null) { castPosition = characterLookup.execute(vector, (RAbstractStringVector) castPosition, dimensionLength); } RTypedValue positionVector = (RTypedValue) profilePosition(castPosition); int positionLength; if (positionVector instanceof RMissing) { positionLength = -1; } else { positionLength = positionLengthProfile.profile(((RAbstractVector) positionVector).getLength()); } assert isValidCastedType(positionVector) : "result type of a position cast node must be integer or logical"; return execute(profile, dimensionLength, positionVector, positionLength); } private final ValueProfile castedValue = ValueProfile.createClassProfile(); Object profilePosition(Object positionVector) { return castedValue.profile(positionVector); } private static boolean isValidCastedType(RTypedValue positionVector) { RType type = positionVector.getRType(); return type == RType.Integer || type == RType.Logical || type == RType.Character || type == RType.Double || type == RType.Null; } public abstract Object execute( PositionProfile statistics, int dimensionLength, Object position, int positionLength); }
/** * The {@code rep} builtin works as follows. * * <ol> * <li>If {@code each} is greater than one, all elements of {@code x} are first replicated {@code * each} times. * <li>If {@code length.out} is given, the result of the first step is truncated or extended as * required. In this case, {@code times} is ignored. * <li>If {@code length.out} is not given, {@code times} is regarded: * <ul> * <li>If {@code times} is a one-element vector, the result of the first step is replicated * {@code times} times. * <li>If {@code times} is a vector longer than one, and {@code each} is greater than one, * an error is issued. * <li>If {@code times} is a vector longer than one, and {@code each} is one, and {@code * times} is as long as {@code x}, each element of {@code x} is given the number of * times indicated by the value at the same index of {@code times}. If {@code times} has * a different length, an error is issued. * </ul> * </ol> */ @RBuiltin( name = "rep", kind = PRIMITIVE, parameterNames = {"x", "times", "length.out", "each"}, dispatch = INTERNAL_GENERIC, behavior = PURE) public abstract class Repeat extends RBuiltinNode { protected abstract Object execute( RAbstractVector x, RAbstractIntVector times, int lengthOut, int each); private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile(); private final BranchProfile errorBranch = BranchProfile.create(); private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile(); private final ConditionProfile replicateOnce = ConditionProfile.createBinaryProfile(); @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create(); @Override public Object[] getDefaultParameterValues() { return new Object[] {RMissing.instance, 1, RRuntime.INT_NA, 1}; } private String argType(Object arg) { return ((RTypedValue) arg).getRType().getName(); } @Override protected void createCasts(CastBuilder casts) { Function<Object, Object> argType = this::argType; casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, argType); casts .arg("times") .defaultError(RError.Message.INVALID_ARGUMENT, "times") .mustNotBeNull() .asIntegerVector(); casts .arg("length.out") .mustNotBeNull() .asIntegerVector() .shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "length.out") .findFirst(RRuntime.INT_NA, RError.Message.FIRST_ELEMENT_USED, "length.out") .mustBe(intNA().or(gte(0))); casts .arg("each") .asIntegerVector() .shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "each") .findFirst(1, RError.Message.FIRST_ELEMENT_USED, "each") .notNA(1) .mustBe(gte(0)); } protected boolean hasNames(RAbstractVector x) { return getNames.getNames(x) != null; } private RError invalidTimes() { throw RError.error(this, RError.Message.INVALID_ARGUMENT, "times"); } @Specialization( guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"}) protected RAbstractVector repNoEachNoNamesSimple( RAbstractDoubleVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) { int t = times.getDataAt(0); if (t < 0) { errorBranch.enter(); throw invalidTimes(); } int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t; double[] data = new double[length]; Arrays.fill(data, x.getDataAt(0)); return RDataFactory.createDoubleVector(data, !RRuntime.isNA(x.getDataAt(0))); } @Specialization(guards = {"each > 1", "!hasNames(x)"}) protected RAbstractVector repEachNoNames( RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) { if (times.getLength() > 1) { errorBranch.enter(); throw invalidTimes(); } RAbstractVector input = handleEach(x, each); if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { return handleLengthOut(input, lengthOut, false); } else { return handleTimes(input, times, false); } } @Specialization(guards = {"each <= 1", "!hasNames(x)"}) protected RAbstractVector repNoEachNoNames( RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) { if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { return handleLengthOut(x, lengthOut, true); } else { return handleTimes(x, times, true); } } @Specialization(guards = {"each > 1", "hasNames(x)"}) protected RAbstractVector repEachNames( RAbstractVector x, RAbstractIntVector times, int lengthOut, int each, @Cached("create()") InitAttributesNode initAttributes, @Cached("createNames()") SetFixedAttributeNode putNames) { if (times.getLength() > 1) { errorBranch.enter(); throw invalidTimes(); } RAbstractVector input = handleEach(x, each); RStringVector names = (RStringVector) handleEach(getNames.getNames(x), each); RVector<?> r; if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { names = (RStringVector) handleLengthOut(names, lengthOut, false); r = handleLengthOut(input, lengthOut, false); } else { names = (RStringVector) handleTimes(names, times, false); r = handleTimes(input, times, false); } putNames.execute(initAttributes.execute(r), names); return r; } @Specialization(guards = {"each <= 1", "hasNames(x)"}) protected RAbstractVector repNoEachNames( RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each, @Cached("create()") InitAttributesNode initAttributes, @Cached("createNames()") SetFixedAttributeNode putNames) { RStringVector names; RVector<?> r; if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { names = (RStringVector) handleLengthOut(getNames.getNames(x), lengthOut, true); r = handleLengthOut(x, lengthOut, true); } else { names = (RStringVector) handleTimes(getNames.getNames(x), times, true); r = handleTimes(x, times, true); } putNames.execute(initAttributes.execute(r), names); return r; } /** Prepare the input vector by replicating its elements. */ private static RVector<?> handleEach(RAbstractVector x, int each) { RVector<?> r = x.createEmptySameType(x.getLength() * each, x.isComplete()); for (int i = 0; i < x.getLength(); i++) { for (int j = i * each; j < (i + 1) * each; j++) { r.transferElementSameType(j, x, i); } } return r; } /** Extend or truncate the vector to a specified length. */ private static RVector<?> handleLengthOut( RAbstractVector x, int lengthOut, boolean copyIfSameSize) { if (x.getLength() == lengthOut) { return (RVector<?>) (copyIfSameSize ? x.copy() : x); } return x.copyResized(lengthOut, false); } /** Replicate the vector a given number of times. */ private RVector<?> handleTimes( RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) { if (oneTimeGiven.profile(times.getLength() == 1)) { // only one times value is given final int howManyTimes = times.getDataAt(0); if (howManyTimes < 0) { errorBranch.enter(); throw invalidTimes(); } if (replicateOnce.profile(howManyTimes == 1)) { return (RVector<?>) (copyIfSameSize ? x.copy() : x); } else { return x.copyResized(x.getLength() * howManyTimes, false); } } else { // times is a vector with several elements if (x.getLength() != times.getLength()) { errorBranch.enter(); invalidTimes(); } // iterate once over the times vector to determine result vector size int resultLength = 0; for (int i = 0; i < times.getLength(); i++) { int t = times.getDataAt(i); if (t < 0) { errorBranch.enter(); throw invalidTimes(); } resultLength += t; } // create and populate result vector RVector<?> r = x.createEmptySameType(resultLength, x.isComplete()); int wp = 0; // write pointer for (int i = 0; i < x.getLength(); i++) { for (int j = 0; j < times.getDataAt(i); ++j, ++wp) { r.transferElementSameType(wp, x, i); } } return r; } } }