diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java index cc09614f38e9b177055a10306df953c5685e74c0..6db16cea3c9e35643226d7397fdd843efb280cfe 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java @@ -81,14 +81,12 @@ public abstract class Names extends RBuiltinNode.Arg1 { protected Object getNames(TruffleObject obj, @Cached("GET_SIZE.createNode()") Node getSizeNode, @Cached("KEYS.createNode()") Node keysNode, - @Cached("READ.createNode()") Node readNode, - @Cached("IS_BOXED.createNode()") Node isBoxedNode, - @Cached("UNBOX.createNode()") Node unboxNode) { + @Cached("READ.createNode()") Node readNode) { try { String[] names; try { - names = readKeys(keysNode, obj, getSizeNode, readNode, isBoxedNode, unboxNode); + names = readKeys(keysNode, obj, getSizeNode, readNode); } catch (UnsupportedMessageException e) { // because it is a java function, java.util.Map (has special handling too) ... ? return RNull.instance; @@ -96,7 +94,7 @@ public abstract class Names extends RBuiltinNode.Arg1 { String[] staticNames = new String[0]; try { if (JavaInterop.isJavaObject(Object.class, obj)) { - staticNames = readKeys(keysNode, toJavaClass(obj), getSizeNode, readNode, isBoxedNode, unboxNode); + staticNames = readKeys(keysNode, toJavaClass(obj), getSizeNode, readNode); } } catch (UnknownIdentifierException | NoSuchFieldError | UnsupportedMessageException e) { // because it is a class ... ? @@ -118,18 +116,14 @@ public abstract class Names extends RBuiltinNode.Arg1 { return JavaInterop.toJavaClass(obj); } - private static String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode, Node isBoxedNode, Node unboxNode) + private static String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode) throws UnknownIdentifierException, InteropException, UnsupportedMessageException { - TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj); + TruffleObject keys = ForeignAccess.sendKeys(keysNode, obj); if (keys != null) { int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys); String[] names = new String[size]; for (int i = 0; i < size; i++) { - Object value; - value = ForeignAccess.sendRead(readNode, keys, i); - if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) { - value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value); - } + Object value = ForeignAccess.sendRead(readNode, keys, i); names[i] = (String) value; } return names; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java index bea08a0ce86a96e7a6b346089e5ff581d582c9e4..aefbeedf3e0ca1f840edfbf0eaa134e4b822aeb8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java @@ -22,9 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base.printer; +import com.oracle.truffle.api.CompilerDirectives; import java.io.IOException; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.InteropException; @@ -33,7 +33,6 @@ import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.object.DynamicObject; -import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode; import com.oracle.truffle.r.nodes.builtin.base.InheritsBuiltin; import com.oracle.truffle.r.nodes.builtin.base.InheritsBuiltinNodeGen; @@ -51,7 +50,6 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode; 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.RType; import com.oracle.truffle.r.runtime.data.RAttributeStorage; import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -69,6 +67,12 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.interop.Foreign2R; +import com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck; +import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck.RType.BOOLEAN; +import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck.RType.DOUBLE; +import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck.RType.INTEGER; +import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck.RType.STRING; import com.oracle.truffle.r.runtime.nodes.RBaseNode; public final class ValuePrinterNode extends RBaseNode { @@ -96,7 +100,7 @@ public final class ValuePrinterNode extends RBaseNode { @Child private Node isBoxedNode = com.oracle.truffle.api.interop.Message.IS_BOXED.createNode(); @Child private Node unboxNode = com.oracle.truffle.api.interop.Message.UNBOX.createNode(); @Child private Node keysNode = com.oracle.truffle.api.interop.Message.KEYS.createNode(); - @Child private SetFixedAttributeNode namesAttrSetter = SetFixedAttributeNode.createNames(); + @Child private Foreign2R foreign2R = Foreign2R.createForeign2R(); @TruffleBoundary public Object convert(TruffleObject obj) { @@ -118,13 +122,10 @@ public final class ValuePrinterNode extends RBaseNode { Object value; try { value = ForeignAccess.sendRead(readNode, object, index); - if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) { - value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value); - } + return String.valueOf(foreign2R.execute(value)); } catch (UnknownIdentifierException | UnsupportedMessageException e) { throw RInternalError.shouldNotReachHere(e); } - return String.valueOf(value); } @Override @@ -132,155 +133,148 @@ public final class ValuePrinterNode extends RBaseNode { throw RInternalError.shouldNotReachHere(); } } + class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector { + + private final RStringVector names; + + RListWrapper(int length, RStringVector names) { + super(length); + this.names = names; + if (names != null) { + DynamicObject attrs = RAttributesLayout.createNames(names); + initAttributes(attrs); + } + } + + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + public Object getDataAt(int index) { + try { + Object value = ForeignAccess.sendRead(readNode, obj, names != null ? names.getDataAt(index) : index); + return foreign2R.execute(value); + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + public RStringVector getNames() { + return names; + } + + @Override + public RList materialize() { + throw RInternalError.shouldNotReachHere(); + } + } try { if (ForeignAccess.sendHasSize(hasSizeNode, obj)) { int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, obj); - boolean allBoolean = true; - boolean allInteger = true; - boolean allNumber = true; - boolean allCharacter = true; - boolean allString = true; + InteropTypeCheck typeCheck = new InteropTypeCheck(); for (int i = 0; i < size; i++) { Object value = ForeignAccess.sendRead(readNode, obj, i); if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) { value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value); } - allBoolean &= value instanceof Boolean; - allInteger &= value instanceof Integer; - allNumber &= value instanceof Number; - allCharacter &= value instanceof Character; - allString &= value instanceof String; + if (typeCheck.checkForeign(value) == InteropTypeCheck.RType.NONE) { + break; + } } - if (allBoolean) { - class RLogicalWrapper extends TruffleObjectWrapper implements RAbstractLogicalVector { + switch (typeCheck.getType()) { + case BOOLEAN: + class RLogicalWrapper extends TruffleObjectWrapper implements RAbstractLogicalVector { - RLogicalWrapper(int length) { - super(length); - } + RLogicalWrapper(int length) { + super(length); + } - @Override - public Object getDataAtAsObject(int index) { - return getDataAt(index); - } + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } - @Override - public byte getDataAt(int index) { - Object value; - try { - value = ForeignAccess.sendRead(readNode, obj, index); - if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) { - value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value); + @Override + public byte getDataAt(int index) { + try { + Object value = ForeignAccess.sendRead(readNode, obj, index); + return (byte) foreign2R.execute(value); + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); } - } catch (UnknownIdentifierException | UnsupportedMessageException e) { - throw RInternalError.shouldNotReachHere(e); } - return RRuntime.asLogical((Boolean) value); - } - @Override - public RLogicalVector materialize() { - throw RInternalError.shouldNotReachHere(); + @Override + public RLogicalVector materialize() { + throw RInternalError.shouldNotReachHere(); + } } - } - return new RLogicalWrapper(size); - } else if (allInteger) { - class RIntWrapper extends TruffleObjectWrapper implements RAbstractIntVector { + return new RLogicalWrapper(size); + case INTEGER: + class RIntWrapper extends TruffleObjectWrapper implements RAbstractIntVector { - RIntWrapper(int length) { - super(length); - } + RIntWrapper(int length) { + super(length); + } - @Override - public Object getDataAtAsObject(int index) { - return getDataAt(index); - } + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } - @Override - public int getDataAt(int index) { - Object value; - try { - value = ForeignAccess.sendRead(readNode, obj, index); - if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) { - value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value); + @Override + public int getDataAt(int index) { + try { + Object value = ForeignAccess.sendRead(readNode, obj, index); + return ((Number) foreign2R.execute(value)).intValue(); + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); } - } catch (UnknownIdentifierException | UnsupportedMessageException e) { - throw RInternalError.shouldNotReachHere(e); } - return (Integer) value; - } - - @Override - public RIntVector materialize() { - throw RInternalError.shouldNotReachHere(); - } - } - return new RIntWrapper(size); - } else if (allNumber) { - class RDoubleWrapper extends TruffleObjectWrapper implements RAbstractDoubleVector { - - RDoubleWrapper(int length) { - super(length); - } - - @Override - public Object getDataAtAsObject(int index) { - return getDataAt(index); - } - @Override - public double getDataAt(int index) { - Object value; - try { - value = ForeignAccess.sendRead(readNode, obj, index); - if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) { - value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value); - } - } catch (UnknownIdentifierException | UnsupportedMessageException e) { - throw RInternalError.shouldNotReachHere(e); + @Override + public RIntVector materialize() { + throw RInternalError.shouldNotReachHere(); } - return ((Number) value).doubleValue(); } + return new RIntWrapper(size); + case DOUBLE: + class RDoubleWrapper extends TruffleObjectWrapper implements RAbstractDoubleVector { - @Override - public RDoubleVector materialize() { - throw RInternalError.shouldNotReachHere(); - } - } - return new RDoubleWrapper(size); - } else if (allString || allCharacter) { - return new RStringWrapper(size, obj); - } else { - class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector { - - RListWrapper(int length) { - super(length); - } + RDoubleWrapper(int length) { + super(length); + } - @Override - public Object getDataAtAsObject(int index) { - return getDataAt(index); - } + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } - @Override - public Object getDataAt(int index) { - Object value; - try { - value = ForeignAccess.sendRead(readNode, obj, index); - if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) { - value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value); + @Override + public double getDataAt(int index) { + try { + Object value = ForeignAccess.sendRead(readNode, obj, index); + return ((Number) foreign2R.execute(value)).doubleValue(); + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); } - } catch (UnknownIdentifierException | UnsupportedMessageException e) { - throw RInternalError.shouldNotReachHere(e); } - return value; - } - @Override - public RList materialize() { - throw RInternalError.shouldNotReachHere(); + @Override + public RDoubleVector materialize() { + throw RInternalError.shouldNotReachHere(); + } } - } - return new RListWrapper(size); + return new RDoubleWrapper(size); + case STRING: + return new RStringWrapper(size, obj); + case NONE: + return new RListWrapper(size, null); + default: + throw RInternalError.shouldNotReachHere(); } } TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj); @@ -292,44 +286,7 @@ public final class ValuePrinterNode extends RBaseNode { names.setDataAt(names.getInternalStore(), i, abstractNames.getDataAt(i)); } - class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector { - - RListWrapper(int length) { - super(length); - DynamicObject attrs = RAttributesLayout.createNames(names); - initAttributes(attrs); - } - - @Override - public Object getDataAtAsObject(int index) { - return getDataAt(index); - } - - @Override - public Object getDataAt(int index) { - Object value; - try { - value = ForeignAccess.sendRead(readNode, obj, names.getDataAt(index)); - if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) { - value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value); - } - } catch (UnknownIdentifierException | UnsupportedMessageException e) { - throw RInternalError.shouldNotReachHere(e); - } - return value; - } - - @Override - public RStringVector getNames() { - return names; - } - - @Override - public RList materialize() { - throw RInternalError.shouldNotReachHere(); - } - } - return new RListWrapper(size); + return new RListWrapper(size, names); } } catch (InteropException e) { // nothing to do @@ -530,11 +487,6 @@ public final class ValuePrinterNode extends RBaseNode { throw RInternalError.shouldNotReachHere(); } - @Override - public RType getRType() { - return RType.Integer; - } - @Override public ForeignAccess getForeignAccess() { throw RInternalError.shouldNotReachHere(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java index e3c2e29a373bec5ea0d6026dc2f2b3b6c09eb518..c3278b4310ed49742d6456bf8a5c006b1a26d6b3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java @@ -79,13 +79,7 @@ final class ValuePrinters implements ValuePrinter<Object> { } else { // handle types that are meant for or can appear via Truffle interop Object x = v; - if (x instanceof Boolean) { - x = RRuntime.asLogical((Boolean) x); - } else if (x instanceof Long || x instanceof Short || x instanceof Float) { - x = ((Number) x).doubleValue(); - } else if (x instanceof Character) { - x = ((Character) x).toString(); - } else if (x instanceof RInteropScalar) { + if (x instanceof RInteropScalar) { x = ((RInteropScalar) x).getRValue(); } // try to box a scalar primitive value to the respective vector diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java index a493d13ce2c342db57e014c1216d48975984bd55..93bad4256df8cc09352cf72034aa061adce059fe 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java @@ -31,7 +31,6 @@ import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.interop.KeyInfo; import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ValueProfile; @@ -220,16 +219,12 @@ public abstract class ExtractVectorNode extends RBaseNode { @Cached("create()") CastStringNode castNode, @Cached("createFirstString()") FirstStringNode firstString, @Cached("createClassProfile()") ValueProfile positionProfile, - @Cached("IS_NULL.createNode()") Node isNullNode, - @Cached("IS_BOXED.createNode()") Node isBoxedNode, - @Cached("UNBOX.createNode()") Node unboxNode, @Cached("createForeign2RNode()") Foreign2R foreign2RNode) { Object[] pos = positionProfile.profile(positions); if (pos.length == 0) { throw error(RError.Message.GENERIC, "No positions for foreign access."); } try { - // TODO implicite unboxing ok? method calls seem to behave this way Object result = object; for (int i = 0; i < pos.length; i++) { result = read(this, pos[i], foreignRead, keyInfoNode, hasSizeNode, (TruffleObject) result, firstString, castNode); @@ -237,24 +232,12 @@ public abstract class ExtractVectorNode extends RBaseNode { assert result instanceof TruffleObject; } } - return unbox(result, isNullNode, isBoxedNode, unboxNode, foreign2RNode); + return foreign2RNode.execute(result); } catch (InteropException | NoSuchFieldError e) { throw RError.interopError(RError.findParentRBase(this), e, object); } } - private static Object unbox(Object obj, Node isNullNode, Node isBoxedNode, Node unboxNode, Foreign2R foreign2RNode) throws UnsupportedMessageException { - if (RRuntime.isForeignObject(obj)) { - if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) obj)) { - return RNull.instance; - } - if (ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) obj)) { - return foreign2RNode.execute(ForeignAccess.sendUnbox(unboxNode, (TruffleObject) obj)); - } - } - return foreign2RNode.execute(obj); - } - public static Object read(RBaseNode caller, Object positions, Node foreignRead, Node keyInfoNode, Node hasSizeNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode) throws RError, InteropException { Object pos = positions; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index b1732b1e1c45ed98026d07c5249d1ef1fa8b0e89..58a993f8712f6aac3c59d263b5e5aacc19866943 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -539,7 +539,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Child private CallArgumentsNode arguments; @Child private Node foreignCall; - @Child private Node isNullCall; @CompilationFinal private int foreignCallArgCount; public ForeignCall(CallArgumentsNode arguments) { @@ -558,15 +557,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS argumentsArray[i] = r2Foreign.execute(argumentsArray[i]); } Object result = ForeignAccess.sendExecute(foreignCall, function, argumentsArray); - if (RRuntime.isForeignObject(result)) { - if (isNullCall == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - isNullCall = insert(Message.IS_NULL.createNode()); - } - if (ForeignAccess.sendIsNull(isNullCall, (TruffleObject) result)) { - return RNull.instance; - } - } return foreign2R.execute(result); } catch (ArityException | UnsupportedMessageException | UnsupportedTypeException e) { CompilerDirectives.transferToInterpreter(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java index 5642fa86b7857bc1780b2f765ce375f571841be6..df43ab4120f35065ede99648b15d3bd54e3f6d0c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java @@ -30,8 +30,8 @@ import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -40,6 +40,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class Foreign2R extends RBaseNode { @Child private Foreign2R recursive; + @Child private Node isNull; @Child private Node isBoxed; @Child private Node unbox; @@ -85,7 +86,15 @@ public abstract class Foreign2R extends RBaseNode { } @Specialization(guards = "isForeignObject(obj)") - public Object doUnbox(TruffleObject obj) { + public Object doForeignObject(TruffleObject obj) { + if (isNull == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isNull = insert(Message.IS_NULL.createNode()); + } + if (ForeignAccess.sendIsNull(isNull, obj)) { + return RNull.instance; + } + /* * For the time being, we have to ask "IS_BOXED" all the time (instead of simply trying * UNBOX first), because some TruffleObjects return bogus values from UNBOX when IS_BOXED is diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java index ebf2d491225124af8bb65854e424c342c044ae02..b6aca07127a1c8bb2281047fdc47971949c92a9b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java @@ -195,12 +195,11 @@ public abstract class ForeignArray2R extends RBaseNode { */ public static RAbstractVector asAbstractVector(CollectedElements ce) { InteropTypeCheck.RType type = ce.typeCheck.getType(); - if (type == null) { - return RDataFactory.createList(ce.elements.toArray(new Object[ce.elements.size()])); - } int size = ce.elements.size(); boolean complete = true; switch (type) { + case NONE: + return RDataFactory.createList(ce.elements.toArray(new Object[ce.elements.size()])); case BOOLEAN: byte[] bytes = new byte[size]; for (int i = 0; i < size; i++) { @@ -263,13 +262,13 @@ public abstract class ForeignArray2R extends RBaseNode { BOOLEAN, DOUBLE, INTEGER, - STRING; + STRING, + NONE; } private RType type = null; - private boolean sameRType = true; - public void checkForeign(Object value) { + public RType checkForeign(Object value) { if (value instanceof Boolean) { setType(RType.BOOLEAN); } else if (value instanceof Byte || value instanceof Integer || value instanceof Short) { @@ -279,12 +278,12 @@ public abstract class ForeignArray2R extends RBaseNode { } else if (value instanceof Character || value instanceof String) { setType(RType.STRING); } else { - this.type = null; - sameRType = false; + this.type = RType.NONE; } + return this.type; } - public void checkVector(RAbstractVector value) { + public RType checkVector(RAbstractVector value) { if (value instanceof RAbstractLogicalVector) { setType(RType.BOOLEAN); } else if (value instanceof RAbstractIntVector) { @@ -294,22 +293,23 @@ public abstract class ForeignArray2R extends RBaseNode { } else if (value instanceof RAbstractStringVector) { setType(RType.STRING); } else { - this.type = null; - sameRType = false; + this.type = RType.NONE; } + return this.type; } private void setType(RType check) { - if (sameRType && this.type == null) { - this.type = check; - } else if (this.type != check) { - this.type = null; - sameRType = false; + if (this.type != RType.NONE) { + if (this.type == null) { + this.type = check; + } else if (this.type != check) { + this.type = RType.NONE; + } } } public RType getType() { - return sameRType ? type : null; + return type != null ? type : RType.NONE; } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 6ece459577d039a5b1fc206a9d530e9c0e187206..dc9999464e0b320d741dc95909a1792f791257d5 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -133622,6 +133622,25 @@ NULL #if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticBooleanObject } [1] TRUE +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (!any(R.version$engine == "FastR")) { cat('[external object]<<<NEWLINE>>>[[1]]<<<NEWLINE>>>[1] 1<<<NEWLINE>>><<<NEWLINE>>>[[2]]<<<NEWLINE>>>[1] 2.1<<<NEWLINE>>><<<NEWLINE>>>[[3]]<<<NEWLINE>>>[1] "a"<<<NEWLINE>>><<<NEWLINE>>>[[4]]<<<NEWLINE>>>[1] TRUE<<<NEWLINE>>><<<NEWLINE>>>[[5]]<<<NEWLINE>>>NULL<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$mixedTypesArray } +[external object] +[[1]] +[1] 1 + +[[2]] +[1] 2.1 + +[[3]] +[1] "a" + +[[4]] +[1] TRUE + +[[5]] +NULL + + ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# #if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] TRUE FALSE TRUE\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldBooleanArray } [external object] diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java index 6c62351cee58b76edf2d5d784269bc68e1e485e7..e28f6b0ebb6eb9d67d8ffc5806bc990efc3a815a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java @@ -390,6 +390,8 @@ public class TestJavaInterop extends TestBase { testForValue(name, f.get(t)); } } + assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$mixedTypesArray", + "cat('[external object]\n[[1]]\n[1] 1\n\n[[2]]\n[1] 2.1\n\n[[3]]\n[1] \"a\"\n\n[[4]]\n[1] TRUE\n\n[[5]]\nNULL\n\n', sep='')"); } @Test @@ -1417,12 +1419,16 @@ public class TestJavaInterop extends TestBase { return sb.toString(); } - private static String getBooleanPrefix(Object value, int i) { - if (value.getClass().getComponentType() == Boolean.TYPE && (boolean) Array.get(value, i)) { + private static String getBooleanPrefix(Object array, int i) { + Object element = Array.get(array, i); + if (element == null) { + return ""; + } + if (array.getClass().getComponentType() == Boolean.TYPE && (boolean) element) { return " "; } - if (i > 0 && value.getClass().getComponentType() == String.class && - (Array.get(value, i).equals("T") || Array.get(value, i).equals("F") || Array.get(value, i).equals("TRUE") || Array.get(value, i).equals("FALSE"))) { + if (i > 0 && array.getClass().getComponentType() == String.class && + (element.equals("T") || element.equals("F") || element.equals("TRUE") || element.equals("FALSE"))) { return " "; } return ""; @@ -1830,7 +1836,7 @@ public class TestJavaInterop extends TestBase { objectArray = new Object[]{new Object(), new Object(), new Object()}; objectIntArray = new Object[]{1, 2, 3}; objectDoubleArray = new Object[]{1.1, 2.1, 3.1}; - mixedTypesArray = new Object[]{1, 2.1, 'a'}; + mixedTypesArray = new Object[]{1, 2.1, 'a', true, null}; hasNullIntArray = new Integer[]{1, null, 3}; map = new HashMap<>();