diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java index 78338d6c6cc4335ed97664ba2bcbe401287e6105..71cf528a84ff3e9f6eb91a48a91ac1b8319701e2 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java @@ -23,25 +23,31 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.ffi.GridRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; /** * The .Call support for the grid package. */ public class GridFunctions { + public abstract static class InitGrid extends RExternalBuiltinNode.Arg1 { + @Child GridRFFI.GridRFFINode gridRFFINode = RFFIFactory.getRFFI().getGridRFFI().gridRFFINode(); + @Specialization @TruffleBoundary protected Object initGrid(REnvironment gridEvalEnv) { - return RFFIFactory.getRFFI().getGridRFFI().initGrid(gridEvalEnv); + return gridRFFINode.initGrid(gridEvalEnv); } } public static final class KillGrid extends RExternalBuiltinNode { + @Child GridRFFI.GridRFFINode gridRFFINode = RFFIFactory.getRFFI().getGridRFFI().gridRFFINode(); + @Override @TruffleBoundary public Object call(RArgsValuesAndNames args) { - return RFFIFactory.getRFFI().getGridRFFI().killGrid(); + return gridRFFINode.killGrid(); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java index e793668a8a24f91d57eb57e120592cb04b223961..6e4b0c668a53fb90eb00a80bd21e0cb9716a9acd 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java @@ -37,8 +37,10 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import com.oracle.truffle.r.runtime.ffi.ToolsRFFI; public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 { + @Child ToolsRFFI.ToolsRFFINode toolsRFFINode = RFFIFactory.getRFFI().getToolsRFFI().toolsRFFINode(); @Override protected void createCasts(CastBuilder casts) { @@ -64,7 +66,7 @@ public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 { try (RConnection openConn = RConnection.fromIndex(con).forceOpen("r")) { // @formatter:off - return RFFIFactory.getRFFI().getToolsRFFI().parseRd(openConn, srcfile, + return toolsRFFINode.parseRd(openConn, srcfile, RDataFactory.createLogicalVectorFromScalar(verboseL), RDataFactory.createLogicalVectorFromScalar(fragmentL), RDataFactory.createStringVectorFromScalar(basename.getDataAt(0)), diff --git a/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c index a946f23f8b1f9fbcc72322e199a1103afe3649a8..fd510c9e56eaa4985c9067a574bf6a2b092415ed 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c @@ -29,27 +29,27 @@ typedef int* (*call_nSeed)(void); typedef int* (*call_seeds)(void); JNIEXPORT void JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_init(JNIEnv *env, jclass c, jlong address, jint seed) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nativeInit(JNIEnv *env, jclass c, jlong address, jint seed) { call_init f = (call_init) address; f(seed); } JNIEXPORT double JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_rand(JNIEnv *env, jclass c, jlong address) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nativeRand(JNIEnv *env, jclass c, jlong address) { call_rand f = (call_rand) address; double* dp = f(); return *dp; } JNIEXPORT jint JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nSeed(JNIEnv *env, jclass c, jlong address) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nativeNSeed(JNIEnv *env, jclass c, jlong address) { call_nSeed f = (call_nSeed) address; int *pn = f(); return *pn; } JNIEXPORT void JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_seeds(JNIEnv *env, jclass c, jlong address, jintArray seedsArray) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nativeSeeds(JNIEnv *env, jclass c, jlong address, jintArray seedsArray) { call_seeds f = (call_seeds) address; int *pseeds = f(); int seedslen = (*env)->GetArrayLength(env, seedsArray); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java index d3871d27be24f6105aa6adb51ee81c45046fd98b..d194d58219e4d6e254e1bcf4bd625683cae1121f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java @@ -42,10 +42,10 @@ import com.oracle.truffle.r.nodes.builtin.base.fastpaths.MatrixFastPathNodeGen; import com.oracle.truffle.r.nodes.builtin.base.fastpaths.SetDiffFastPathNodeGen; import com.oracle.truffle.r.nodes.builtin.base.fastpaths.VectorFastPathsFactory.DoubleFastPathNodeGen; import com.oracle.truffle.r.nodes.builtin.base.fastpaths.VectorFastPathsFactory.IntegerFastPathNodeGen; -import com.oracle.truffle.r.nodes.builtin.base.foreign.DotC; -import com.oracle.truffle.r.nodes.builtin.base.foreign.DotCNodeGen; -import com.oracle.truffle.r.nodes.builtin.base.foreign.ForeignFunctions; -import com.oracle.truffle.r.nodes.builtin.base.foreign.ForeignFunctionsFactory; +import com.oracle.truffle.r.nodes.builtin.base.foreign.CallAndExternalFunctions; +import com.oracle.truffle.r.nodes.builtin.base.foreign.CallAndExternalFunctionsFactory; +import com.oracle.truffle.r.nodes.builtin.base.foreign.FortranAndCFunctions; +import com.oracle.truffle.r.nodes.builtin.base.foreign.FortranAndCFunctionsFactory; import com.oracle.truffle.r.nodes.builtin.base.infix.AccessField; import com.oracle.truffle.r.nodes.builtin.base.infix.AccessFieldNodeGen; import com.oracle.truffle.r.nodes.builtin.base.infix.AssignBuiltin; @@ -217,6 +217,11 @@ public class BasePackage extends RBuiltinPackage { add(BrowserFunctions.BrowserSetDebug.class, BrowserFunctionsFactory.BrowserSetDebugNodeGen::create); add(BrowserFunctions.BrowserText.class, BrowserFunctionsFactory.BrowserTextNodeGen::create); add(Call.class, CallNodeGen::create); + add(CallAndExternalFunctions.DotCall.class, CallAndExternalFunctionsFactory.DotCallNodeGen::create); + add(CallAndExternalFunctions.DotCallGraphics.class, CallAndExternalFunctionsFactory.DotCallGraphicsNodeGen::create); + add(CallAndExternalFunctions.DotExternal.class, CallAndExternalFunctionsFactory.DotExternalNodeGen::create); + add(CallAndExternalFunctions.DotExternal2.class, CallAndExternalFunctionsFactory.DotExternal2NodeGen::create); + add(CallAndExternalFunctions.DotExternalGraphics.class, CallAndExternalFunctionsFactory.DotExternalGraphicsNodeGen::create); add(Capabilities.class, CapabilitiesNodeGen::create); add(Cat.class, CatNodeGen::create); add(Ceiling.class, CeilingNodeGen::create); @@ -387,17 +392,12 @@ public class BasePackage extends RBuiltinPackage { add(FileFunctions.ListDirs.class, FileFunctionsFactory.ListDirsNodeGen::create); add(FileFunctions.Unlink.class, FileFunctionsFactory.UnlinkNodeGen::create); add(Floor.class, FloorNodeGen::create); - add(DotC.class, DotCNodeGen::create); add(ForceAndCall.class, ForceAndCallNodeGen::create); - add(ForeignFunctions.DotCall.class, ForeignFunctionsFactory.DotCallNodeGen::create); - add(ForeignFunctions.DotCallGraphics.class, ForeignFunctionsFactory.DotCallGraphicsNodeGen::create); - add(ForeignFunctions.DotExternal.class, ForeignFunctionsFactory.DotExternalNodeGen::create); - add(ForeignFunctions.DotExternal2.class, ForeignFunctionsFactory.DotExternal2NodeGen::create); - add(ForeignFunctions.DotExternalGraphics.class, ForeignFunctionsFactory.DotExternalGraphicsNodeGen::create); - add(ForeignFunctions.Fortran.class, ForeignFunctionsFactory.FortranNodeGen::create); add(Formals.class, FormalsNodeGen::create); add(Format.class, FormatNodeGen::create); add(FormatC.class, FormatCNodeGen::create); + add(FortranAndCFunctions.DotC.class, FortranAndCFunctionsFactory.DotCNodeGen::create); + add(FortranAndCFunctions.Fortran.class, FortranAndCFunctionsFactory.FortranNodeGen::create); add(FrameFunctions.MatchCall.class, FrameFunctionsFactory.MatchCallNodeGen::create); add(FrameFunctions.ParentFrame.class, FrameFunctionsFactory.ParentFrameNodeGen::create); add(FrameFunctions.SysCall.class, FrameFunctionsFactory.SysCallNodeGen::create); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java index fe7ce64eb662db796aae3d05ae6981247b57ea65..06999f6a158957e5ea50770f8477daea0db39bec 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java @@ -63,6 +63,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; */ public class GrepFunctions { public abstract static class CommonCodeAdapter extends RBuiltinNode { + @Child protected PCRERFFI.PCRERFFINode pcreRFFINode = RFFIFactory.getRFFI().getPCRERFFI().pcreRFFINode(); /** * This profile is needed to satisfy API requirements. @@ -205,8 +206,8 @@ public class GrepFunctions { protected PCRERFFI.Result compilePerlPattern(String pattern, boolean ignoreCase) { int cflags = ignoreCase ? PCRERFFI.CASELESS : 0; - long tables = RFFIFactory.getRFFI().getPCRERFFI().maketables(); - PCRERFFI.Result pcre = RFFIFactory.getRFFI().getPCRERFFI().compile(pattern, cflags, tables); + long tables = pcreRFFINode.maketables(); + PCRERFFI.Result pcre = pcreRFFINode.compile(pattern, cflags, tables); if (pcre.result == 0) { // TODO output warning if pcre.errorMessage not NULL throw RError.error(this, RError.Message.INVALID_REGEXP, pattern); @@ -246,7 +247,7 @@ public class GrepFunctions { for (int i = 0; i < len; i++) { String text = vector.getDataAt(i); if (!RRuntime.isNA(text)) { - if (RFFIFactory.getRFFI().getPCRERFFI().exec(pcre.result, 0, text, 0, 0, ovector) >= 0) { + if (pcreRFFINode.exec(pcre.result, 0, text, 0, 0, ovector) >= 0) { matches[i] = true; } } @@ -433,7 +434,7 @@ public class GrepFunctions { int eflag = 0; int lastEnd = -1; StringBuffer sb = new StringBuffer(); - while (RFFIFactory.getRFFI().getPCRERFFI().exec(pcre.result, 0, input, offset, eflag, ovector) >= 0) { + while (pcreRFFINode.exec(pcre.result, 0, input, offset, eflag, ovector) >= 0) { nmatch++; for (int j = offset; j < ovector[0]; j++) { sb.append(input.charAt(j)); @@ -789,13 +790,13 @@ public class GrepFunctions { } } else if (perl) { PCRERFFI.Result pcre = compilePerlPattern(pattern, ignoreCase); - int maxCaptureCount = RFFIFactory.getRFFI().getPCRERFFI().getCaptureCount(pcre.result, 0); + int maxCaptureCount = pcreRFFINode.getCaptureCount(pcre.result, 0); int[] ovector = new int[(maxCaptureCount + 1) * 3]; int offset = 0; while (true) { - int captureCount = RFFIFactory.getRFFI().getPCRERFFI().exec(pcre.result, 0, text, offset, 0, ovector); + int captureCount = pcreRFFINode.exec(pcre.result, 0, text, offset, 0, ovector); if (captureCount >= 0) { - String[] captureNames = RFFIFactory.getRFFI().getPCRERFFI().getCaptureNames(pcre.result, 0, maxCaptureCount); + String[] captureNames = pcreRFFINode.getCaptureNames(pcre.result, 0, maxCaptureCount); for (int i = 0; i < captureNames.length; i++) { if (captureNames[i] == null) { captureNames[i] = ""; @@ -1152,7 +1153,7 @@ public class GrepFunctions { // treat split = NULL as split = "" RAbstractStringVector split = splitArg.getLength() == 0 ? RDataFactory.createStringVectorFromScalar("") : splitArg; String[] splits = new String[split.getLength()]; - long pcreTables = perl ? RFFIFactory.getRFFI().getPCRERFFI().maketables() : 0; + long pcreTables = perl ? pcreRFFINode.maketables() : 0; PCRERFFI.Result[] pcreSplits = perl ? new PCRERFFI.Result[splits.length] : null; na.enable(x); @@ -1161,7 +1162,7 @@ public class GrepFunctions { splits[i] = fixed || perl ? split.getDataAt(i) : RegExp.checkPreDefinedClasses(split.getDataAt(i)); if (perl) { if (!currentSplit.isEmpty()) { - pcreSplits[i] = RFFIFactory.getRFFI().getPCRERFFI().compile(currentSplit, 0, pcreTables); + pcreSplits[i] = pcreRFFINode.compile(currentSplit, 0, pcreTables); if (pcreSplits[i].result == 0) { // TODO output warning if pcre.errorMessage not NULL throw RError.error(this, RError.Message.INVALID_REGEXP, currentSplit); @@ -1231,14 +1232,14 @@ public class GrepFunctions { return RDataFactory.createStringVector(result, true); } - private static RStringVector splitPerl(String data, PCRERFFI.Result pcre) { + private RStringVector splitPerl(String data, PCRERFFI.Result pcre) { ArrayList<String> matches = new ArrayList<>(); int lastEndOffset = 0; int lastEndIndex = 0; int[] ovector = new int[30]; int[] fromByteMapping = getFromByteMapping(data); // non-null if it's necessary - while (RFFIFactory.getRFFI().getPCRERFFI().exec(pcre.result, 0, data, lastEndOffset, 0, ovector) >= 0) { + while (pcreRFFINode.exec(pcre.result, 0, data, lastEndOffset, 0, ovector) >= 0) { // offset == byte position // index == character position int startOffset = ovector[0]; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java index 2e1b049a8896038a9cfd8cd5c5286209590fed69..bd82f21a35e201aa79282e19a78421de2cdd864c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java @@ -49,6 +49,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.ffi.LapackRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -61,18 +62,22 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; */ public class LaFunctions { + protected abstract static class Adapter extends RBuiltinNode { + @Child protected LapackRFFI.LapackRFFINode lapackRFFINode = RFFIFactory.getRFFI().getLapackRFFI().getLapackRFFINode(); + } + @RBuiltin(name = "La_version", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class Version extends RBuiltinNode { + public abstract static class Version extends Adapter { @Specialization @TruffleBoundary protected String doVersion() { int[] version = new int[3]; - RFFIFactory.getRFFI().getLapackRFFI().ilaver(version); + lapackRFFINode.ilaver(version); return version[0] + "." + version[1] + "." + version[2]; } } - private abstract static class RsgAdapter extends RBuiltinNode { + private abstract static class RsgAdapter extends Adapter { protected static final String[] NAMES = new String[]{"values", "vectors"}; protected final BranchProfile errorProfile = BranchProfile.create(); @@ -108,7 +113,7 @@ public class LaFunctions { double[] wi = new double[n]; double[] work = new double[1]; // ask for optimal size of work array - int info = RFFIFactory.getRFFI().getLapackRFFI().dgeev(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, -1); + int info = lapackRFFINode.dgeev(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, -1); if (info != 0) { errorProfile.enter(); throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeev"); @@ -116,7 +121,7 @@ public class LaFunctions { // now allocate work array and make the actual call int lwork = (int) work[0]; work = new double[lwork]; - info = RFFIFactory.getRFFI().getLapackRFFI().dgeev(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, lwork); + info = lapackRFFINode.dgeev(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, lwork); if (info != 0) { errorProfile.enter(); throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeev"); @@ -209,7 +214,7 @@ public class LaFunctions { int[] isuppz = new int[2 * n]; double[] work = new double[1]; int[] iwork = new int[1]; - int info = RFFIFactory.getRFFI().getLapackRFFI().dsyevr(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork); + int info = lapackRFFINode.dsyevr(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork); if (info != 0) { errorProfile.enter(); throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dysevr"); @@ -218,7 +223,7 @@ public class LaFunctions { liwork = iwork[0]; work = new double[lwork]; iwork = new int[liwork]; - info = RFFIFactory.getRFFI().getLapackRFFI().dsyevr(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork); + info = lapackRFFINode.dsyevr(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork); if (info != 0) { errorProfile.enter(); throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dysevr"); @@ -239,7 +244,7 @@ public class LaFunctions { } @RBuiltin(name = "La_qr", kind = INTERNAL, parameterNames = {"in"}, behavior = PURE) - public abstract static class Qr extends RBuiltinNode { + public abstract static class Qr extends Adapter { @CompilationFinal private static final String[] NAMES = new String[]{"qr", "rank", "qraux", "pivot"}; @@ -266,14 +271,14 @@ public class LaFunctions { double[] tau = new double[m < n ? m : n]; double[] work = new double[1]; // ask for optimal size of work array - int info = RFFIFactory.getRFFI().getLapackRFFI().dgeqp3(m, n, a, m, jpvt, tau, work, -1); + int info = lapackRFFINode.dgeqp3(m, n, a, m, jpvt, tau, work, -1); if (info < 0) { errorProfile.enter(); throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeqp3"); } int lwork = (int) work[0]; work = new double[lwork]; - info = RFFIFactory.getRFFI().getLapackRFFI().dgeqp3(m, n, a, m, jpvt, tau, work, lwork); + info = lapackRFFINode.dgeqp3(m, n, a, m, jpvt, tau, work, lwork); if (info < 0) { errorProfile.enter(); throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeqp3"); @@ -292,7 +297,7 @@ public class LaFunctions { } @RBuiltin(name = "qr_coef_real", kind = INTERNAL, parameterNames = {"q", "b"}, behavior = PURE) - public abstract static class QrCoefReal extends RBuiltinNode { + public abstract static class QrCoefReal extends Adapter { private final BranchProfile errorProfile = BranchProfile.create(); @@ -330,19 +335,19 @@ public class LaFunctions { // we work directly in the internal data of b double[] bData = b.getDataWithoutCopying(); // ask for optimal size of work array - int info = RFFIFactory.getRFFI().getLapackRFFI().dormqr(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, -1); + int info = lapackRFFINode.dormqr(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, -1); if (info < 0) { errorProfile.enter(); throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dormqr"); } int lwork = (int) work[0]; work = new double[lwork]; - info = RFFIFactory.getRFFI().getLapackRFFI().dormqr(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, lwork); + info = lapackRFFINode.dormqr(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, lwork); if (info < 0) { errorProfile.enter(); throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dormqr"); } - info = RFFIFactory.getRFFI().getLapackRFFI().dtrtrs('U', 'N', 'N', k, nrhs, qrData, n, bData, n); + info = lapackRFFINode.dtrtrs('U', 'N', 'N', k, nrhs, qrData, n, bData, n); if (info < 0) { errorProfile.enter(); throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dtrtrs"); @@ -353,7 +358,7 @@ public class LaFunctions { } @RBuiltin(name = "det_ge_real", kind = INTERNAL, parameterNames = {"a", "uselog"}, behavior = PURE) - public abstract static class DetGeReal extends RBuiltinNode { + public abstract static class DetGeReal extends Adapter { private static final RStringVector NAMES_VECTOR = RDataFactory.createStringVector(new String[]{"modulus", "sign"}, RDataFactory.COMPLETE_VECTOR); private static final RStringVector DET_CLASS = RDataFactory.createStringVector(new String[]{"det"}, RDataFactory.COMPLETE_VECTOR); @@ -386,7 +391,7 @@ public class LaFunctions { int[] ipiv = new int[n]; double modulus = 0; double[] aData = a.getDataWithoutCopying(); - int info = RFFIFactory.getRFFI().getLapackRFFI().dgetrf(n, n, aData, n, ipiv); + int info = lapackRFFINode.dgetrf(n, n, aData, n, ipiv); int sign = 1; if (info < 0) { errorProfile.enter(); @@ -440,7 +445,7 @@ public class LaFunctions { } @RBuiltin(name = "La_chol", kind = INTERNAL, parameterNames = {"a", "pivot", "tol"}, behavior = PURE) - public abstract static class LaChol extends RBuiltinNode { + public abstract static class LaChol extends Adapter { private final BranchProfile errorProfile = BranchProfile.create(); private final ConditionProfile noPivot = ConditionProfile.createBinaryProfile(); @@ -478,7 +483,7 @@ public class LaFunctions { } int info; if (noPivot.profile(!piv)) { - info = RFFIFactory.getRFFI().getLapackRFFI().dpotrf('U', m, aData, m); + info = lapackRFFINode.dpotrf('U', m, aData, m); if (info != 0) { errorProfile.enter(); // TODO informative error message (aka GnuR) @@ -488,7 +493,7 @@ public class LaFunctions { int[] ipiv = new int[m]; double[] work = new double[2 * m]; int[] rank = new int[1]; - info = RFFIFactory.getRFFI().getLapackRFFI().dpstrf('U', n, aData, n, ipiv, rank, tol, work); + info = lapackRFFINode.dpstrf('U', n, aData, n, ipiv, rank, tol, work); if (info != 0) { errorProfile.enter(); // TODO informative error message (aka GnuR) @@ -511,7 +516,7 @@ public class LaFunctions { } @RBuiltin(name = "La_solve", kind = INTERNAL, parameterNames = {"a", "bin", "tolin"}, behavior = PURE) - public abstract static class LaSolve extends RBuiltinNode { + public abstract static class LaSolve extends Adapter { protected final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); @Child private CastDoubleNode castDouble = CastDoubleNodeGen.create(false, false, false); @@ -601,7 +606,7 @@ public class LaFunctions { assert aDouble != a; avals = aDouble.getInternalStore(); } - int info = RFFIFactory.getRFFI().getLapackRFFI().dgesv(n, p, avals, n, ipiv, bData, n); + int info = lapackRFFINode.dgesv(n, p, avals, n, ipiv, bData, n); if (info < 0) { RError.error(this, RError.Message.LAPACK_INVALID_VALUE, -info, "dgesv"); } @@ -609,10 +614,10 @@ public class LaFunctions { RError.error(this, RError.Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info); } if (tol > 0) { - double anorm = RFFIFactory.getRFFI().getLapackRFFI().dlange('1', n, n, avals, n, null); + double anorm = lapackRFFINode.dlange('1', n, n, avals, n, null); double[] work = new double[4 * n]; double[] rcond = new double[1]; - RFFIFactory.getRFFI().getLapackRFFI().dgecon('1', n, avals, n, anorm, rcond, work, ipiv); + lapackRFFINode.dgecon('1', n, avals, n, anorm, rcond, work, ipiv); if (rcond[0] < tol) { RError.error(this, RError.Message.SYSTEM_COMP_SINGULAR, rcond[0]); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java similarity index 80% rename from com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java rename to com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java index 652e1209f88aff67fca0de71f4c8e69e66e6581f..5f2c06c4cbdaec3ab2605da7fa6f4a560a6bd692 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java @@ -15,7 +15,6 @@ import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; -import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -91,7 +90,6 @@ import com.oracle.truffle.r.library.utils.ObjectSizeNodeGen; import com.oracle.truffle.r.library.utils.RprofNodeGen; import com.oracle.truffle.r.library.utils.RprofmemNodeGen; import com.oracle.truffle.r.library.utils.TypeConvertNodeGen; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode; import com.oracle.truffle.r.nodes.objects.GetPrimNameNodeGen; @@ -99,8 +97,6 @@ import com.oracle.truffle.r.nodes.objects.NewObjectNodeGen; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalCode; -import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; @@ -108,22 +104,21 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ffi.CallRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; -import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; +import com.oracle.truffle.r.runtime.ffi.RFFIFactory; /** - * {@code .Call} {@code .Fortran}, {@code .External}, {@code .External2}, {@code External.graphics} - * functions. + * {@code .Call}, {@code .Call.graphics}, {@code .External}, {@code .External2}, + * {@code External.graphics} functions, which share a common signature. * * TODO Completeness (more types, more error checks), Performance (copying). Especially all the * subtleties around copying. * * See <a href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/Foreign.html">here</a>. */ -public class ForeignFunctions { +public class CallAndExternalFunctions { @TruffleBoundary protected static Object encodeArgumentPairList(RArgsValuesAndNames args, String symbolName) { @@ -136,160 +131,8 @@ public class ForeignFunctions { return list; } - /** - * Locator for "builtin" package function implementations. The "builtin" packages contain many - * functions that are called from R code via the FFI, e.g. {@code .Call}, but implemented - * internally in GnuR, and not necessarily following the FFI API. The value passed to - * {@code .Call} etc., is a symbol, created when the package is loaded and stored in the - * namespace environment of the package, that is a list-valued object. Evidently these - * "builtins" are somewhat similar to the {@code .Primitive} and {@code .Internal} builtins and, - * similarly, most of these are re-implemented in Java in FastR. The - * {@link #lookupBuiltin(RList)} method checks the name in the list object and returns the - * {@link RExternalBuiltinNode} that implements the function, or {@code null}. A {@code null} - * result implies that the builtin is not implemented in Java, but called directly via the FFI - * interface, which is only possible for functions that use the FFI in a way that FastR can - * handle. - */ - protected abstract static class LookupAdapter extends RBuiltinNode { - @Child private ExtractNativeCallInfoNode extractSymbolInfoNode = ExtractNativeCallInfoNodeGen.create(); + protected abstract static class CallRFFIAdapter extends LookupAdapter { @Child protected CallRFFI.CallRFFINode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().callRFFINode(); - - protected static class UnimplementedExternal extends RExternalBuiltinNode { - private final String name; - - public UnimplementedExternal(String name) { - this.name = name; - } - - @Override - public final Object call(RArgsValuesAndNames args) { - throw RInternalError.unimplemented("unimplemented external builtin: " + name); - } - } - - protected abstract RExternalBuiltinNode lookupBuiltin(RList symbol); - - private static final String UNKNOWN_EXTERNAL_BUILTIN = "UNKNOWN_EXTERNAL_BUILTIN"; - - protected static String lookupName(RList symbol) { - CompilerAsserts.neverPartOfCompilation(); - if (symbol.getNames() != null) { - RAbstractStringVector names = symbol.getNames(); - for (int i = 0; i < names.getLength(); i++) { - if (names.getDataAt(i).equals("name")) { - String name = RRuntime.asString(symbol.getDataAt(i)); - return name != null ? name : UNKNOWN_EXTERNAL_BUILTIN; - } - } - } - return UNKNOWN_EXTERNAL_BUILTIN; - } - - @TruffleBoundary - protected RuntimeException fallback(Object symbol) { - String name = null; - if (symbol instanceof RList) { - name = lookupName((RList) symbol); - name = name == UNKNOWN_EXTERNAL_BUILTIN ? null : name; - if (name != null && lookupBuiltin((RList) symbol) != null) { - /* - * if we reach this point, then the cache saw a different value for f. the lists - * that contain the information about native calls are never expected to change. - */ - throw RInternalError.shouldNotReachHere("fallback reached for " + getRBuiltin().name() + " " + name); - } - } - throw RError.nyi(this, getRBuiltin().name() + " specialization failure: " + (name == null ? "<unknown>" : name)); - } - - protected NativeCallInfo extractSymbolInfo(VirtualFrame frame, RList symbol) { - return (NativeCallInfo) extractSymbolInfoNode.execute(frame, symbol); - } - - protected String checkPackageArg(Object rPackage, BranchProfile errorProfile) { - String libName = null; - if (!(rPackage instanceof RMissing)) { - libName = RRuntime.asString(rPackage); - if (libName == null) { - errorProfile.enter(); - throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE"); - } - } - return libName; - } - - protected static RExternalBuiltinNode getExternalModelBuiltinNode(String name) { - return new RInternalCodeBuiltinNode(RContext.getInstance(), "stats", RInternalCode.loadSourceRelativeTo(StatsUtil.class, "model.R"), name); - } - - protected static final int CallNST = DLL.NativeSymbolType.Call.ordinal(); - protected static final int ExternalNST = DLL.NativeSymbolType.External.ordinal(); - - public static DLL.RegisteredNativeSymbol createRegisteredNativeSymbol(int nstOrd) { - // DSL cannot resolve DLL.DLL.NativeSymbolType - DLL.NativeSymbolType nst = DLL.NativeSymbolType.values()[nstOrd]; - return new DLL.RegisteredNativeSymbol(nst, null, null); - } - } - - /** - * Interface to .Fortran native functions. Some functions have explicit implementations in - * FastR, otherwise the .Fortran interface uses the machinery that implements the .C interface. - */ - @RBuiltin(name = ".Fortran", kind = PRIMITIVE, parameterNames = {".NAME", "...", "NAOK", "DUP", "PACKAGE", "ENCODING"}, behavior = COMPLEX) - public abstract static class Fortran extends LookupAdapter { - - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, RMissing.instance, RMissing.instance}; - } - - @Override - @TruffleBoundary - protected RExternalBuiltinNode lookupBuiltin(RList symbol) { - switch (lookupName(symbol)) { - case "dqrdc2": - return new Dqrdc2(); - case "dqrcf": - return new Dqrcf(); - default: - return null; - } - } - - @SuppressWarnings("unused") - @Specialization(limit = "1", guards = {"cached == symbol", "builtin != null"}) - protected Object doExternal(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding, // - @Cached("symbol") RList cached, // - @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin) { - return builtin.call(frame, args); - } - - @Specialization(guards = "lookupBuiltin(symbol) == null") - protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage, - @SuppressWarnings("unused") RMissing encoding) { - NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); - return DotC.dispatch(this, nativeCallInfo, naok, dup, args); - } - - @Specialization - protected RList c(RAbstractStringVector f, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, @SuppressWarnings("unused") RMissing encoding, // - @Cached("create()") BranchProfile errorProfile) { - String libName = checkPackageArg(rPackage, errorProfile); - DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Fortran, null, null); - DLL.SymbolHandle func = DLL.findSymbol(f.getDataAt(0), libName, rns); - if (func == DLL.SYMBOL_NOT_FOUND) { - errorProfile.enter(); - throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, f); - } - return DotC.dispatch(this, new NativeCallInfo(f.getDataAt(0), func, rns.getDllInfo()), naok, dup, args); - } - - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object symbol, Object args, Object naok, Object dup, Object rPackage, Object encoding) { - throw fallback(symbol); - } } /** @@ -309,7 +152,7 @@ public class ForeignFunctions { * could be invoked by a string but experimentally that situation has never been encountered. */ @RBuiltin(name = ".Call", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotCall extends LookupAdapter { + public abstract static class DotCall extends CallRFFIAdapter { private final BranchProfile errorProfile = BranchProfile.create(); @@ -651,7 +494,7 @@ public class ForeignFunctions { * {@link DotCall}. */ @RBuiltin(name = ".External", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotExternal extends LookupAdapter { + public abstract static class DotExternal extends CallRFFIAdapter { private final BranchProfile errorProfile = BranchProfile.create(); @@ -742,7 +585,7 @@ public class ForeignFunctions { } @RBuiltin(name = ".External2", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotExternal2 extends LookupAdapter { + public abstract static class DotExternal2 extends CallRFFIAdapter { private static final Object CALL = "call"; private static final Object OP = "op"; private static final Object RHO = "rho"; @@ -819,7 +662,7 @@ public class ForeignFunctions { } @RBuiltin(name = ".External.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotExternalGraphics extends LookupAdapter { + public abstract static class DotExternalGraphics extends CallRFFIAdapter { private final BranchProfile errorProfile = BranchProfile.create(); @@ -876,7 +719,7 @@ public class ForeignFunctions { } @RBuiltin(name = ".Call.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotCallGraphics extends LookupAdapter { + public abstract static class DotCallGraphics extends CallRFFIAdapter { private final BranchProfile errorProfile = BranchProfile.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java deleted file mode 100644 index 8009ea798359a524bc8b59bd25bdd0408fbe1d0e..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * This material is distributed under the GNU General Public License - * Version 2. You may review the terms of this license at - * http://www.gnu.org/licenses/gpl-2.0.html - * - * Copyright (c) 1995-2012, The R Core Team - * Copyright (c) 2003, The R Foundation - * Copyright (c) 2015, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.nodes.builtin.base.foreign; - -import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; -import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; - -import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.ffi.DLL; -import com.oracle.truffle.r.runtime.ffi.RFFIFactory; -import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; - -/** - * {@code .C} functions. - * - * TODO Completeness (more types, more error checks), Performance (copying). Especially all the - * subtleties around copying. - * - * See <a href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/Foreign.html">here</a>. - */ -@RBuiltin(name = ".C", kind = PRIMITIVE, parameterNames = {".NAME", "...", "NAOK", "DUP", "PACKAGE", "ENCODING"}, behavior = COMPLEX) -public abstract class DotC extends RBuiltinNode { - - private static final int SCALAR_DOUBLE = 0; - private static final int SCALAR_INT = 1; - private static final int SCALAR_LOGICAL = 2; - @SuppressWarnings("unused") private static final int SCALAR_STRING = 3; - private static final int VECTOR_DOUBLE = 10; - private static final int VECTOR_INT = 11; - private static final int VECTOR_LOGICAL = 12; - @SuppressWarnings("unused") private static final int VECTOR_STRING = 12; - - @Child private ExtractNativeCallInfoNode extractSymbolInfoNode = ExtractNativeCallInfoNodeGen.create(); - - protected NativeCallInfo extractSymbolInfo(VirtualFrame frame, RList symbol) { - return (NativeCallInfo) extractSymbolInfoNode.execute(frame, symbol); - } - - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, RMissing.instance, RMissing.instance}; - } - - @SuppressWarnings("unused") - @Specialization - protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding) { - NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); - return dispatch(this, nativeCallInfo, naok, dup, args); - } - - @SuppressWarnings("unused") - @Specialization - protected RList c(RAbstractStringVector f, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding, // - @Cached("create()") BranchProfile errorProfile) { - String libName = null; - if (!(rPackage instanceof RMissing)) { - libName = RRuntime.asString(rPackage); - if (libName == null) { - errorProfile.enter(); - throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE"); - } - } - DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.C, null, null); - DLL.SymbolHandle func = DLL.findSymbol(f.getDataAt(0), libName, rns); - if (func == DLL.SYMBOL_NOT_FOUND) { - errorProfile.enter(); - throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, f); - } - return dispatch(this, new NativeCallInfo(f.getDataAt(0), func, rns.getDllInfo()), naok, dup, args); - } - - private static int[] checkNAs(RBuiltinNode node, int argIndex, int[] data) { - CompilerAsserts.neverPartOfCompilation(); - for (int i = 0; i < data.length; i++) { - if (RRuntime.isNA(data[i])) { - throw RError.error(node, RError.Message.NA_IN_FOREIGN_FUNCTION_CALL, argIndex); - } - } - return data; - } - - private static double[] checkNAs(RBuiltinNode node, int argIndex, double[] data) { - CompilerAsserts.neverPartOfCompilation(); - for (int i = 0; i < data.length; i++) { - if (!RRuntime.isFinite(data[i])) { - throw RError.error(node, RError.Message.NA_NAN_INF_IN_FOREIGN_FUNCTION_CALL, argIndex); - } - } - return data; - } - - private static RStringVector validateArgNames(int argsLength, ArgumentsSignature signature) { - String[] listArgNames = new String[argsLength]; - for (int i = 0; i < argsLength; i++) { - String name = signature.getName(i); - if (name == null) { - name = RRuntime.NAMES_ATTR_EMPTY_VALUE; - } - listArgNames[i] = name; - } - return RDataFactory.createStringVector(listArgNames, RDataFactory.COMPLETE_VECTOR); - } - - @TruffleBoundary - protected static RList dispatch(RBuiltinNode node, NativeCallInfo nativeCallInfo, byte naok, byte dup, RArgsValuesAndNames args) { - @SuppressWarnings("unused") - boolean dupArgs = RRuntime.fromLogical(dup); - @SuppressWarnings("unused") - boolean checkNA = RRuntime.fromLogical(naok); - // Analyze the args, making copies (ignoring dup for now) - Object[] array = args.getArguments(); - int[] argTypes = new int[array.length]; - Object[] nativeArgs = new Object[array.length]; - for (int i = 0; i < array.length; i++) { - Object arg = array[i]; - if (arg instanceof RAbstractDoubleVector) { - argTypes[i] = VECTOR_DOUBLE; - nativeArgs[i] = checkNAs(node, i + 1, ((RAbstractDoubleVector) arg).materialize().getDataCopy()); - } else if (arg instanceof RAbstractIntVector) { - argTypes[i] = VECTOR_INT; - nativeArgs[i] = checkNAs(node, i + 1, ((RAbstractIntVector) arg).materialize().getDataCopy()); - } else if (arg instanceof RAbstractLogicalVector) { - argTypes[i] = VECTOR_LOGICAL; - // passed as int[] - byte[] data = ((RAbstractLogicalVector) arg).materialize().getDataWithoutCopying(); - int[] dataAsInt = new int[data.length]; - for (int j = 0; j < data.length; j++) { - // An NA is an error but the error handling happens in checkNAs - dataAsInt[j] = RRuntime.isNA(data[j]) ? RRuntime.INT_NA : data[j]; - } - nativeArgs[i] = checkNAs(node, i + 1, dataAsInt); - } else if (arg instanceof Double) { - argTypes[i] = SCALAR_DOUBLE; - nativeArgs[i] = checkNAs(node, i + 1, new double[]{(double) arg}); - } else if (arg instanceof Integer) { - argTypes[i] = SCALAR_INT; - nativeArgs[i] = checkNAs(node, i + 1, new int[]{(int) arg}); - } else if (arg instanceof Byte) { - argTypes[i] = SCALAR_LOGICAL; - nativeArgs[i] = checkNAs(node, i + 1, new int[]{RRuntime.isNA((byte) arg) ? RRuntime.INT_NA : (byte) arg}); - } else { - throw RError.error(node, RError.Message.UNIMPLEMENTED_ARG_TYPE, i + 1); - } - } - RFFIFactory.getRFFI().getCRFFI().invoke(nativeCallInfo, nativeArgs); - // we have to assume that the native method updated everything - RStringVector listNames = validateArgNames(array.length, args.getSignature()); - Object[] results = new Object[array.length]; - for (int i = 0; i < array.length; i++) { - switch (argTypes[i]) { - case SCALAR_DOUBLE: - results[i] = RDataFactory.createDoubleVector((double[]) nativeArgs[i], RDataFactory.COMPLETE_VECTOR); - break; - case SCALAR_INT: - results[i] = RDataFactory.createIntVector((int[]) nativeArgs[i], RDataFactory.COMPLETE_VECTOR); - break; - case SCALAR_LOGICAL: - // have to convert back from int[] - int[] nativeIntArgs = (int[]) nativeArgs[i]; - byte[] nativeByteArgs = new byte[nativeIntArgs.length]; - for (int j = 0; j < nativeByteArgs.length; j++) { - int nativeInt = nativeIntArgs[j]; - nativeByteArgs[j] = (byte) (nativeInt == RRuntime.INT_NA ? RRuntime.LOGICAL_NA : nativeInt & 0xFF); - } - results[i] = RDataFactory.createLogicalVector(nativeByteArgs, RDataFactory.COMPLETE_VECTOR); - break; - case VECTOR_DOUBLE: - results[i] = ((RAbstractDoubleVector) array[i]).materialize().copyResetData((double[]) nativeArgs[i]); - break; - case VECTOR_INT: - results[i] = ((RAbstractIntVector) array[i]).materialize().copyResetData((int[]) nativeArgs[i]); - break; - case VECTOR_LOGICAL: { - int[] intData = (int[]) nativeArgs[i]; - byte[] byteData = new byte[intData.length]; - for (int j = 0; j < intData.length; j++) { - byteData[j] = RRuntime.isNA(intData[j]) ? RRuntime.LOGICAL_NA : RRuntime.asLogical(intData[j] != 0); - } - results[i] = ((RAbstractLogicalVector) array[i]).materialize().copyResetData(byteData); - break; - } - } - } - return RDataFactory.createList(results, listNames); - } - -} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java index b8dfa18b98a9656c6d2df0059a5589ebf7deda57..ebf0fb5462597a941b316806e45c1e71959e5bc5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java @@ -21,9 +21,11 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.ffi.RApplRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; public final class Dqrcf extends RExternalBuiltinNode { + @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().rApplRFFINode(); private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE; private static final RStringVector DQRCF_NAMES = RDataFactory.createStringVector(new String[]{E, E, E, E, E, E, "coef", "info"}, RDataFactory.COMPLETE_VECTOR); @@ -45,7 +47,7 @@ public final class Dqrcf extends RExternalBuiltinNode { double[] y = yVec.materialize().getDataTemp(); double[] b = bVec.materialize().getDataTemp(); int[] info = infoVec.materialize().getDataTemp(); - RFFIFactory.getRFFI().getRApplRFFI().dqrcf(x, n, k.getDataAt(0), qraux, y, ny, b, info); + rApplRFFINode.dqrcf(x, n, k.getDataAt(0), qraux, y, ny, b, info); RDoubleVector coef = RDataFactory.createDoubleVector(b, RDataFactory.COMPLETE_VECTOR); coef.copyAttributesFrom(attrProfiles, bVec); // @formatter:off diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java index fb842d465d81c176cdc1f5aeadaab8f3d07326c0..d1cac035699cd82ebef27232c8f901a9bdff7631 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java @@ -20,9 +20,11 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.ffi.RApplRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; public final class Dqrdc2 extends RExternalBuiltinNode { + @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().rApplRFFINode(); private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE; private static final RStringVector DQRDC2_NAMES = RDataFactory.createStringVector(new String[]{"qr", E, E, E, E, "rank", "qraux", "pivot", E}, RDataFactory.COMPLETE_VECTOR); @@ -44,7 +46,7 @@ public final class Dqrdc2 extends RExternalBuiltinNode { int[] rank = rankVec.materialize().getDataTemp(); double[] qraux = qrauxVec.materialize().getDataTemp(); int[] pivot = pivotVec.materialize().getDataTemp(); - RFFIFactory.getRFFI().getRApplRFFI().dqrdc2(x, ldx, n, p, tol, rank, qraux, pivot, workVec.materialize().getDataCopy()); + rApplRFFINode.dqrdc2(x, ldx, n, p, tol, rank, qraux, pivot, workVec.materialize().getDataCopy()); // @formatter:off Object[] data = new Object[]{ RDataFactory.createDoubleVector(x, RDataFactory.COMPLETE_VECTOR, xVec.getDimensions()), diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ExtractNativeCallInfoNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ExtractNativeCallInfoNode.java deleted file mode 100644 index 47d1f4a19c04070de6ce485cc2b780ee8f2bca86..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ExtractNativeCallInfoNode.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.r.nodes.builtin.base.foreign; - -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; -import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogical; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; -import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; -import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; - -/** - * Extracts the salient information needed for a native call from the {@link RList} value provided - * from R. - */ -public abstract class ExtractNativeCallInfoNode extends Node { - @Child private ExtractVectorNode nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - @Child private ExtractVectorNode addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - @Child private ExtractVectorNode packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - @Child private ExtractVectorNode infoExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - - protected abstract Object execute(VirtualFrame frame, RList symbol); - - @Specialization - protected Object extractNativeCallInfo(VirtualFrame frame, RList symbol) { - if (nameExtract == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - } - if (addressExtract == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - } - if (packageExtract == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - } - String name = RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name")); - SymbolHandle address = ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr(); - // field name may be "package" or "dll", but always at (R) index 3 - RList packageList = (RList) packageExtract.apply(frame, symbol, new Object[]{3}, RLogical.valueOf(false), RMissing.instance); - DLLInfo dllInfo = (DLLInfo) ((RExternalPtr) addressExtract.applyAccessField(frame, packageList, "info")).getExternalObject(); - return new NativeCallInfo(name, address, dllInfo); - - } - -} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java new file mode 100644 index 0000000000000000000000000000000000000000..af635ab2ccb0f6d77da60a71153212ff6c1d9f93 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java @@ -0,0 +1,282 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (c) 1995-2012, The R Core Team + * Copyright (c) 2003, The R Foundation + * Copyright (c) 2015, 2016, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.nodes.builtin.base.foreign; + +import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; + +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.ffi.CRFFI; +import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; + +/** + * {@code .C} and {@code .Fortran} functions, which share a common signature. + * + * TODO Completeness (more types, more error checks), Performance (copying). Especially all the + * subtleties around copying. + * + * See <a href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/Foreign.html">here</a>. + */ +public class FortranAndCFunctions { + + protected abstract static class CRFFIAdapter extends LookupAdapter { + private static final int SCALAR_DOUBLE = 0; + private static final int SCALAR_INT = 1; + private static final int SCALAR_LOGICAL = 2; + @SuppressWarnings("unused") private static final int SCALAR_STRING = 3; + private static final int VECTOR_DOUBLE = 10; + private static final int VECTOR_INT = 11; + private static final int VECTOR_LOGICAL = 12; + @SuppressWarnings("unused") private static final int VECTOR_STRING = 12; + + @Child private CRFFI.CRFFINode cRFFINode = RFFIFactory.getRFFI().getCRFFI().getCRFFINode(); + + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, RMissing.instance, RMissing.instance}; + } + + @TruffleBoundary + protected RList dispatch(RBuiltinNode node, NativeCallInfo nativeCallInfo, byte naok, byte dup, RArgsValuesAndNames args) { + @SuppressWarnings("unused") + boolean dupArgs = RRuntime.fromLogical(dup); + @SuppressWarnings("unused") + boolean checkNA = RRuntime.fromLogical(naok); + // Analyze the args, making copies (ignoring dup for now) + Object[] array = args.getArguments(); + int[] argTypes = new int[array.length]; + Object[] nativeArgs = new Object[array.length]; + for (int i = 0; i < array.length; i++) { + Object arg = array[i]; + if (arg instanceof RAbstractDoubleVector) { + argTypes[i] = VECTOR_DOUBLE; + nativeArgs[i] = checkNAs(node, i + 1, ((RAbstractDoubleVector) arg).materialize().getDataCopy()); + } else if (arg instanceof RAbstractIntVector) { + argTypes[i] = VECTOR_INT; + nativeArgs[i] = checkNAs(node, i + 1, ((RAbstractIntVector) arg).materialize().getDataCopy()); + } else if (arg instanceof RAbstractLogicalVector) { + argTypes[i] = VECTOR_LOGICAL; + // passed as int[] + byte[] data = ((RAbstractLogicalVector) arg).materialize().getDataWithoutCopying(); + int[] dataAsInt = new int[data.length]; + for (int j = 0; j < data.length; j++) { + // An NA is an error but the error handling happens in checkNAs + dataAsInt[j] = RRuntime.isNA(data[j]) ? RRuntime.INT_NA : data[j]; + } + nativeArgs[i] = checkNAs(node, i + 1, dataAsInt); + } else if (arg instanceof Double) { + argTypes[i] = SCALAR_DOUBLE; + nativeArgs[i] = checkNAs(node, i + 1, new double[]{(double) arg}); + } else if (arg instanceof Integer) { + argTypes[i] = SCALAR_INT; + nativeArgs[i] = checkNAs(node, i + 1, new int[]{(int) arg}); + } else if (arg instanceof Byte) { + argTypes[i] = SCALAR_LOGICAL; + nativeArgs[i] = checkNAs(node, i + 1, new int[]{RRuntime.isNA((byte) arg) ? RRuntime.INT_NA : (byte) arg}); + } else { + throw RError.error(node, RError.Message.UNIMPLEMENTED_ARG_TYPE, i + 1); + } + } + cRFFINode.invoke(nativeCallInfo, nativeArgs); + // we have to assume that the native method updated everything + RStringVector listNames = validateArgNames(array.length, args.getSignature()); + Object[] results = new Object[array.length]; + for (int i = 0; i < array.length; i++) { + switch (argTypes[i]) { + case SCALAR_DOUBLE: + results[i] = RDataFactory.createDoubleVector((double[]) nativeArgs[i], RDataFactory.COMPLETE_VECTOR); + break; + case SCALAR_INT: + results[i] = RDataFactory.createIntVector((int[]) nativeArgs[i], RDataFactory.COMPLETE_VECTOR); + break; + case SCALAR_LOGICAL: + // have to convert back from int[] + int[] nativeIntArgs = (int[]) nativeArgs[i]; + byte[] nativeByteArgs = new byte[nativeIntArgs.length]; + for (int j = 0; j < nativeByteArgs.length; j++) { + int nativeInt = nativeIntArgs[j]; + nativeByteArgs[j] = (byte) (nativeInt == RRuntime.INT_NA ? RRuntime.LOGICAL_NA : nativeInt & 0xFF); + } + results[i] = RDataFactory.createLogicalVector(nativeByteArgs, RDataFactory.COMPLETE_VECTOR); + break; + case VECTOR_DOUBLE: + results[i] = ((RAbstractDoubleVector) array[i]).materialize().copyResetData((double[]) nativeArgs[i]); + break; + case VECTOR_INT: + results[i] = ((RAbstractIntVector) array[i]).materialize().copyResetData((int[]) nativeArgs[i]); + break; + case VECTOR_LOGICAL: { + int[] intData = (int[]) nativeArgs[i]; + byte[] byteData = new byte[intData.length]; + for (int j = 0; j < intData.length; j++) { + byteData[j] = RRuntime.isNA(intData[j]) ? RRuntime.LOGICAL_NA : RRuntime.asLogical(intData[j] != 0); + } + results[i] = ((RAbstractLogicalVector) array[i]).materialize().copyResetData(byteData); + break; + } + } + } + return RDataFactory.createList(results, listNames); + } + + private static int[] checkNAs(RBuiltinNode node, int argIndex, int[] data) { + CompilerAsserts.neverPartOfCompilation(); + for (int i = 0; i < data.length; i++) { + if (RRuntime.isNA(data[i])) { + throw RError.error(node, RError.Message.NA_IN_FOREIGN_FUNCTION_CALL, argIndex); + } + } + return data; + } + + private static double[] checkNAs(RBuiltinNode node, int argIndex, double[] data) { + CompilerAsserts.neverPartOfCompilation(); + for (int i = 0; i < data.length; i++) { + if (!RRuntime.isFinite(data[i])) { + throw RError.error(node, RError.Message.NA_NAN_INF_IN_FOREIGN_FUNCTION_CALL, argIndex); + } + } + return data; + } + + private static RStringVector validateArgNames(int argsLength, ArgumentsSignature signature) { + String[] listArgNames = new String[argsLength]; + for (int i = 0; i < argsLength; i++) { + String name = signature.getName(i); + if (name == null) { + name = RRuntime.NAMES_ATTR_EMPTY_VALUE; + } + listArgNames[i] = name; + } + return RDataFactory.createStringVector(listArgNames, RDataFactory.COMPLETE_VECTOR); + } + + } + + /** + * Interface to .Fortran native functions. Some functions have explicit implementations in + * FastR, otherwise the .Fortran interface uses the machinery that implements the .C interface. + */ + @RBuiltin(name = ".Fortran", kind = PRIMITIVE, parameterNames = {".NAME", "...", "NAOK", "DUP", "PACKAGE", "ENCODING"}, behavior = COMPLEX) + public abstract static class Fortran extends CRFFIAdapter { + + @Override + @TruffleBoundary + protected RExternalBuiltinNode lookupBuiltin(RList symbol) { + switch (lookupName(symbol)) { + case "dqrdc2": + return new Dqrdc2(); + case "dqrcf": + return new Dqrcf(); + default: + return null; + } + } + + @SuppressWarnings("unused") + @Specialization(limit = "1", guards = {"cached == symbol", "builtin != null"}) + protected Object doExternal(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding, // + @Cached("symbol") RList cached, // + @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin) { + return builtin.call(frame, args); + } + + @Specialization(guards = "lookupBuiltin(symbol) == null") + protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage, + @SuppressWarnings("unused") RMissing encoding) { + NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + return dispatch(this, nativeCallInfo, naok, dup, args); + } + + @Specialization + protected RList c(RAbstractStringVector symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, @SuppressWarnings("unused") RMissing encoding, // + @Cached("create()") BranchProfile errorProfile) { + String libName = checkPackageArg(rPackage, errorProfile); + DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Fortran, null, null); + DLL.SymbolHandle func = DLL.findSymbol(symbol.getDataAt(0), libName, rns); + if (func == DLL.SYMBOL_NOT_FOUND) { + errorProfile.enter(); + throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol); + } + return dispatch(this, new NativeCallInfo(symbol.getDataAt(0), func, rns.getDllInfo()), naok, dup, args); + } + + @SuppressWarnings("unused") + @Fallback + protected Object fallback(Object symbol, Object args, Object naok, Object dup, Object rPackage, Object encoding) { + throw fallback(symbol); + } + } + + @RBuiltin(name = ".C", kind = PRIMITIVE, parameterNames = {".NAME", "...", "NAOK", "DUP", "PACKAGE", "ENCODING"}, behavior = COMPLEX) + public abstract static class DotC extends CRFFIAdapter { + + @Override + @TruffleBoundary + protected RExternalBuiltinNode lookupBuiltin(RList symbol) { + throw RInternalError.shouldNotReachHere(); + } + + @SuppressWarnings("unused") + @Specialization + protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding) { + NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + return dispatch(this, nativeCallInfo, naok, dup, args); + } + + @SuppressWarnings("unused") + @Specialization + protected RList c(RAbstractStringVector symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding, // + @Cached("create()") BranchProfile errorProfile) { + String libName = null; + if (!(rPackage instanceof RMissing)) { + libName = RRuntime.asString(rPackage); + if (libName == null) { + errorProfile.enter(); + throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE"); + } + } + DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.C, null, null); + DLL.SymbolHandle func = DLL.findSymbol(symbol.getDataAt(0), libName, rns); + if (func == DLL.SYMBOL_NOT_FOUND) { + errorProfile.enter(); + throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol); + } + return dispatch(this, new NativeCallInfo(symbol.getDataAt(0), func, rns.getDllInfo()), naok, dup, args); + } + + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..9569ccc557fd49addc15c425f2d5e320b3f2ad54 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.nodes.builtin.base.foreign; + +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.r.library.stats.StatsUtil; +import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; +import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapterFactory.ExtractNativeCallInfoNodeGen; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalCode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RExternalPtr; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RLogical; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; + +/** + * Locator for "builtin" package function implementations. The "builtin" packages contain many + * functions that are called from R code via the FFI, e.g. {@code .Call}, but implemented internally + * in GnuR, and not necessarily following the FFI API. The value passed to {@code .Call} etc., is a + * symbol, created when the package is loaded and stored in the namespace environment of the + * package, that is a list-valued object. Evidently these "builtins" are somewhat similar to the + * {@code .Primitive} and {@code .Internal} builtins and, similarly, most of these are + * re-implemented in Java in FastR. The {@link #lookupBuiltin(RList)} method checks the name in the + * list object and returns the {@link RExternalBuiltinNode} that implements the function, or + * {@code null}. A {@code null} result implies that the builtin is not implemented in Java, but + * called directly via the FFI interface, which is only possible for functions that use the FFI in a + * way that FastR can handle. + * + * This class also handles the "lookup" of the {@link NativeCallInfo} data for builtins that are + * still implemented by native code. + */ +abstract class LookupAdapter extends RBuiltinNode { + @Child private ExtractNativeCallInfoNode extractSymbolInfoNode = ExtractNativeCallInfoNodeGen.create(); + + protected static class UnimplementedExternal extends RExternalBuiltinNode { + private final String name; + + public UnimplementedExternal(String name) { + this.name = name; + } + + @Override + public final Object call(RArgsValuesAndNames args) { + throw RInternalError.unimplemented("unimplemented external builtin: " + name); + } + } + + protected abstract RExternalBuiltinNode lookupBuiltin(RList symbol); + + private static final String UNKNOWN_EXTERNAL_BUILTIN = "UNKNOWN_EXTERNAL_BUILTIN"; + + protected static String lookupName(RList symbol) { + CompilerAsserts.neverPartOfCompilation(); + if (symbol.getNames() != null) { + RAbstractStringVector names = symbol.getNames(); + for (int i = 0; i < names.getLength(); i++) { + if (names.getDataAt(i).equals("name")) { + String name = RRuntime.asString(symbol.getDataAt(i)); + return name != null ? name : UNKNOWN_EXTERNAL_BUILTIN; + } + } + } + return UNKNOWN_EXTERNAL_BUILTIN; + } + + @TruffleBoundary + protected RuntimeException fallback(Object symbol) { + String name = null; + if (symbol instanceof RList) { + name = lookupName((RList) symbol); + name = name == UNKNOWN_EXTERNAL_BUILTIN ? null : name; + if (name != null && lookupBuiltin((RList) symbol) != null) { + /* + * if we reach this point, then the cache saw a different value for f. the lists + * that contain the information about native calls are never expected to change. + */ + throw RInternalError.shouldNotReachHere("fallback reached for " + getRBuiltin().name() + " " + name); + } + } + throw RError.nyi(this, getRBuiltin().name() + " specialization failure: " + (name == null ? "<unknown>" : name)); + } + + protected NativeCallInfo extractSymbolInfo(VirtualFrame frame, RList symbol) { + return (NativeCallInfo) extractSymbolInfoNode.execute(frame, symbol); + } + + protected String checkPackageArg(Object rPackage, BranchProfile errorProfile) { + String libName = null; + if (!(rPackage instanceof RMissing)) { + libName = RRuntime.asString(rPackage); + if (libName == null) { + errorProfile.enter(); + throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE"); + } + } + return libName; + } + + /** + * Extracts the salient information needed for a native call from the {@link RList} value + * provided from R. + */ + public abstract static class ExtractNativeCallInfoNode extends Node { + @Child private ExtractVectorNode nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private ExtractVectorNode addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private ExtractVectorNode packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private ExtractVectorNode infoExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + + protected abstract Object execute(VirtualFrame frame, RList symbol); + + @Specialization + protected Object extractNativeCallInfo(VirtualFrame frame, RList symbol) { + if (nameExtract == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + } + if (addressExtract == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + } + if (packageExtract == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + } + String name = RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name")); + SymbolHandle address = ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr(); + // field name may be "package" or "dll", but always at (R) index 3 + RList packageList = (RList) packageExtract.apply(frame, symbol, new Object[]{3}, RLogical.valueOf(false), RMissing.instance); + DLLInfo dllInfo = (DLLInfo) ((RExternalPtr) addressExtract.applyAccessField(frame, packageList, "info")).getExternalObject(); + return new NativeCallInfo(name, address, dllInfo); + + } + } + + protected static RExternalBuiltinNode getExternalModelBuiltinNode(String name) { + return new RInternalCodeBuiltinNode(RContext.getInstance(), "stats", RInternalCode.loadSourceRelativeTo(StatsUtil.class, "model.R"), name); + } + + protected static final int CallNST = DLL.NativeSymbolType.Call.ordinal(); + protected static final int ExternalNST = DLL.NativeSymbolType.External.ordinal(); + + public static DLL.RegisteredNativeSymbol createRegisteredNativeSymbol(int nstOrd) { + // DSL cannot resolve DLL.DLL.NativeSymbolType + DLL.NativeSymbolType nst = DLL.NativeSymbolType.values()[nstOrd]; + return new DLL.RegisteredNativeSymbol(nst, null, null); + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java index 07719a305b4ca2937b7dbd2d4a5cb64eddebc9b0..81767da8e0d65ae564317aac007716c30fede1f5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java @@ -30,6 +30,7 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.ffi.RApplRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; /** @@ -38,6 +39,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory; */ @RBuiltin(name = ".fastr.dqrls", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x", "n", "p", "y", "ny", "tol", "coeff"}, behavior = PURE) public abstract class FastrDqrls extends RBuiltinNode { + @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().rApplRFFINode(); private static final String[] NAMES = new String[]{"qr", "coefficients", "residuals", "effects", "rank", "pivot", "qraux", "tol", "pivoted"}; private static RStringVector namesVector = null; @@ -82,7 +84,7 @@ public abstract class FastrDqrls extends RBuiltinNode { pivot[i] = i + 1; } - RFFIFactory.getRFFI().getRApplRFFI().dqrls(x, n, p, y, ny, tol, coeff, residuals, effects, rank, pivot, qraux, work); + rApplRFFINode.dqrls(x, n, p, y, ny, tol, coeff, residuals, effects, rank, pivot, qraux, work); RDoubleVector resultCoeffVect = RDataFactory.createDoubleVector(coeff, RDataFactory.COMPLETE_VECTOR); resultCoeffVect.copyAttributesFrom(coeffAttributeProfiles, coeffVec); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java index 8e1df26de4542db1e598d98cda69db08fc4ffd12..f44263215c268e63a6344ef7b65906778e93d5a8 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.ffi.generic; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.ffi.CallRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.GridRFFI; @@ -32,46 +33,55 @@ import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; public class Generic_Grid implements GridRFFI { - private static final class GridProvider { - private static GridProvider grid; - private static DLL.SymbolHandle initGrid; - private static DLL.SymbolHandle killGrid; + private static class Generic_GridRFFINode extends GridRFFINode { + private CallRFFI.CallRFFINode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().callRFFINode(); - @TruffleBoundary - private GridProvider() { - System.load(LibPaths.getPackageLibPath("grid")); - initGrid = DLL.findSymbol("L_initGrid", "grid", DLL.RegisteredNativeSymbol.any()); - killGrid = DLL.findSymbol("L_killGrid", "grid", DLL.RegisteredNativeSymbol.any()); - assert initGrid != DLL.SYMBOL_NOT_FOUND && killGrid != DLL.SYMBOL_NOT_FOUND; - } + private static final class GridProvider { + private static GridProvider grid; + private static DLL.SymbolHandle initGrid; + private static DLL.SymbolHandle killGrid; - static GridProvider gridProvider() { - if (grid == null) { - grid = new GridProvider(); + @TruffleBoundary + private GridProvider() { + System.load(LibPaths.getPackageLibPath("grid")); + initGrid = DLL.findSymbol("L_initGrid", "grid", DLL.RegisteredNativeSymbol.any()); + killGrid = DLL.findSymbol("L_killGrid", "grid", DLL.RegisteredNativeSymbol.any()); + assert initGrid != DLL.SYMBOL_NOT_FOUND && killGrid != DLL.SYMBOL_NOT_FOUND; + } + + static GridProvider gridProvider() { + if (grid == null) { + grid = new GridProvider(); + } + return grid; + } + + @SuppressWarnings("static-method") + long getInitGrid() { + return initGrid.asAddress(); } - return grid; - } - @SuppressWarnings("static-method") - long getInitGrid() { - return initGrid.asAddress(); + @SuppressWarnings("static-method") + long getKillGrid() { + return killGrid.asAddress(); + } } - @SuppressWarnings("static-method") - long getKillGrid() { - return killGrid.asAddress(); + @Override + public Object initGrid(REnvironment gridEvalEnv) { + long initGrid = GridProvider.gridProvider().getInitGrid(); + return callRFFINode.invokeCall(new NativeCallInfo("L_initGrid", new SymbolHandle(initGrid), DLL.findLibrary("grid")), new Object[]{gridEvalEnv}); } - } - @Override - public Object initGrid(REnvironment gridEvalEnv) { - long initGrid = GridProvider.gridProvider().getInitGrid(); - return RFFIFactory.getRFFI().getCallRFFI().callRFFINode().invokeCall(new NativeCallInfo("L_initGrid", new SymbolHandle(initGrid), DLL.findLibrary("grid")), new Object[]{gridEvalEnv}); + @Override + public Object killGrid() { + long killGrid = GridProvider.gridProvider().getKillGrid(); + return callRFFINode.invokeCall(new NativeCallInfo("L_killGrid", new SymbolHandle(killGrid), DLL.findLibrary("grid")), new Object[0]); + } } @Override - public Object killGrid() { - long killGrid = GridProvider.gridProvider().getKillGrid(); - return RFFIFactory.getRFFI().getCallRFFI().callRFFINode().invokeCall(new NativeCallInfo("L_killGrid", new SymbolHandle(killGrid), DLL.findLibrary("grid")), new Object[0]); + public GridRFFINode gridRFFINode() { + return new Generic_GridRFFINode(); } } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java index bd5724e4bb19ed8cfde6c34cb4804872ebd91cb0..a7d4a797d516586fcb2b64369b4487be785948d0 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java @@ -30,6 +30,7 @@ import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.ffi.CallRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.LibPaths; @@ -38,46 +39,59 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.ffi.ToolsRFFI; public class Generic_Tools implements ToolsRFFI { - private static final class ToolsProvider { - private static final String C_PARSE_RD = "C_parseRd"; - private static ToolsProvider tools; - private static DLL.SymbolHandle parseRd; + private static class Generic_ToolsRFFINode extends ToolsRFFINode { + private CallRFFI.CallRFFINode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().callRFFINode(); - @TruffleBoundary - private ToolsProvider() { - System.load(LibPaths.getPackageLibPath("tools")); - parseRd = DLL.findSymbol(C_PARSE_RD, "tools", DLL.RegisteredNativeSymbol.any()); - assert parseRd != DLL.SYMBOL_NOT_FOUND; - } + private static final class ToolsProvider { + private static final String C_PARSE_RD = "C_parseRd"; + private static ToolsProvider tools; + private static DLL.SymbolHandle parseRd; + + @TruffleBoundary + private ToolsProvider() { + System.load(LibPaths.getPackageLibPath("tools")); + parseRd = DLL.findSymbol(C_PARSE_RD, "tools", DLL.RegisteredNativeSymbol.any()); + assert parseRd != DLL.SYMBOL_NOT_FOUND; + } + + static ToolsProvider toolsProvider() { + if (tools == null) { + tools = new ToolsProvider(); + } + return tools; + } - static ToolsProvider toolsProvider() { - if (tools == null) { - tools = new ToolsProvider(); + @SuppressWarnings("static-method") + long getParseRd() { + return parseRd.asAddress(); } - return tools; } - @SuppressWarnings("static-method") - long getParseRd() { - return parseRd.asAddress(); + private static final Semaphore parseRdCritical = new Semaphore(1, false); + private NativeCallInfo nativeCallInfo; + + @Override + public Object parseRd(RConnection con, REnvironment srcfile, RLogicalVector verbose, RLogicalVector fragment, RStringVector basename, RLogicalVector warningCalls, Object macros, + RLogicalVector warndups) { + // The C code is not thread safe. + try { + parseRdCritical.acquire(); + long parseRd = ToolsProvider.toolsProvider().getParseRd(); + if (nativeCallInfo == null) { + nativeCallInfo = new NativeCallInfo("parseRd", new SymbolHandle(parseRd), DLL.findLibrary("tools")); + } + return callRFFINode.invokeCall(nativeCallInfo, + new Object[]{con, srcfile, verbose, fragment, basename, warningCalls, macros, warndups}); + } catch (Throwable ex) { + throw RInternalError.shouldNotReachHere(ex, "error during Rd parsing"); + } finally { + parseRdCritical.release(); + } } } - private static final Semaphore parseRdCritical = new Semaphore(1, false); - @Override - public Object parseRd(RConnection con, REnvironment srcfile, RLogicalVector verbose, RLogicalVector fragment, RStringVector basename, RLogicalVector warningCalls, Object macros, - RLogicalVector warndups) { - // The C code is not thread safe. - try { - parseRdCritical.acquire(); - long parseRd = ToolsProvider.toolsProvider().getParseRd(); - return RFFIFactory.getRFFI().getCallRFFI().callRFFINode().invokeCall(new NativeCallInfo("parseRd", new SymbolHandle(parseRd), DLL.findLibrary("tools")), - new Object[]{con, srcfile, verbose, fragment, basename, warningCalls, macros, warndups}); - } catch (Throwable ex) { - throw RInternalError.shouldNotReachHere(ex, "error during Rd parsing"); - } finally { - parseRdCritical.release(); - } + public ToolsRFFINode toolsRFFINode() { + return new Generic_ToolsRFFINode(); } } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java index 1928c09f73d4053f518cb777a1c8257b78451ae6..13092011133a88a6f06d7c522d8694b2cc92518f 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java @@ -30,21 +30,27 @@ import com.oracle.truffle.r.runtime.ffi.CRFFI; import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; public class JNI_C implements CRFFI { - - /** - * This is rather similar to {@link JNI_Call}, except the objects are guaranteed to be native - * array types, no upcalls are possible, and no result is returned. However, the receiving - * function expects actual native arrays (not SEXPs), so these have to be handled on the JNI - * side. - */ - @Override - @TruffleBoundary - public synchronized void invoke(NativeCallInfo nativeCallInfo, Object[] args) { - if (traceEnabled()) { - traceDownCall(nativeCallInfo.name, args); + private static class JNI_CRFFINode extends CRFFINode { + /** + * This is rather similar to {@link JNI_Call}, except the objects are guaranteed to be + * native array types, no upcalls are possible, and no result is returned. However, the + * receiving function expects actual native arrays (not SEXPs), so these have to be handled + * on the JNI side. + */ + @Override + @TruffleBoundary + public synchronized void invoke(NativeCallInfo nativeCallInfo, Object[] args) { + if (traceEnabled()) { + traceDownCall(nativeCallInfo.name, args); + } + c(nativeCallInfo.address.asAddress(), args); } - c(nativeCallInfo.address.asAddress(), args); } private static native void c(long address, Object[] args); + + @Override + public CRFFINode getCRFFINode() { + return new JNI_CRFFINode(); + } } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java index 8a36622c131f5246cb1e0183991db17dbd4863f4..f39d93925ece061d526918cda5dd6933dec4b809 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java @@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.ffi.UpCallsRFFIFactory; */ public class JNI_Call implements CallRFFI { - public static class JNI_CallRFFINode extends CallRFFINode { + private static class JNI_CallRFFINode extends CallRFFINode { @Override @TruffleBoundary diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java index e6d37de0f1f956b90a964530f09c98c501ab724e..6550897121e2872e3904231456e8e42fc25a22b2 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java @@ -26,77 +26,85 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.LapackRFFI; public class JNI_Lapack implements LapackRFFI { - @Override - @TruffleBoundary - public void ilaver(int[] version) { - native_ilaver(version); - } - - @Override - @TruffleBoundary - public int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) { - return native_dgeev(jobVL, jobVR, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork); - } - - @Override - @TruffleBoundary - public int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) { - return native_dgeqp3(m, n, a, lda, jpvt, tau, work, lwork); - } - - @Override - @TruffleBoundary - public int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) { - return native_dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork); - } - - @Override - @TruffleBoundary - public int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) { - return native_dtrtrs(uplo, trans, diag, n, nrhs, a, lda, b, ldb); - } - - @Override - @TruffleBoundary - public int dgetrf(int m, int n, double[] a, int lda, int[] ipiv) { - return native_dgetrf(m, n, a, lda, ipiv); - } - - @Override - @TruffleBoundary - public int dpotrf(char uplo, int n, double[] a, int lda) { - return native_dpotrf(uplo, n, a, lda); + private static class JNI_LapackRFFINode extends LapackRFFINode { + @Override + @TruffleBoundary + public void ilaver(int[] version) { + native_ilaver(version); + } + + @Override + @TruffleBoundary + public int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) { + return native_dgeev(jobVL, jobVR, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork); + } + + @Override + @TruffleBoundary + public int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) { + return native_dgeqp3(m, n, a, lda, jpvt, tau, work, lwork); + } + + @Override + @TruffleBoundary + public int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) { + return native_dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork); + } + + @Override + @TruffleBoundary + public int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) { + return native_dtrtrs(uplo, trans, diag, n, nrhs, a, lda, b, ldb); + } + + @Override + @TruffleBoundary + public int dgetrf(int m, int n, double[] a, int lda, int[] ipiv) { + return native_dgetrf(m, n, a, lda, ipiv); + } + + @Override + @TruffleBoundary + public int dpotrf(char uplo, int n, double[] a, int lda) { + return native_dpotrf(uplo, n, a, lda); + } + + @Override + @TruffleBoundary + public int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) { + return native_dpstrf(uplo, n, a, lda, piv, rank, tol, work); + } + + @Override + @TruffleBoundary + public int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) { + return native_dgesv(n, nrhs, a, lda, ipiv, b, ldb); + } + + @Override + @TruffleBoundary + public double dlange(char norm, int m, int n, double[] a, int lda, double[] work) { + return native_dlange(norm, m, n, a, lda, work); + } + + @Override + @TruffleBoundary + public int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) { + return native_dgecon(norm, n, a, lda, anorm, rcond, work, iwork); + } + + @Override + public int dsyevr(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, + double[] w, double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork) { + return native_dsyevr(jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, isuppz, work, lwork, iwork, liwork); + } } @Override - @TruffleBoundary - public int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) { - return native_dpstrf(uplo, n, a, lda, piv, rank, tol, work); + public LapackRFFINode getLapackRFFINode() { + return new JNI_LapackRFFINode(); } - @Override - @TruffleBoundary - public int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) { - return native_dgesv(n, nrhs, a, lda, ipiv, b, ldb); - } - - @Override - @TruffleBoundary - public double dlange(char norm, int m, int n, double[] a, int lda, double[] work) { - return native_dlange(norm, m, n, a, lda, work); - } - - @Override - @TruffleBoundary - public int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) { - return native_dgecon(norm, n, a, lda, anorm, rcond, work, iwork); - } - - @Override - public int dsyevr(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, - double[] w, double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork) { - return native_dsyevr(jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, isuppz, work, lwork, iwork, liwork); - } // Checkstyle: stop method name private static native void native_ilaver(int[] version); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java index dda34a3c1896e369eb8799ffdd981cb4129d8688..cfad8dc4d53dd71361b00604d684f8cd5b28dde9 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java @@ -28,45 +28,47 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.ffi.PCRERFFI; public class JNI_PCRE implements PCRERFFI { - @Override - public long maketables() { - return nativeMaketables(); - } + private static class JNI_PCRERFFINode extends PCRERFFINode { + @Override + public long maketables() { + return nativeMaketables(); + } - @Override - public Result compile(String pattern, int options, long tables) { - return nativeCompile(pattern, options, tables); - } + @Override + public Result compile(String pattern, int options, long tables) { + return nativeCompile(pattern, options, tables); + } - @Override - public int getCaptureCount(long code, long extra) { - int res = nativeGetCaptureCount(code, extra); - if (res < 0) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, res); + @Override + public int getCaptureCount(long code, long extra) { + int res = nativeGetCaptureCount(code, extra); + if (res < 0) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, res); + } + return res; } - return res; - } - @Override - public String[] getCaptureNames(long code, long extra, int captureCount) { - String[] ret = new String[captureCount]; - int res = nativeGetCaptureNames(code, extra, ret); - if (res < 0) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, res); + @Override + public String[] getCaptureNames(long code, long extra, int captureCount) { + String[] ret = new String[captureCount]; + int res = nativeGetCaptureNames(code, extra, ret); + if (res < 0) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, res); + } + return ret; } - return ret; - } - @Override - public Result study(long code, int options) { - throw RInternalError.unimplemented("pcre_study"); - } + @Override + public Result study(long code, int options) { + throw RInternalError.unimplemented("pcre_study"); + } - @Override - public int exec(long code, long extra, String subject, int offset, int options, int[] ovector) { - return nativeExec(code, extra, subject, offset, options, ovector, ovector.length); + @Override + public int exec(long code, long extra, String subject, int offset, int options, int[] ovector) { + return nativeExec(code, extra, subject, offset, options, ovector, ovector.length); + } } private static native long nativeMaketables(); @@ -80,4 +82,9 @@ public class JNI_PCRE implements PCRERFFI { private static native int nativeExec(long code, long extra, String subject, int offset, int options, int[] ovector, int ovectorLen); + @Override + public PCRERFFINode pcreRFFINode() { + return new JNI_PCRERFFINode(); + } + } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java index b48a2fa9c113c12f68a2632ee147f1b3c55c4287..84e9f41389ea11c075246182b01961df103c41c7 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java @@ -26,24 +26,30 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.RApplRFFI; public class JNI_RAppl implements RApplRFFI { - @Override - @TruffleBoundary - public void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) { - native_dqrdc2(x, ldx, n, p, tol, rank, qraux, pivot, work); + private static class JNI_RApplRFFINode extends RApplRFFINode { + @Override + @TruffleBoundary + public void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) { + native_dqrdc2(x, ldx, n, p, tol, rank, qraux, pivot, work); + } + + @Override + @TruffleBoundary + public void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) { + native_dqrcf(x, n, k, qraux, y, ny, b, info); + } + + @Override + @TruffleBoundary + public void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) { + native_dqrls(x, n, p, y, ny, tol, b, rsd, qty, k, jpvt, qraux, work); + } } @Override - @TruffleBoundary - public void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) { - native_dqrcf(x, n, k, qraux, y, ny, b, info); + public RApplRFFINode rApplRFFINode() { + return new JNI_RApplRFFINode(); } - - @Override - @TruffleBoundary - public void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) { - native_dqrls(x, n, p, y, ny, tol, b, rsd, qty, k, jpvt, qraux, work); - } - // Checkstyle: stop method name private static native void native_dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java index 1387cb869aaaa5c1a8f649187c2aa27cf7d4a24d..d3df6fab2cec55f4abe60efa82b11b30dcdd99fc 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java @@ -27,36 +27,44 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.UserRngRFFI; public class JNI_UserRng implements UserRngRFFI { - @Override - @TruffleBoundary - public void init(int seed) { - init(Function.Init.getSymbolHandle().asAddress(), seed); + private static class JNI_UserRngRFFINode extends UserRngRFFINode { + @Override + @TruffleBoundary + public void init(int seed) { + nativeInit(Function.Init.getSymbolHandle().asAddress(), seed); - } + } - @Override - @TruffleBoundary - public double rand() { - return rand(Function.Rand.getSymbolHandle().asAddress()); - } + @Override + @TruffleBoundary + public double rand() { + return nativeRand(Function.Rand.getSymbolHandle().asAddress()); + } - @Override - @TruffleBoundary - public int nSeed() { - return nSeed(Function.NSeed.getSymbolHandle().asAddress()); + @Override + @TruffleBoundary + public int nSeed() { + return nativeNSeed(Function.NSeed.getSymbolHandle().asAddress()); + } + + @Override + @TruffleBoundary + public void seeds(int[] n) { + nativeSeeds(Function.Seedloc.getSymbolHandle().asAddress(), n); + } } @Override - @TruffleBoundary - public void seeds(int[] n) { - seeds(Function.Seedloc.getSymbolHandle().asAddress(), n); + public UserRngRFFINode userRngRFFINode() { + return new JNI_UserRngRFFINode(); } - private static native void init(long address, int seed); + private static native void nativeInit(long address, int seed); + + private static native double nativeRand(long address); - private static native double rand(long address); + private static native int nativeNSeed(long address); - private static native int nSeed(long address); + private static native void nativeSeeds(long address, int[] n); - private static native void seeds(long address, int[] n); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java index 24cdcd702ad4a17447951e0f3aff6fbf9f5267fc..25fa782b9c8939f4717495b7b6a312bdcc6416e1 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java @@ -22,14 +22,20 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.api.nodes.Node; + /** * Support for the {.C} and {.Fortran} calls. */ public interface CRFFI { - /** - * Invoke the native method identified by {@code symbolInfo} passing it the arguments in - * {@code args}. The values in {@code args} should be native types,e.g., {@code double[]} not - * {@code RDoubleVector}. - */ - void invoke(NativeCallInfo nativeCallInfo, Object[] args); + abstract class CRFFINode extends Node { + /** + * Invoke the native method identified by {@code symbolInfo} passing it the arguments in + * {@code args}. The values in {@code args} should be native types,e.g., {@code double[]} + * not {@code RDoubleVector}. + */ + public abstract void invoke(NativeCallInfo nativeCallInfo, Object[] args); + } + + CRFFINode getCRFFINode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java index 5930f8d17e6230d6fcb82bb00047a2a5e72bf881..a773e43a2fc7d8d6af75ded36a1c99cb23c42971 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java @@ -28,7 +28,7 @@ import com.oracle.truffle.api.nodes.Node; * Support for the {.Call} and {.External} calls. */ public interface CallRFFI { - public abstract static class CallRFFINode extends Node { + abstract class CallRFFINode extends Node { /** * Invoke the native function identified by {@code symbolInfo} passing it the arguments in * {@code args}. The values in {@code args} can be any of the types used to represent diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java index 561ba671024c66baf1db51eacd3776bc0b218778..f413af683385fc1a4e029e7c9df982189261cd0c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java @@ -22,10 +22,15 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.runtime.env.REnvironment; public interface GridRFFI { - Object initGrid(REnvironment gridEvalEnv); + abstract class GridRFFINode extends Node { + public abstract Object initGrid(REnvironment gridEvalEnv); - Object killGrid(); + public abstract Object killGrid(); + } + + GridRFFINode gridRFFINode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java index 9d537ec5006221e9796736eaf19bc85e645631c0..306186a614732b107b6f5bd119ede7fde980fe78 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java @@ -22,67 +22,73 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.api.nodes.Node; + /** * Collection of statically typed Lapack methods that are used in the {@code base} package. The * signatures match the Fortran definition with the exception that the "info" value is returned as * the result of the call. */ public interface LapackRFFI { - /** - * Return version info, mjor, minor, patch, in {@code version}. - */ - void ilaver(int[] version); + abstract class LapackRFFINode extends Node { + /** + * Return version info, mjor, minor, patch, in {@code version}. + */ + public abstract void ilaver(int[] version); + + /** + * See <a href="http://www.netlib.org/lapack/explore-html/d9/d28/dgeev_8f.html">spec</a>. + */ + public abstract int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/d9/d28/dgeev_8f.html">spec</a>. - */ - int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork); + /** + * See <a href="http://www.netlib.org/lapack/explore-html/db/de5/dgeqp3_8f.html">spec</a>. + */ + public abstract int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/db/de5/dgeqp3_8f.html">spec</a>. - */ - int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork); + /** + * See <a href="http://www.netlib.org/lapack/explore-html/da/d82/dormqr_8f.html">spec</a>. + */ + public abstract int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/da/d82/dormqr_8f.html">spec</a>. - */ - int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork); + /** + * See <a href="http://www.netlib.org/lapack/explore-html/d6/d6f/dtrtrs_8f.html">spec</a>. + */ + public abstract int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/d6/d6f/dtrtrs_8f.html">spec</a>. - */ - int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb); + /** + * See <a href="http://www.netlib.org/lapack/explore-html/d3/d6a/dgetrf_8f.html">spec</a>. + */ + public abstract int dgetrf(int m, int n, double[] a, int lda, int[] ipiv); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/d3/d6a/dgetrf_8f.html">spec</a>. - */ - int dgetrf(int m, int n, double[] a, int lda, int[] ipiv); + /** + * See <a href="http://www.netlib.org/lapack/explore-html/d0/d8a/dpotrf_8f.html">spec</a>. + */ + public abstract int dpotrf(char uplo, int n, double[] a, int lda); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/d0/d8a/dpotrf_8f.html">spec</a>. - */ - int dpotrf(char uplo, int n, double[] a, int lda); + /** + * See <a href="http://www.netlib.org/lapack/explore-html/dd/dad/dpstrf_8f.html">spec</a>. + */ + public abstract int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/dd/dad/dpstrf_8f.html">spec</a>. - */ - int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work); + /** + * See <a href="http://www.netlib.org/lapack/explore-html/d8/d72/dgesv_8f.html">spec</a>. + */ + public abstract int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/d8/d72/dgesv_8f.html">spec</a>. - */ - int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb); + /** + * See <a href="http://www.netlib.org/lapack/explore-html/dc/d09/dlange_8f.html">spec</a>. + */ + public abstract double dlange(char norm, int m, int n, double[] a, int lda, double[] work); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/dc/d09/dlange_8f.html">spec</a>. - */ - double dlange(char norm, int m, int n, double[] a, int lda, double[] work); + /** + * See <a href="http://www.netlib.org/lapack/explore-html/db/de4/dgecon_8f.html">spec</a>. + */ + public abstract int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork); - /** - * See <a href="http://www.netlib.org/lapack/explore-html/db/de4/dgecon_8f.html">spec</a>. - */ - int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork); + public abstract int dsyevr(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, + double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork); + } - int dsyevr(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, - double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork); + LapackRFFINode getLapackRFFINode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java index 1825446c61a5d71aa069c44c0460febb2b902922..81a91ecb1dd6fc3fb695490d70743683550d32a6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.api.nodes.Node; + /** * An interface to the <a href="http://www.pcre.org/original/doc/html/index.html">PCRE</a> library * for Perl regular expressions. @@ -47,16 +49,21 @@ public interface PCRERFFI { } } - long maketables(); + abstract class PCRERFFINode extends Node { + + public abstract long maketables(); - Result compile(String pattern, int options, long tables); + public abstract Result compile(String pattern, int options, long tables); - int getCaptureCount(long code, long extra); + public abstract int getCaptureCount(long code, long extra); - String[] getCaptureNames(long code, long extra, int captureCount); + public abstract String[] getCaptureNames(long code, long extra, int captureCount); - Result study(long code, int options); + public abstract Result study(long code, int options); + + public abstract int exec(long code, long extra, String subject, int offset, int options, int[] ovector); + } - int exec(long code, long extra, String subject, int offset, int options, int[] ovector); + PCRERFFINode pcreRFFINode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java index 4f20c85d9b914cd51b4ae9ef42aa7da45a300317..bc40f240118696438a50e3bb626e0b2501351e3a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java @@ -22,17 +22,23 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.api.nodes.Node; + /** * Collection of statically typed methods (from Linpack and elsewhere) that are built in to a GnuR * implementation and factored out into a separate library in FastR. This corresponds to the * {@code libappl} library in GnuR. */ public interface RApplRFFI { - // Linpack - void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work); + abstract class RApplRFFINode extends Node { + // Linpack + public abstract void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work); + + public abstract void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info); - void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info); + public abstract void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work); + } - void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work); + RApplRFFINode rApplRFFINode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StatsRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StatsRFFI.java index a6940fbd86b4969722001e7e4257765d43252746..6e4d58f145b96e6a330566e47c53d54e9842dfeb 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StatsRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StatsRFFI.java @@ -30,7 +30,7 @@ import com.oracle.truffle.api.nodes.Node; * {@code fft_factor} and {@code fft_work}. functions from the GNU R C code. */ public interface StatsRFFI { - public abstract static class FFTNode extends Node { + abstract class FFTNode extends Node { public abstract void executeFactor(int n, int[] pmaxf, int[] pmaxp); public abstract int executeWork(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ToolsRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ToolsRFFI.java index 04bc7e21a310117776602427c0dee389e3154b6b..85538d2347d6d48776c8adab362c2db9ff192377 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ToolsRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ToolsRFFI.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RStringVector; @@ -31,14 +32,18 @@ import com.oracle.truffle.r.runtime.env.REnvironment; * Interface to native (C) methods provided by the {@code tools} package. */ public interface ToolsRFFI { - /** - * This invokes the Rd parser, written in C, and part of GnuR, that does its work using the R - * FFI interface. The R code initially invokes this via {@code .External2(C_parseRd, ...)}, - * which has a custom specialization in the implementation of the {@code .External2} builtin. - * That does some work in Java, and then calls this method to invoke the actual C code. We can't - * go straight to the GnuR C entry point as that makes GnuR-specific assumptions about, for - * example, how connections are implemented. - */ - Object parseRd(RConnection con, REnvironment srcfile, RLogicalVector verbose, RLogicalVector fragment, RStringVector basename, RLogicalVector warningCalls, Object macros, - RLogicalVector warndups); + abstract class ToolsRFFINode extends Node { + /** + * This invokes the Rd parser, written in C, and part of GnuR, that does its work using the + * R FFI interface. The R code initially invokes this via {@code .External2(C_parseRd, ...)} + * , which has a custom specialization in the implementation of the {@code .External2} + * builtin. That does some work in Java, and then calls this method to invoke the actual C + * code. We can't go straight to the GnuR C entry point as that makes GnuR-specific + * assumptions about, for example, how connections are implemented. + */ + public abstract Object parseRd(RConnection con, REnvironment srcfile, RLogicalVector verbose, RLogicalVector fragment, RStringVector basename, RLogicalVector warningCalls, Object macros, + RLogicalVector warndups); + } + + ToolsRFFINode toolsRFFINode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java index dc692727fcfe6b46100e854a859d63ec0abaa700..569540ed503d52b74af5861cfab8276f66a275a7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java @@ -22,17 +22,23 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.api.nodes.Node; + /** * Explicit statically typed interface to user-supplied random number generators. */ public interface UserRngRFFI { + abstract class UserRngRFFINode extends Node { + + public abstract void init(int seed); - void init(int seed); + public abstract double rand(); - double rand(); + public abstract int nSeed(); - int nSeed(); + public abstract void seeds(int[] n); + } - void seeds(int[] n); + UserRngRFFINode userRngRFFINode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java index 84187071f92296f69c96bec987616bcefd1d0270..b209867c61113a26a4bd9f902f9a66675a84a2ae 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java @@ -66,8 +66,15 @@ public final class UserRNG implements RandomNumberGenerator { } - private UserRngRFFI userRngRFFI; private int nSeeds = 0; + private UserRngRFFI.UserRngRFFINode userRngRFFINode; + + private UserRngRFFI.UserRngRFFINode getUserRngRFFINode() { + if (userRngRFFINode == null) { + userRngRFFINode = RFFIFactory.getRFFI().getUserRngRFFI().userRngRFFINode(); + } + return userRngRFFINode; + } @Override @TruffleBoundary @@ -79,15 +86,14 @@ public final class UserRNG implements RandomNumberGenerator { for (Function f : Function.values()) { f.setSymbolHandle(dllInfo); } - userRngRFFI = RFFIFactory.getRFFI().getUserRngRFFI(); if (Function.Init.isDefined()) { - userRngRFFI.init(seed); + getUserRngRFFINode().init(seed); } if (Function.Seedloc.isDefined() && !Function.NSeed.isDefined()) { RError.warning(RError.NO_CALLER, RError.Message.RNG_READ_SEEDS); } if (Function.NSeed.isDefined()) { - int ns = userRngRFFI.nSeed(); + int ns = getUserRngRFFINode().nSeed(); if (ns < 0 || ns > 625) { RError.warning(RError.NO_CALLER, RError.Message.GENERIC, "seed length must be in 0...625; ignored"); } else { @@ -125,7 +131,7 @@ public final class UserRNG implements RandomNumberGenerator { return null; } int[] seeds = new int[nSeeds]; - userRngRFFI.seeds(seeds); + getUserRngRFFINode().seeds(seeds); int[] result = new int[nSeeds + 1]; System.arraycopy(seeds, 0, result, 1, seeds.length); return result; @@ -133,7 +139,7 @@ public final class UserRNG implements RandomNumberGenerator { @Override public double genrandDouble() { - return userRngRFFI.rand(); + return getUserRngRFFINode().rand(); } @Override diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index 34b4bca629f2ceea3857c3c258899c620e4673e9..7dabf754391dcb6c7cc52860c0a2089c3779e868 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -154,7 +154,8 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/f com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java,gnu_r.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java,gnu_r.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Flushconsole.java,gnu_r.copyright -com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java,gnu_r.copyright +com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java,gnu_r.copyright +com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java,gnu_r.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/MakeQuartzDefault.java,gnu_r.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java,gnu_r.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dnorm4.java,gnu_r.copyright