Skip to content

Commit 6aa1d92

Browse files
committed
better handling of foreign objects in as.list/matrix/array/data.frame/...
1 parent 823b5e5 commit 6aa1d92

File tree

17 files changed

+5226
-9096
lines changed

17 files changed

+5226
-9096
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,11 @@ protected Object asVector(Object x, String mode,
155155
@Cached("create(type)") DropAttributesNode drop,
156156
@Cached("create()") ForeignArray2R foreignArray2R) {
157157
if (RRuntime.isForeignObject(x)) {
158-
Object o = foreignArray2R.convert((TruffleObject) x);
158+
if (type == RType.List) {
159+
// already returns list, no need to cast
160+
return foreignArray2R.convertToList((TruffleObject) x, true, true);
161+
}
162+
Object o = foreignArray2R.convert((TruffleObject) x, true, true);
159163
if (!RRuntime.isForeignObject(o)) {
160164
return cast == null ? o : cast.doCast(o);
161165
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ public BasePackage() {
486486
add(FastRInterop.JavaIsInstance.class, FastRInteropFactory.JavaIsInstanceNodeGen::create);
487487
add(FastRInterop.JavaAsTruffleObject.class, FastRInteropFactory.JavaAsTruffleObjectNodeGen::create);
488488
add(FastRInterop.ToJavaArray.class, FastRInteropFactory.ToJavaArrayNodeGen::create);
489-
add(FastRInterop.FromForeignArray.class, FastRInteropFactory.FromForeignArrayNodeGen::create);
489+
add(FastRInterop.AsVector.class, FastRInteropFactory.AsVectorNodeGen::create);
490490
add(FastRInterop.ToByte.class, FastRInteropFactory.ToByteNodeGen::create);
491491
add(FastRInterop.ToChar.class, FastRInteropFactory.ToCharNodeGen::create);
492492
add(FastRInterop.ToFloat.class, FastRInteropFactory.ToFloatNodeGen::create);

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

Lines changed: 6 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -22,51 +22,40 @@
2222
*/
2323
package com.oracle.truffle.r.nodes.builtin.base;
2424

25-
import com.oracle.truffle.api.CompilerDirectives;
2625
import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
2726
import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
2827
import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
2928

3029
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
31-
import com.oracle.truffle.api.TruffleLanguage;
3230
import com.oracle.truffle.api.dsl.Cached;
3331
import com.oracle.truffle.api.dsl.Fallback;
3432
import com.oracle.truffle.api.dsl.ImportStatic;
3533
import com.oracle.truffle.api.dsl.Specialization;
36-
import com.oracle.truffle.api.interop.ForeignAccess;
37-
import com.oracle.truffle.api.interop.InteropException;
38-
import com.oracle.truffle.api.interop.Message;
3934
import com.oracle.truffle.api.interop.TruffleObject;
40-
import com.oracle.truffle.api.interop.UnknownIdentifierException;
41-
import com.oracle.truffle.api.interop.UnsupportedMessageException;
42-
import com.oracle.truffle.api.nodes.Node;
4335
import com.oracle.truffle.api.profiles.ConditionProfile;
4436
import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
4537
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
46-
import com.oracle.truffle.r.runtime.RInternalError;
4738
import com.oracle.truffle.r.runtime.RRuntime;
4839
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
49-
import com.oracle.truffle.r.runtime.context.RContext;
50-
import com.oracle.truffle.r.runtime.data.RDataFactory;
5140
import com.oracle.truffle.r.runtime.data.RNull;
5241
import com.oracle.truffle.r.runtime.data.RStringVector;
5342
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
5443
import com.oracle.truffle.r.runtime.env.REnvironment;
44+
import com.oracle.truffle.r.runtime.interop.GetForeignKeysNode;
5545

56-
@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
46+
@ImportStatic(RRuntime.class)
5747
@RBuiltin(name = "names", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
5848
public abstract class Names extends RBuiltinNode.Arg1 {
5949

6050
private final ConditionProfile hasNames = ConditionProfile.createBinaryProfile();
61-
@Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
62-
@Child private Node executeNode;
6351

6452
static {
6553
Casts.noCasts(Names.class);
6654
}
6755

6856
@Specialization
69-
protected Object getNames(RAbstractContainer container) {
57+
protected Object getNames(RAbstractContainer container,
58+
@Cached("create()") GetNamesAttributeNode getNames) {
7059
RStringVector names = getNames.getNames(container);
7160
if (hasNames.profile(names != null)) {
7261
return names;
@@ -83,54 +72,8 @@ protected Object getNames(REnvironment env) {
8372

8473
@Specialization(guards = "isForeignObject(obj)")
8574
protected Object getNames(TruffleObject obj,
86-
@Cached("GET_SIZE.createNode()") Node getSizeNode,
87-
@Cached("KEYS.createNode()") Node keysNode,
88-
@Cached("READ.createNode()") Node readNode) {
89-
90-
try {
91-
String[] names;
92-
try {
93-
names = readKeys(keysNode, obj, getSizeNode, readNode);
94-
} catch (UnsupportedMessageException e) {
95-
// because it is a java function, java.util.Map (has special handling too) ... ?
96-
return RNull.instance;
97-
}
98-
String[] staticNames = new String[0];
99-
RContext context = RContext.getInstance();
100-
TruffleLanguage.Env env = context.getEnv();
101-
if (env.isHostObject(obj) && !(env.asHostObject(obj) instanceof Class)) {
102-
if (executeNode == null) {
103-
CompilerDirectives.transferToInterpreterAndInvalidate();
104-
executeNode = insert(Message.EXECUTE.createNode());
105-
}
106-
try {
107-
TruffleObject clazzStatic = context.toJavaStatic(obj, readNode, executeNode);
108-
staticNames = readKeys(keysNode, clazzStatic, getSizeNode, readNode);
109-
} catch (UnknownIdentifierException | NoSuchFieldError | UnsupportedMessageException e) {
110-
}
111-
}
112-
if (names.length == 0 && staticNames.length == 0) {
113-
return RNull.instance;
114-
}
115-
String[] result = new String[names.length + staticNames.length];
116-
System.arraycopy(names, 0, result, 0, names.length);
117-
System.arraycopy(staticNames, 0, result, names.length, staticNames.length);
118-
return RDataFactory.createStringVector(result, true);
119-
} catch (InteropException e) {
120-
throw RInternalError.shouldNotReachHere(e);
121-
}
122-
}
123-
124-
private static String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode)
125-
throws UnknownIdentifierException, InteropException, UnsupportedMessageException {
126-
TruffleObject keys = ForeignAccess.sendKeys(keysNode, obj);
127-
int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys);
128-
String[] names = new String[size];
129-
for (int i = 0; i < size; i++) {
130-
Object value = ForeignAccess.sendRead(readNode, keys, i);
131-
names[i] = (String) value;
132-
}
133-
return names;
75+
@Cached("create()") GetForeignKeysNode foreignKeys) {
76+
return foreignKeys.execute(obj, true);
13477
}
13578

13679
@Fallback
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# This code is free software; you can redistribute it and/or modify it
5+
# under the terms of the GNU General Public License version 3 only, as
6+
# published by the Free Software Foundation.
7+
#
8+
# This code is distributed in the hope that it will be useful, but WITHOUT
9+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
# version 3 for more details (a copy is included in the LICENSE file that
12+
# accompanied this code).
13+
#
14+
# You should have received a copy of the GNU General Public License version
15+
# 3 along with this work; if not, write to the Free Software Foundation,
16+
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
#
18+
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19+
# or visit www.oracle.com if you need additional information or have any
20+
# questions.
21+
22+
as.matrix.polyglot.value <- function(x, ...) {
23+
v <- .fastr.interop.asVector(x, recursive=TRUE, dropDimensions=FALSE)
24+
return(as.matrix(v), ...)
25+
}
26+
27+
as.array.polyglot.value <- function(x, ...) {
28+
v <- .fastr.interop.asVector(x, recursive=TRUE, dropDimensions=FALSE)
29+
return(as.array(v), ...)
30+
}
31+
32+
as.data.frame.polyglot.value <- function(x, row.names = NULL, optional = FALSE, ..., nm = paste(deparse(substitute(x),
33+
width.cutoff = 500L), collapse = " ")) {
34+
v <- .fastr.interop.asVector(x, recursive=TRUE, dropDimensions=FALSE)
35+
if (!optional && !is.null(v) && is.atomic(v)) {
36+
v <- list(v)
37+
names(v) <- nm
38+
}
39+
as.data.frame(v, row.names=row.names, optional=optional, ...)
40+
}

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -949,33 +949,36 @@ protected boolean isJavaLikeVector(RAbstractVector vec) {
949949
}
950950

951951
@ImportStatic({Message.class, RRuntime.class})
952-
@RBuiltin(name = ".fastr.interop.fromArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"array", "recursive"}, behavior = COMPLEX)
953-
public abstract static class FromForeignArray extends RBuiltinNode.Arg2 {
952+
@RBuiltin(name = ".fastr.interop.asVector", visibility = ON, kind = PRIMITIVE, parameterNames = {"array", "recursive", "dropDimensions"}, behavior = COMPLEX)
953+
public abstract static class AsVector extends RBuiltinNode.Arg3 {
954954

955955
static {
956-
Casts casts = new Casts(FromForeignArray.class);
956+
Casts casts = new Casts(AsVector.class);
957957
casts.arg("array").castForeignObjects(false).mustNotBeMissing();
958958
casts.arg("recursive").mapMissing(Predef.constant(RRuntime.LOGICAL_FALSE)).mustBe(logicalValue().or(Predef.nullValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustBe(
959959
notLogicalNA()).map(Predef.toBoolean());
960+
casts.arg("dropDimensions").mapMissing(Predef.constant(RRuntime.LOGICAL_FALSE)).mustBe(logicalValue().or(Predef.nullValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustBe(
961+
notLogicalNA()).map(Predef.toBoolean());
960962
}
961963

962964
private final ConditionProfile isArrayProfile = ConditionProfile.createBinaryProfile();
963965

964966
@Specialization(guards = {"isForeignObject(obj)"})
965967
@TruffleBoundary
966-
public Object fromArray(TruffleObject obj, boolean recursive,
968+
public Object asVector(TruffleObject obj, boolean recursive, boolean dropDimensions,
967969
@Cached("HAS_SIZE.createNode()") Node hasSize,
968970
@Cached("create()") ForeignArray2R array2R) {
969971
if (isArrayProfile.profile(ForeignAccess.sendHasSize(hasSize, obj))) {
970-
return array2R.convert(obj, recursive);
972+
return array2R.convert(obj, recursive, dropDimensions);
971973
} else {
972-
throw error(RError.Message.GENERIC, "not a java array");
974+
// a non-array we can convert only to List
975+
return array2R.convertToList(obj, recursive, dropDimensions);
973976
}
974977
}
975978

976979
@Fallback
977-
public Object fromObject(@SuppressWarnings("unused") Object obj, @SuppressWarnings("unused") Object recursive) {
978-
throw error(RError.Message.GENERIC, "not a java array");
980+
public Object fallback(@SuppressWarnings("unused") Object obj, @SuppressWarnings("unused") Object recursive, @SuppressWarnings("unused") Object dropDimensions) {
981+
return RNull.instance;
979982
}
980983
}
981984

com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.oracle.truffle.api.interop.ForeignAccess;
3434
import com.oracle.truffle.api.interop.InteropException;
3535
import com.oracle.truffle.api.interop.KeyInfo;
36+
import com.oracle.truffle.api.interop.Message;
3637
import com.oracle.truffle.api.interop.TruffleObject;
3738
import com.oracle.truffle.api.nodes.Node;
3839
import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -68,7 +69,7 @@
6869
import com.oracle.truffle.r.runtime.env.REnvironment;
6970
import com.oracle.truffle.r.runtime.interop.Foreign2R;
7071
import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
71-
import com.oracle.truffle.r.runtime.interop.ForeignArray2R.ForeignArrayData;
72+
import com.oracle.truffle.r.runtime.interop.ForeignTypeCheck;
7273
import com.oracle.truffle.r.runtime.nodes.RBaseNode;
7374

7475
@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
@@ -249,6 +250,7 @@ protected ExtractVectorNode getThis() {
249250
return this;
250251
}
251252

253+
@ImportStatic(Message.class)
252254
protected static final class GenericVectorExtractNode extends TruffleBoundaryNode {
253255

254256
@Child private CachedExtractVectorNode cached;
@@ -278,20 +280,18 @@ public CachedExtractVectorNode get(ExtractVectorNode node, RAbstractContainer ve
278280
@Specialization(guards = {"isForeignObject(object)", "positionsByVector(positions)"})
279281
protected Object accessFieldByVectorPositions(TruffleObject object, Object[] positions, @SuppressWarnings("unused") Object exact, @SuppressWarnings("unused") Object dropDimensions,
280282
@Cached("createReadElement()") ReadElementNode readElement,
281-
@Cached("IS_NULL.createNode()") Node isNullNode,
282-
@Cached("IS_BOXED.createNode()") Node isBoxedNode,
283-
@Cached("UNBOX.createNode()") Node unboxNode,
284283
@Cached("create()") Foreign2R foreign2RNode) {
285284

286285
RAbstractVector vec = (RAbstractVector) positions[0];
287-
ForeignArrayData arrayData = new ForeignArrayData();
288-
289286
try {
287+
ForeignTypeCheck typeCheck = new ForeignTypeCheck();
288+
Object[] elements = new Object[vec.getLength()];
290289
for (int i = 0; i < vec.getLength(); i++) {
291290
Object res = readElement.execute(vec.getDataAtAsObject(i), object);
292-
arrayData.process(res, () -> isNullNode, () -> isBoxedNode, () -> unboxNode, () -> foreign2RNode, false);
291+
elements[i] = foreign2RNode.execute(res);
292+
typeCheck.check(elements[i]);
293293
}
294-
return ForeignArray2R.asAbstractVector(arrayData);
294+
return ForeignArray2R.asAbstractVector(elements, typeCheck.getType());
295295
} catch (InteropException e) {
296296
CompilerDirectives.transferToInterpreter();
297297
throw RError.interopError(RError.findParentRBase(this), e, object);

com.oracle.truffle.r.pkgs/rJava/R/jfirst.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@
471471
}
472472
obj <- attr(obj, "external.object", exact=TRUE)
473473
# we rely on this being called only if obj is an external array
474-
obj <- .fastr.interop.fromArray(obj)
474+
obj <- .fastr.interop.asVector(obj)
475475
lapply(obj, function(e) {.fromJ(e, toExtPointer=TRUE)})
476476
}
477477

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import com.oracle.truffle.r.runtime.RInternalError;
3333
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
3434
import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
35-
import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
35+
import com.oracle.truffle.r.runtime.interop.CopyForeignArrayNode;
3636

3737
public abstract class RForeignWrapper implements RAbstractVector {
3838

@@ -42,7 +42,7 @@ public abstract class RForeignWrapper implements RAbstractVector {
4242
protected static final Node UNBOX = Message.UNBOX.createNode();
4343
protected static final Node READ = Message.READ.createNode();
4444

45-
private static final ForeignArray2R FOREIGN_ARRAY_2R = ForeignArray2R.create();
45+
private static final CopyForeignArrayNode COPY_ARRAY = CopyForeignArrayNode.create();
4646

4747
protected final TruffleObject delegate;
4848

@@ -92,7 +92,7 @@ public final void setDimensions(int[] newDimensions) {
9292

9393
@Override
9494
public final RAbstractVector copy() {
95-
return (RAbstractVector) FOREIGN_ARRAY_2R.copy(delegate, true);
95+
return COPY_ARRAY.toVector(delegate, getRType());
9696
}
9797

9898
@Override

0 commit comments

Comments
 (0)