Skip to content

Commit e3e5cc7

Browse files
committed
[GR-21134] Do not eagerly materialize vectors going to native code.
PullRequest: fastr/2482
2 parents a517f93 + 8641446 commit e3e5cc7

File tree

5 files changed

+37
-52
lines changed

5 files changed

+37
-52
lines changed

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/VectorDataClosure.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
*/
2323
package com.oracle.truffle.r.runtime.data;
2424

25+
import com.oracle.truffle.api.CompilerDirectives;
2526
import com.oracle.truffle.api.interop.TruffleObject;
2627
import com.oracle.truffle.api.library.CachedLibrary;
2728
import com.oracle.truffle.api.library.ExportLibrary;
@@ -111,8 +112,18 @@ public Object materialize(@CachedLibrary("this.data") VectorDataLibrary dataLib)
111112
switch (getType()) {
112113
case Integer:
113114
return new RIntArrayVectorData(getIntDataCopy(dataLib), dataLib.getNACheck(data).neverSeenNA());
115+
case Double:
116+
return new RDoubleArrayVectorData(getDoubleDataCopy(dataLib), dataLib.getNACheck(data).neverSeenNA());
117+
case Raw:
118+
return new RRawArrayVectorData(getRawDataCopy(dataLib));
119+
case Logical:
120+
return new RLogicalArrayVectorData(getLogicalDataCopy(dataLib), dataLib.getNACheck(data).neverSeenNA());
121+
case Complex:
122+
return new RComplexArrayVectorData(getComplexDataCopy(dataLib), dataLib.getNACheck(data).neverSeenNA());
123+
case Character:
124+
return new RStringArrayVectorData(getStringDataCopy(dataLib), dataLib.getNACheck(data).neverSeenNA());
114125
default:
115-
throw RInternalError.unimplemented("TODO");
126+
throw CompilerDirectives.shouldNotReachHere(getType().toString());
116127
}
117128
}
118129

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/FFIMaterializeNode.java

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,22 @@
2828
import com.oracle.truffle.api.dsl.ImportStatic;
2929
import com.oracle.truffle.api.dsl.Specialization;
3030
import com.oracle.truffle.api.interop.TruffleObject;
31-
import com.oracle.truffle.api.library.CachedLibrary;
3231
import com.oracle.truffle.api.nodes.Node;
3332
import com.oracle.truffle.r.runtime.DSLConfig;
3433
import com.oracle.truffle.r.runtime.RInternalError;
3534
import com.oracle.truffle.r.runtime.RRuntime;
3635
import com.oracle.truffle.r.runtime.context.RContext;
37-
import com.oracle.truffle.r.runtime.data.AbstractContainerLibrary;
3836
import com.oracle.truffle.r.runtime.data.NativeDataAccess;
3937
import com.oracle.truffle.r.runtime.data.RBaseObject;
4038
import com.oracle.truffle.r.runtime.data.RComplex;
4139
import com.oracle.truffle.r.runtime.data.RDataFactory;
4240
import com.oracle.truffle.r.runtime.data.RRaw;
43-
import com.oracle.truffle.r.runtime.data.RScalarVector;
44-
import com.oracle.truffle.r.runtime.data.RSequence;
45-
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
4641
import com.oracle.truffle.r.runtime.ffi.interop.NativeDoubleArray;
4742

