Skip to content

Commit 9d03a7b

Browse files
committed
[GR-26520] Implement match5, IS_LONG_VEC, fix dyn symbol loading, minor perf. improvement in rand functions.
PullRequest: fastr/2462
2 parents 26a336e + 6f33afb commit 9d03a7b

File tree

20 files changed

+430
-359
lines changed

20 files changed

+430
-359
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ New features:
1111
* ALTREP specific C API, e.g., `INTEGER_IS_SORTED`
1212
* serialization and deserialization of custom ALTREP objects is not supported yet
1313

14+
Added missing R builtins and C APIs:
15+
16+
* non-API C function match5, which is used by some packages
17+
* non-API C function `match5`, which is used by some packages (#149)
18+
* define dummy `XLENGTH` macro if `USE_RINTERNALS` is defined
19+
* non-existence of this macro is used by some packages to detect old R versions
20+
* `IS_LONG_VEC` C API function
21+
* when loading native symbol dynamically, FastR also checks the name with trailing underscode to be compatible with GNU-R
22+
1423
# 20.2.0
1524

1625
Bug fixes:

ci.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ overlay : '06028bf33eaa66698cffa99e1cb920694d68977e' }
1+
{ overlay : '657555ba0ca3d65cda3d9b536343d0bff5f99f5c' }

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2697,7 +2697,7 @@ public Object Rf_asCharacterFactor(Object x) {
26972697
}
26982698

