Skip to content

Commit a39acb9

Browse files
committed
[GR-19137] [GR-17127] [GR-18935] Backport several fixes.
PullRequest: fastr/2199
2 parents 6609c0d + 9342336 commit a39acb9

File tree

22 files changed

+12219
-9150
lines changed

22 files changed

+12219
-9150
lines changed

3rd_party_licenses.txt

Lines changed: 11986 additions & 9081 deletions
Large diffs are not rendered by default.

CHANGELOG.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,25 @@
22

33
New features:
44

5+
* new Graal LLVM based back-end for running packages native code.
6+
* The default {FASTR_HOME}/etc/Makeconf is configured to use the Graal LLVM toolchain to build the native code of R packages.
7+
* The toolchain builds standard native binaries for a given plarform and also embeds the corresponding LLVM bitcode in them.
8+
* R builtin `fastr.setToolchain(name)` (`name` can be `llvm` or `native`) sets the compiler toolchain used for package building (modifies etc/Makeconf).
9+
* To switch back to the previous toolchain configuration that used `GCC`, execute `fastr.setToolchain("native")`.
10+
* Option `--R.BackEnd` specifies the default backend used to execute packages native code.
11+
* Different R packages can be run via different backends in one FastR context.
12+
* `--R.BackEnd=native`, the default, is JNI based backend that runs directly the actual native code.
13+
* `--R.BackEnd=llvm` is the new LLVM backend that loads the LLVM bitcode embedded in package libraries and runs it via Graal LLVM.
14+
* `--R.BackEndNative=pkg1,pkg2,...` enumerates packages whose native code will be executed by the native backend.
15+
* `--R.BackEndLLVM=pkg1,pkg2,...` enumerates packages whose native code will be executed by the LLVM backend.
16+
* Note: All `--R.BackEnd*` options are passed to R subprocesses.
17+
* Debugging of packages native code with LLVM backend.
18+
* Option `--R.DebugLLVMLibs` activates debugging of native code using the bundled LLVM bitcode.
19+
* Builtin `fastr.useDebugMakevars(use)` activates/deactivates a special `etc/Makevars.site` tailored for building the packages native code for debugging.
520
* `gc` attempts to invoke Java GC when FastR is run with `--R.EnableExplicitGC=true`
621
* this is intended only for testing purposes and it is not recommended to run GC explicitly in FastR.
722
* `gc` is not invoking Java GC by default because GNU-R GC and Java GC are fundamentally
823
different and this may lead to unintended behavior.
9-
* Option `--R.BackEnd` specifies an RFFI backend. `--R.BackEnd=native`, the default, activates the JNI based backend, while `--R.BackEnd=llvm` activates the LLVM backend loading the LLVM bitcode bundled with package libraries. Note: All ``--R.BackEnd*` options are passed to R subprocesses.
10-
* Option `--R.BackEndNative` enumerates packages whose native code will be executed by the native backend (JNI based)
11-
* Option `--R.BackEndLLVM` enumerates packages whose native code will be executed by the LLVM backend
12-
* Option `--R.DebugLLVMLibs` activates debugging of native code using the bundled LLVM bitcode
13-
* Builtin `fastr.useDebugMakevars(use)` activates/deactivates a special `etc/Makevars.site` for debugging native code
14-
* Builtin `fastr.setToolchain(name)` (`name` can be `llvm` or `native`) sets the compiler toolchain used for package building
1524

1625
Added missing R builtins and C APIs
1726

@@ -34,7 +43,6 @@ Bug fixes:
3443
* failures when working with large vectors (>1GB)
3544

3645

37-
3846
# 19.2.0
3947

4048
New features:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ which can be installed with `install.fastr.packages(c("rJava", "data.table"))`.
5757
Packages that use the [R extensions C API](https://cran.r-project.org/doc/manuals/r-release/R-exts.html) in hot paths,
5858
especially via `Rcpp`, may exhibit slower performance on FastR due to the high cost of transitions between the native and managed code.
5959
This will be mitigated by using the Graal LLVM interpreter. The support is available in the development version via
60-
the `--R.BackEndLLVM` option. Note that most of the times FastR running R code equivalent to given `Rcpp` code is as
60+
the `--R.BackEnd=llvm` option. Note that most of the times FastR running R code equivalent to given `Rcpp` code is as
6161
fast as GNU-R and sometimes even faster because the GraalVM dynamic compiler can optimize the program as a whole.
6262

6363
## Stay connected with the community

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UserRng.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ private static final class TruffleLLVMInitNode extends RNGNode implements InitNo
6464
@Override
6565
public void execute(VirtualFrame frame, int seed) {
6666
RFFIContext stateRFFI = RContext.getInstance().getStateRFFI();
67-
Object before = stateRFFI.beforeDowncall(frame, RFFIFactory.Type.LLVM);
67+
Object before = stateRFFI.beforeDowncall(frame.materialize(), RFFIFactory.Type.LLVM);
6868
try {
6969
userFunctionInterop.execute(userFunctionTarget, seed);
7070
} catch (InteropException ex) {
@@ -84,7 +84,7 @@ private static final class TruffleLLVM_RandNode extends RNGNode implements RandN
8484
@Override
8585
public double execute(VirtualFrame frame) {
8686
RFFIContext stateRFFI = RContext.getInstance().getStateRFFI();
87-
Object before = stateRFFI.beforeDowncall(frame, RFFIFactory.Type.LLVM);
87+
Object before = stateRFFI.beforeDowncall(frame.materialize(), RFFIFactory.Type.LLVM);
8888
try {
8989
Object address = userFunctionInterop.execute(userFunctionTarget);
9090
return (double) readPointerInterop.execute(readPointerTarget, address);
@@ -105,7 +105,7 @@ private static final class TruffleLLVM_NSeedNode extends RNGNode implements NSee
105105
@Override
106106
public int execute(VirtualFrame frame) {
107107
RFFIContext stateRFFI = RContext.getInstance().getStateRFFI();
108-
Object before = stateRFFI.beforeDowncall(frame, RFFIFactory.Type.LLVM);
108+
Object before = stateRFFI.beforeDowncall(frame.materialize(), RFFIFactory.Type.LLVM);
109109
try {
110110
Object address = userFunctionInterop.execute(userFunctionTarget);
111111
return (int) readPointerInterop.execute(readPointerTarget, address);
@@ -126,7 +126,7 @@ private static final class TruffleLLVM_SeedsNode extends RNGNode implements Seed
126126
@Override
127127
public void execute(VirtualFrame frame, int[] n) {
128128
RFFIContext stateRFFI = RContext.getInstance().getStateRFFI();
129-
Object before = stateRFFI.beforeDowncall(frame, RFFIFactory.Type.LLVM);
129+
Object before = stateRFFI.beforeDowncall(frame.materialize(), RFFIFactory.Type.LLVM);
130130
try {
131131
Object address = userFunctionInterop.execute(userFunctionTarget);
132132
for (int i = 0; i < n.length; i++) {

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/mixed/TruffleMixed_Context.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*/
2323
package com.oracle.truffle.r.ffi.impl.mixed;
2424

25-
import com.oracle.truffle.api.frame.VirtualFrame;
25+
import com.oracle.truffle.api.frame.MaterializedFrame;
2626
import com.oracle.truffle.api.interop.TruffleObject;
2727
import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_Context;
2828
import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL.LLVM_Handle;
@@ -137,7 +137,7 @@ public void afterUpcall(boolean canRunGc, Type rffiType) {
137137
}
138138

139139
@Override
140-
public Object beforeDowncall(VirtualFrame frame, Type rffiType) {
140+
public Object beforeDowncall(MaterializedFrame frame, Type rffiType) {
141141
Type actualRffiType = rffiType == null ? Type.LLVM : rffiType;
142142
assert rffiType != null;
143143
switch (rffiType) {

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import com.oracle.truffle.api.CompilerDirectives;
3636
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
3737
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
38-
import com.oracle.truffle.api.frame.VirtualFrame;
38+
import com.oracle.truffle.api.frame.MaterializedFrame;
3939
import com.oracle.truffle.api.interop.InteropException;
4040
import com.oracle.truffle.api.interop.InteropLibrary;
4141
import com.oracle.truffle.api.interop.TruffleObject;
@@ -399,7 +399,7 @@ public void beforeDispose(RContext context) {
399399
}
400400

401401
@Override
402-
public Object beforeDowncall(VirtualFrame frame, RFFIFactory.Type rffiType) {
402+
public Object beforeDowncall(MaterializedFrame frame, RFFIFactory.Type rffiType) {
403403
Object tokenFromSuper = super.beforeDowncall(frame, RFFIFactory.Type.NFI);
404404
transientAllocations.push(new ArrayList<>());
405405
if (hasAccessLock) {

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UserRng.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ private static final class TruffleNFI_InitNode extends RNGNode implements InitNo
6363
@Override
6464
public void execute(VirtualFrame frame, int seed) {
6565
RFFIContext stateRFFI = RContext.getInstance().getStateRFFI();
66-
Object before = stateRFFI.beforeDowncall(frame, RFFIFactory.Type.NFI);
66+
Object before = stateRFFI.beforeDowncall(frame.materialize(), RFFIFactory.Type.NFI);
6767
try {
6868
userFunctionInterop.execute(userFunctionTarget, seed);
6969
} catch (InteropException ex) {
@@ -83,7 +83,7 @@ private static final class TruffleNFI_RandNode extends RNGNode implements RandNo
8383
@Override
8484
public double execute(VirtualFrame frame) {
8585
RFFIContext stateRFFI = RContext.getInstance().getStateRFFI();
86-
Object before = stateRFFI.beforeDowncall(frame, RFFIFactory.Type.NFI);
86+
Object before = stateRFFI.beforeDowncall(frame.materialize(), RFFIFactory.Type.NFI);
8787
try {
8888
Object address = userFunctionInterop.execute(userFunctionTarget);
8989
return (double) readPointerInterop.execute(readPointerTarget, address);
@@ -104,7 +104,7 @@ private static final class TruffleNFI_NSeedNode extends RNGNode implements NSeed
104104
@Override
105105
public int execute(VirtualFrame frame) {
106106
RFFIContext stateRFFI = RContext.getInstance().getStateRFFI();
107-
Object before = stateRFFI.beforeDowncall(frame, RFFIFactory.Type.NFI);
107+
Object before = stateRFFI.beforeDowncall(frame.materialize(), RFFIFactory.Type.NFI);
108108
try {
109109
Object address = userFunctionInterop.execute(userFunctionTarget);
110110
return (int) readPointerInterop.execute(readPointerTarget, address);
@@ -125,7 +125,7 @@ private static final class TruffleNFI_SeedsNode extends RNGNode implements Seeds
125125
@Override
126126
public void execute(VirtualFrame frame, int[] n) {
127127
RFFIContext stateRFFI = RContext.getInstance().getStateRFFI();
128-
Object before = stateRFFI.beforeDowncall(frame, RFFIFactory.Type.NFI);
128+
Object before = stateRFFI.beforeDowncall(frame.materialize(), RFFIFactory.Type.NFI);
129129
try {
130130
Object address = userFunctionInterop.execute(userFunctionTarget);
131131
for (int i = 0; i < n.length; i++) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ private static RArgsValuesAndNames createArgsAndNames(List<Object> argValues, RA
180180
}
181181

182182
private void flattenFirstArgs(VirtualFrame frame, int n, RArgsValuesAndNames args, PromiseHelperNode promiseHelper) {
183+
// In GnuR there appears to be no error checks on n > args.length
183184
if (args.getLength() < n) {
184185
CompilerDirectives.transferToInterpreter();
185186
throw RError.nyi(this, "forceAndCall with insufficient arguments");

com.oracle.truffle.r.native/run/configure_fastr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ done
102102
res=$?
103103
if [[ $res != 0 ]]; then
104104
echo "Cannot build a simple C program linking with libgfortran, libgcc_s, and libquadmath."
105-
echo "Please install GCC using:"
106-
echo " On Debian based systems: apt-get install build-essential"
107-
echo " On CentOS/RHEL: yum groupinstall \"Developent Tools\""
105+
echo "Please install GCC and gfortran using:"
106+
echo " On Debian based systems: sudo apt-get install build-essential gfortran"
107+
echo " On CentOS/RHEL/Oracle Linux: sudo yum groupinstall \"Developent Tools\"; yum install gcc-gfortran"
108108
echo ""
109109
printHelp
110110
exit 1

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
5050
import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
5151
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
52-
import com.oracle.truffle.r.runtime.RError;
5352
import com.oracle.truffle.r.runtime.Collections.ArrayListObj;
53+
import com.oracle.truffle.r.runtime.RError;
5454
import com.oracle.truffle.r.runtime.RError.Message;
5555
import com.oracle.truffle.r.runtime.RInternalError;
5656
import com.oracle.truffle.r.runtime.RRuntime;
@@ -1977,6 +1977,9 @@ private static RIntVector convertFirstMatchedRangeToRIndex(HaystackDescriptor ha
19771977
protected Object grepFixedNoInvert(RRawVector pattern, RRawVector x, int offset, @SuppressWarnings("unused") Object ignoreCase, @SuppressWarnings("unused") boolean fixed, boolean value,
19781978
boolean all,
19791979
@SuppressWarnings("unused") boolean invert) {
1980+
if (x.getLength() == 0) {
1981+
return RDataFactory.createEmptyIntVector();
1982+
}
19801983
HaystackDescriptor haystackDescriptor = null;
19811984
if (all) {
19821985
haystackDescriptor = findAllOccurrences(pattern, x, offset);
@@ -2011,6 +2014,9 @@ protected Object grepFixedNoInvert(RRawVector pattern, RRawVector x, int offset,
20112014
protected Object grepFixedInvert(RRawVector pattern, RRawVector x, int offset, @SuppressWarnings("unused") Object ignoreCase, @SuppressWarnings("unused") boolean fixed,
20122015
@SuppressWarnings("unused") boolean value, boolean all,
20132016
@SuppressWarnings("unused") boolean invert) {
2017+
if (x.getLength() == 0) {
2018+
return RDataFactory.createEmptyIntVector();
2019+
}
20142020
HaystackDescriptor haystackDescriptor = null;
20152021
if (all) {
20162022
haystackDescriptor = findAllOccurrences(pattern, x, offset);
@@ -2029,6 +2035,9 @@ protected Object grepFixedInvert(RRawVector pattern, RRawVector x, int offset, @
20292035
protected Object grepFixedIgnoreInvert(RRawVector pattern, RRawVector x, int offset, @SuppressWarnings("unused") Object ignoreCase, boolean fixed, boolean value, boolean all,
20302036
boolean invert) {
20312037
warning(Message.ARGUMENT_IGNORED, "invert = TRUE");
2038+
if (x.getLength() == 0) {
2039+
return RDataFactory.createEmptyIntVector();
2040+
}
20322041
return grepFixedNoInvert(pattern, x, offset, ignoreCase, fixed, value, all, invert);
20332042
}
20342043

0 commit comments

Comments
 (0)