4843
/**
4944
* Converts values that can live on the FastR side to values that can be sent to the native code,
5045
* i.e., anything that is not {@link RBaseObject} and doesn't have a native mirror needs to be
51-
* wrapped to such object. Moreover, we need to convert compact read-only vectors to materialized
52-
* ones, since user may expect to be able to take their data-pointer and write into them.
46+
* wrapped to such object.
5347
*
5448
* See documentation/dev/ffi.md for more details.
5549
*/
@@ -58,101 +52,81 @@
5852
public abstract class FFIMaterializeNode extends Node {
5953

6054
public Object materialize(Object value) {
61-
return execute(value, false);
55+
return execute(value);
6256
}
6357

64-
public Object materializeProtected(Object value) {
65-
return execute(value, true);
66-
}
67-
68-
protected abstract Object execute(Object value, boolean protect);
58+
protected abstract Object execute(Object value);
6959

7060
public static Object uncachedMaterialize(Object value) {
71-
return FFIMaterializeNodeGen.getUncached().execute(value, false);
61+
return FFIMaterializeNodeGen.getUncached().execute(value);
7262
}
7363

7464
// Scalar values:
7565

7666
@Specialization
77-
protected static Object wrap(int value, @SuppressWarnings("unused") boolean protect) {
67+
protected static Object wrap(int value) {
7868
return RDataFactory.createIntVectorFromScalar(value);
7969
}
8070

8171
@Specialization
82-
protected static Object wrap(double value, @SuppressWarnings("unused") boolean protect) {
72+
protected static Object wrap(double value) {
8373
return RDataFactory.createDoubleVectorFromScalar(value);
8474
}
8575

8676
@Specialization
87-
protected static Object wrap(double[] value, @SuppressWarnings("unused") boolean protect) {
77+
protected static Object wrap(double[] value) {
8878
return new NativeDoubleArray(value);
8979
}
9080

9181
@Specialization
92-
protected static Object wrap(byte value, @SuppressWarnings("unused") boolean protect) {
82+
protected static Object wrap(byte value) {
9383
return RDataFactory.createLogicalVectorFromScalar(value);
9484
}
9585

9686
@Specialization
97-
protected static Object wrap(String value, @SuppressWarnings("unused") boolean protect) {
87+
protected static Object wrap(String value) {
9888
return RDataFactory.createStringVectorFromScalar(value);
9989
}
10090

10191
@Specialization
102-
protected static Object wrap(RRaw value, @SuppressWarnings("unused") boolean protect) {
92+
protected static Object wrap(RRaw value) {
10393
return RDataFactory.createRawVectorFromScalar(value);
10494
}
10595

10696
@Specialization
107-
protected static Object wrap(RComplex value, @SuppressWarnings("unused") boolean protect) {
97+
protected static Object wrap(RComplex value) {
10898
return RDataFactory.createComplexVectorFromScalar(value);
10999
}
110100

111-
// Sequences: life-cycle of the materialized vector is cached and tied with the sequence via a
112-
// field inside the sequence
113-
114-
@Specialization
115-
protected static Object wrap(RSequence seq, @SuppressWarnings("unused") boolean protect) {
116-
return seq.cachedMaterialize();
117-
}
118-
119101
// RObjectDataPtr: held by a field in NativeMirror of the corresponding vector
120102

121103
@Specialization
122-
protected static Object wrap(RObjectDataPtr value, @SuppressWarnings("unused") boolean protect) {
104+
protected static Object wrap(RObjectDataPtr value) {
123105
return value;
124106
}
125107

126-
// No need to wrap other RObjects than sequences or scalars
127-
128-
@Specialization(guards = "!isRScalarVectorOrSequenceOrHasVectorData(value)")
129-
protected static Object wrap(RBaseObject value, @SuppressWarnings("unused") boolean protect) {
108+
// No need to wrap any RObjects
109+
@Specialization
110+
protected static Object wrap(RBaseObject value) {
130111
return value;
131112
}
132113

133-
@Specialization(limit = "getGenericDataLibraryCacheSize()")
134-
protected static Object wrap(RAbstractContainer value, @SuppressWarnings("unused") boolean protect,
135-
@CachedLibrary("value") AbstractContainerLibrary containerLibrary) {
136-
// TODO specialize only for sequences (and maybe some other)
137-
return containerLibrary.cachedMaterialize(value);
138-
}
139-
140114
// Symbol holds the address as a field
141115

142116
@Specialization
143-
protected static Object wrap(DLL.SymbolHandle sym, @SuppressWarnings("unused") boolean protect) {
117+
protected static Object wrap(DLL.SymbolHandle sym) {
144118
return sym.asAddress();
145119
}
146120

147121
// Wrappers for foreign objects are held in a weak hash map
148122

149123
@Specialization(guards = "isForeignObject(value)")
150-
protected static Object wrapForeignObject(TruffleObject value, @SuppressWarnings("unused") boolean protect) {
124+
protected static Object wrapForeignObject(TruffleObject value) {
151125
return RContext.getInstance().getRFFI().getOrCreateForeignObjectWrapper(value);
152126
}
153127

154128
@Fallback
155-
protected static Object wrap(Object value, @SuppressWarnings("unused") boolean protect) {
129+
protected static Object wrap(Object value) {
156130
CompilerDirectives.transferToInterpreter();
157131
String name = value == null ? "null" : value.getClass().getSimpleName();
158132
throw RInternalError.shouldNotReachHere("invalid wrapping: " + name);
@@ -164,10 +138,6 @@ static boolean isForeignObject(Object value) {
164138
return RRuntime.isForeignObject(value);
165139
}
166140

167-
protected static boolean isRScalarVectorOrSequenceOrHasVectorData(RBaseObject value) {
168-
return value instanceof RScalarVector || value instanceof RSequence || RRuntime.hasVectorData(value);
169-
}
170-
171141
public static FFIMaterializeNode create() {
172142
return FFIMaterializeNodeGen.create();
173143
}

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ private JavaGDResizeCallNode(DownCallNodeFactory parent) {
151151
}
152152

153153
public Object execute(VirtualFrame frame, Object dev) {
154-
return call(frame, NativeFunction.javaGDresizeCall, opToNativeMirrorNode.execute(materializeNode.execute(dev, false)));
154+
return call(frame, NativeFunction.javaGDresizeCall, opToNativeMirrorNode.execute(materializeNode.materialize(dev)));
155155
}
156156

157157
}

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RObjectDataPtr.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ public Object readArrayElement(long index,
415415
@Exclusive @Cached("createBinaryProfile()") ConditionProfile wasMaterializedProfile,
416416
@CachedLibrary(limit = "DATA_LIB_LIMIT") VectorDataLibrary dataLib) {
417417
Object result = super.readArrayElement(index, dataLib);
418-
Object materialized = materializeNode.execute(result, false);
418+
Object materialized = materializeNode.materialize(result);
419419
if (wasMaterializedProfile.profile(materialized != result)) {
420420
dataLib.setElementAt(vectorData, RRuntime.interopArrayIndexToInt(index, vector), materialized);
421421
}

com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# This code is free software; you can redistribute it and/or modify it
@@ -407,3 +407,7 @@ if (Sys.getenv("TESTRFFI_IGNORE_4GB_VECTOR_TEST") != "") {
407407
}
408408

409409
is.null(rffi.testMissingArgWithATTRIB())
410+
411+
# Compact representations and RFFI:
412+
# sequences get materialized on write, but should not get materialized on read
413+
rffi.shareIntElement(1:2,1:3,1:4,1:5)

0 commit comments

Comments
 (0)