26992699
@Override
2700-
public Object Rf_match(Object itables, Object ix, int nmatch) {
2700+
public Object match5(Object itables, Object ix, int nmatch, Object incomparables, Object env) {
27012701
throw implementedAsNode();
27022702
}
27032703

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MatchNodes.java

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,44 +22,31 @@
2222
*/
2323
package com.oracle.truffle.r.ffi.impl.nodes;
2424

25-
import com.oracle.truffle.api.CompilerDirectives;
25+
import com.oracle.truffle.api.dsl.Cached;
2626
import com.oracle.truffle.api.dsl.Fallback;
2727
import com.oracle.truffle.api.dsl.GenerateUncached;
2828
import com.oracle.truffle.api.dsl.Specialization;
2929
import com.oracle.truffle.api.dsl.TypeSystemReference;
3030
import com.oracle.truffle.r.ffi.impl.nodes.MatchNodesFactory.NonNullStringMatchNodeGen;
31-
import com.oracle.truffle.r.nodes.builtin.MatchInternalNode;
32-
import com.oracle.truffle.r.nodes.builtin.MatchInternalNodeGen;
33-
import com.oracle.truffle.r.runtime.RError;
34-
import static com.oracle.truffle.r.runtime.RError.Message.MATCH_VECTOR_ARGS;
31+
import com.oracle.truffle.r.nodes.builtin.Match5Node;
3532
import com.oracle.truffle.r.runtime.RInternalError;
3633
import com.oracle.truffle.r.runtime.RRuntime;
3734
import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
3835
import com.oracle.truffle.r.runtime.data.RTypes;
3936
import com.oracle.truffle.r.runtime.data.RStringVector;
40-
import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
4137

4238
public final class MatchNodes {
4339

4440
@TypeSystemReference(RTypes.class)
45-
public abstract static class MatchNode extends FFIUpCallNode.Arg3 {
46-
47-
@Child MatchInternalNode match = MatchInternalNodeGen.create();
48-
41+
public abstract static class Match5UpCallNode extends FFIUpCallNode.Arg5 {
4942
@Specialization
50-
Object match(RAbstractVector x, RAbstractVector table, int noMatch) {
51-
return match.execute(x, table, noMatch);
52-
}
53-
54-
@SuppressWarnings("unused")
55-
@Fallback
56-
Object match(Object itables, Object ix, Object nmatch) {
57-
CompilerDirectives.transferToInterpreter();
58-
throw RError.error(this, MATCH_VECTOR_ARGS);
43+
Object match(Object x, Object table, int noMatch, Object incomparables, @SuppressWarnings("unused") Object env,
44+
@Cached Match5Node match5Node) {
45+
return match5Node.execute(x, table, noMatch, incomparables);
5946
}
6047

61-
public static MatchNode create() {
62-
return MatchNodesFactory.MatchNodeGen.create();
48+
public static Match5UpCallNode create() {
49+
return MatchNodesFactory.Match5UpCallNodeGen.create();
6350
}
6451
}
6552

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
package com.oracle.truffle.r.ffi.impl.nodes;
2424

2525
import com.oracle.truffle.api.CompilerDirectives;
26+
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
2627
import com.oracle.truffle.api.dsl.Cached;
28+
import com.oracle.truffle.api.dsl.CachedContext;
2729
import com.oracle.truffle.api.dsl.GenerateUncached;
2830
import com.oracle.truffle.api.dsl.ImportStatic;
2931
import com.oracle.truffle.api.dsl.Specialization;
@@ -34,10 +36,12 @@
3436
import com.oracle.truffle.api.nodes.Node;
3537
import com.oracle.truffle.r.runtime.DSLConfig;
3638
import com.oracle.truffle.r.runtime.RInternalError;
39+
import com.oracle.truffle.r.runtime.context.RContext;
40+
import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
3741
import com.oracle.truffle.r.runtime.data.RDataFactory;
3842
import com.oracle.truffle.r.runtime.data.RDoubleVector;
39-
import com.oracle.truffle.r.runtime.data.RNull;
4043
import com.oracle.truffle.r.runtime.data.RIntVector;
44+
import com.oracle.truffle.r.runtime.data.RNull;
4145
import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
4246
import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator;
4347
import com.oracle.truffle.r.runtime.interop.ConvertForeignObjectNode;
@@ -47,11 +51,11 @@
4751
import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function3_2;
4852
import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function4_1;
4953
import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function4_2;
54+
import com.oracle.truffle.r.runtime.nmath.RMultinom;
5055
import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction1_Double;
5156
import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction2_Double;
5257
import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction3_DoubleBase;
5358
import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider;
54-
import com.oracle.truffle.r.runtime.nmath.RMultinom;
5559
import com.oracle.truffle.r.runtime.nmath.distr.Rbinom;
5660

5761
public final class RandFunctionsNodes {
@@ -83,8 +87,9 @@ public static RandFunction3_1Node create() {
8387
@GenerateUncached
8488
public abstract static class RandFunction3Node extends FFIUpCallNode.Arg4 {
8589
@Specialization
86-
protected double evaluate(RandFunction3_DoubleBase delegate, double a, double b, double c) {
87-
return delegate.execute(a, b, c, RandomNumberProvider.fromCurrentRNG());
90+
protected double evaluate(RandFunction3_DoubleBase delegate, double a, double b, double c,
91+
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef) {
92+
return delegate.execute(a, b, c, RandomNumberProvider.fromCurrentRNG(ctxRef.get()));
8893
}
8994

9095
public static RandFunction3Node create() {
@@ -96,8 +101,9 @@ public static RandFunction3Node create() {
96101
public abstract static class RandFunction2Node extends FFIUpCallNode.Arg3 {
97102

98103
@Specialization
99-
protected double evaluate(RandFunction2_Double delegate, double a, double b) {
100-
return delegate.execute(a, b, RandomNumberProvider.fromCurrentRNG());
104+
protected double evaluate(RandFunction2_Double delegate, double a, double b,
105+
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef) {
106+
return delegate.execute(a, b, RandomNumberProvider.fromCurrentRNG(ctxRef.get()));
101107
}
102108

103109
public static RandFunction2Node create() {
@@ -108,8 +114,9 @@ public static RandFunction2Node create() {
108114
@GenerateUncached
109115
public abstract static class RandFunction1Node extends FFIUpCallNode.Arg2 {
110116
@Specialization
111-
protected double evaluate(RandFunction1_Double delegate, double a) {
112-
return delegate.execute(a, RandomNumberProvider.fromCurrentRNG());
117+
protected double evaluate(RandFunction1_Double delegate, double a,
118+
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef) {
119+
return delegate.execute(a, RandomNumberProvider.fromCurrentRNG(ctxRef.get()));
113120
}
114121

115122
public static RandFunction1Node create() {
@@ -233,11 +240,12 @@ abstract static class DoRMultinomNode extends Node {
233240

234241
@Specialization(guards = {"probAccess.supports(prob)", "rNAccess.supports(rN)"})
235242
protected void doRMultinom(int n, RDoubleVector prob, int k, RIntVector rN,
243+
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef,
236244
@Cached("prob.access()") VectorAccess probAccess,
237245
@Cached("rN.access()") VectorAccess rNAccess,
238246
@Cached() Rbinom rbinom) {
239247
int[] rNArr = new int[k];
240-
RMultinom.rmultinom(n, probAccess.access(prob), probAccess, 1d, rNArr, 0, RandomNumberProvider.fromCurrentRNG(), rbinom);
248+
RMultinom.rmultinom(n, probAccess.access(prob), probAccess, 1d, rNArr, 0, RandomNumberProvider.fromCurrentRNG(ctxRef.get()), rbinom);
241249
int i = 0;
242250
for (SequentialIterator rNIter = rNAccess.access(rN); rNAccess.next(rNIter);) {
243251
rNAccess.setInt(rNIter, rNArr[i++]);
@@ -246,8 +254,9 @@ protected void doRMultinom(int n, RDoubleVector prob, int k, RIntVector rN,
246254

247255
@Specialization(replaces = "doRMultinom")
248256
protected void doGeneric(int n, RDoubleVector prob, int k, RIntVector rN,
249-
@Cached() Rbinom rbinom) {
250-
doRMultinom(n, prob, k, rN, prob.slowPathAccess(), rN.slowPathAccess(), rbinom);
257+
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef,
258+
@Cached Rbinom rbinom) {
259+
doRMultinom(n, prob, k, rN, ctxRef, prob.slowPathAccess(), rN.slowPathAccess(), rbinom);
251260
}
252261

253262
}

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,8 +1034,12 @@ public interface StdUpCallsRFFI {
10341034
@RFFIUpCallNode(value = AsCharacterFactor.class, needsCallTarget = true)
10351035
Object Rf_asCharacterFactor(Object x);
10361036

1037-
@RFFIUpCallNode(value = MatchNodes.MatchNode.class, needsCallTarget = true)
1038-
Object Rf_match(Object itables, Object ix, int nmatch);
1037+
/**
1038+
* The {@code match5} function is internal to R, but nonetheless referenced by some R packages.
1039+
* Moreover, other {@code Rf_match} variants delegate to this function.
1040+
*/
1041+
@RFFIUpCallNode(value = MatchNodes.Match5UpCallNode.class, needsCallTarget = true)
1042+
Object match5(Object itables, Object ix, int nmatch, Object incomparables, Object env);
10391043

10401044
@RFFIUpCallNode(MatchNodes.NonNullStringMatchNode.class)
10411045
boolean Rf_NonNullStringMatch(Object s, Object t);

com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@
3131
import java.util.function.Function;
3232
import java.util.function.Supplier;
3333

34+
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
3435
import com.oracle.truffle.api.dsl.Cached;
36+
import com.oracle.truffle.api.dsl.CachedContext;
37+
import com.oracle.truffle.api.dsl.ImportStatic;
3538
import com.oracle.truffle.api.dsl.Specialization;
39+
import com.oracle.truffle.api.library.CachedLibrary;
3640
import com.oracle.truffle.api.nodes.Node;
3741
import com.oracle.truffle.api.profiles.BranchProfile;
3842
import com.oracle.truffle.api.profiles.LoopConditionProfile;
@@ -47,11 +51,15 @@
4751
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
4852
import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
4953
import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
54+
import com.oracle.truffle.r.runtime.DSLConfig;
5055
import com.oracle.truffle.r.runtime.RError;
5156
import com.oracle.truffle.r.runtime.RRuntime;
57+
import com.oracle.truffle.r.runtime.context.RContext;
58+
import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
5259
import com.oracle.truffle.r.runtime.data.RDataFactory;
5360
import com.oracle.truffle.r.runtime.data.RDoubleVector;
5461
import com.oracle.truffle.r.runtime.data.RIntVector;
62+
import com.oracle.truffle.r.runtime.data.VectorDataLibrary;
5563
import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
5664
import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
5765
import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator;
@@ -82,24 +90,28 @@ private RandFunctionsNodes() {
8290
* argument must be cast using {@link #addLengthCast(Casts)}. Using this node allows us to avoid
8391
* casting of long vectors to integers if we only need to know their length.
8492
*/
93+
@ImportStatic(DSLConfig.class)
8594
protected abstract static class ConvertToLength extends Node {
8695
public abstract int execute(RAbstractVector value);
8796

88-
@Specialization(guards = "vector.getLength() == 1")
97+
@Specialization(guards = "dataLib.getLength(vector.getData()) == 1")
8998
public int lengthOne(RAbstractVector vector,
9099
@Cached("createNonPreserving()") CastIntegerNode castNode,
100+
@CachedLibrary(limit = "getCacheSize(2)") VectorDataLibrary dataLib,
91101
@Cached("create()") BranchProfile seenNA) {
92-
int result = ((RIntVector) castNode.doCast(vector)).getDataAt(0);
102+
RIntVector vec = (RIntVector) castNode.doCast(vector);
103+
int result = dataLib.getIntAt(vec.getData(), 0);
93104
if (RRuntime.isNA(result) || result < 0) {
94105
seenNA.enter();
95106
throw RError.error(SHOW_CALLER, INVALID_UNNAMED_ARGUMENTS);
96107
}
97108
return result;
98109
}
99110

100-
@Specialization(guards = "vector.getLength() != 1")
101-
public int notSingle(RAbstractVector vector) {
102-
return vector.getLength();
111+
@Specialization(guards = "dataLib.getLength(vector.getData()) != 1", limit = "getVectorAccessCacheSize()")
112+
public int notSingle(RAbstractVector vector,
113+
@CachedLibrary("vector.getData()") VectorDataLibrary dataLib) {
114+
return dataLib.getLength(vector.getData());
103115
}
104116

105117
private static void addLengthCast(Casts casts) {
@@ -312,9 +324,10 @@ public static RandFunction3Node createDouble(Supplier<RandFunction3_DoubleBase>
312324
}
313325

314326
@Specialization
315-
protected RAbstractVector evaluate(RAbstractVector length, RDoubleVector a, RDoubleVector b, RDoubleVector c) {
327+
protected RAbstractVector evaluate(RAbstractVector length, RDoubleVector a, RDoubleVector b, RDoubleVector c,
328+
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef) {
316329
RRNG.getRNGState();
317-
return inner.execute(length, a, b, c, RandomNumberProvider.fromCurrentRNG());
330+
return inner.execute(length, a, b, c, RandomNumberProvider.fromCurrentRNG(ctxRef.get()));
318331
}
319332
}
320333

@@ -341,9 +354,10 @@ public static RandFunction2Node createDouble(Supplier<RandFunction2_Double> func
341354
}
342355

343356
@Specialization
344-
protected Object evaluate(RAbstractVector length, RDoubleVector a, RDoubleVector b) {
357+
protected Object evaluate(RAbstractVector length, RDoubleVector a, RDoubleVector b,
358+
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef) {
345359
RRNG.getRNGState();
346-
return inner.execute(length, a, b, DUMMY_VECTOR, RandomNumberProvider.fromCurrentRNG());
360+
return inner.execute(length, a, b, DUMMY_VECTOR, RandomNumberProvider.fromCurrentRNG(ctxRef.get()));
347361
}
348362
}
349363

@@ -369,9 +383,10 @@ public static RandFunction1Node createDouble(Supplier<RandFunction1_Double> func
369383
}
370384

371385
@Specialization
372-
protected Object evaluate(RAbstractVector length, RDoubleVector a) {
386+
protected Object evaluate(RAbstractVector length, RDoubleVector a,
387+
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef) {
373388
RRNG.getRNGState();
374-
return inner.execute(length, a, DUMMY_VECTOR, DUMMY_VECTOR, RandomNumberProvider.fromCurrentRNG());
389+
return inner.execute(length, a, DUMMY_VECTOR, DUMMY_VECTOR, RandomNumberProvider.fromCurrentRNG(ctxRef.get()));
375390
}
376391
}
377392
}

com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ typedef double (*call_Rf_ftrunc)(double a);
426426
typedef double (*call_Rf_cospi)(double a);
427427
typedef double (*call_Rf_sinpi)(double a);
428428
typedef double (*call_Rf_tanpi)(double a);
429-
typedef SEXP (*call_Rf_match)(SEXP itable, SEXP ix, int nmatch);
429+
typedef SEXP (*call_match5)(SEXP itable, SEXP ix, int nmatch, SEXP incomparables, SEXP env);
430430
typedef Rboolean (*call_Rf_NonNullStringMatch)(SEXP s, SEXP t);
431431
typedef SEXP (*call_getvar)();
432432
typedef SEXP (*call_R_ParseVector)(SEXP text, int n, SEXP srcFile);

0 commit comments

Comments
 (0)