diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java index 090cd5aa987d71ee1ac1da2c7155bc2e7643cdd2..5a9c503079500a97603e9ffdb595104feaa5314e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java @@ -62,6 +62,7 @@ public enum FastROptions { EmitTmpHashed("Use an SHA-256 hash as file name to reduce temporary file creation.", true), SpawnUsesPolyglot("use PolyglotEngine for .fastr.context.spwan", false), SynchronizeNativeCode("allow only one thread to enter packages' native code", false), + ForeignObjectWrappers("use wrappers for foreign objects (as opposed to full conversion)", false), // Promises optimizations EagerEval("If enabled, overrides all other EagerEval switches (see EagerEvalHelper)", false), diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignBooleanWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignBooleanWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..b3c30b09276c0864281b5cbd856c0b8cb0c876ea --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignBooleanWrapper.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.runtime.data; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +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.UnknownIdentifierException; +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.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.nodes.FastPathVectorAccess.FastPathFromLogicalAccess; +import com.oracle.truffle.r.runtime.data.nodes.SlowPathVectorAccess.SlowPathFromLogicalAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; + +public final class RForeignBooleanWrapper extends RForeignWrapper implements RAbstractLogicalVector { + + public RForeignBooleanWrapper(TruffleObject delegate) { + super(delegate); + } + + @Override + public RLogicalVector materialize() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + @TruffleBoundary + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + @TruffleBoundary + public byte getDataAt(int index) { + try { + return RRuntime.asLogical((boolean) ForeignAccess.sendRead(READ, delegate, index)); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + private static final class FastPathAccess extends FastPathFromLogicalAccess { + + FastPathAccess(RAbstractContainer value) { + super(value); + } + + @Child private Node getSize = Message.GET_SIZE.createNode(); + @Child private Node read = Message.READ.createNode(); + + @Override + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(getSize, ((RForeignWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + protected byte getLogical(Object internalStore, int index) { + try { + return RRuntime.asLogical((boolean) ForeignAccess.sendRead(read, (TruffleObject) internalStore, index)); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + @Override + public VectorAccess access() { + return new FastPathAccess(this); + } + + private static final SlowPathFromLogicalAccess SLOW_PATH_ACCESS = new SlowPathFromLogicalAccess() { + @Override + @TruffleBoundary + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(GET_SIZE, ((RForeignBooleanWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + protected byte getLogical(Object store, int index) { + RForeignBooleanWrapper vector = (RForeignBooleanWrapper) store; + try { + return RRuntime.asLogical((boolean) ForeignAccess.sendRead(READ, vector.delegate, index)); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + }; + + @Override + public VectorAccess slowPathAccess() { + return SLOW_PATH_ACCESS; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignDoubleWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignDoubleWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..90dbbe7faf6395e88a163bef390b916e28a1bf28 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignDoubleWrapper.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.runtime.data; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +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.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.nodes.FastPathVectorAccess.FastPathFromDoubleAccess; +import com.oracle.truffle.r.runtime.data.nodes.SlowPathVectorAccess.SlowPathFromDoubleAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; + +public final class RForeignDoubleWrapper extends RForeignWrapper implements RAbstractDoubleVector { + + public RForeignDoubleWrapper(TruffleObject delegate) { + super(delegate); + } + + @Override + public RDoubleVector materialize() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + @TruffleBoundary + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + @TruffleBoundary + public double getDataAt(int index) { + try { + return ((Number) ForeignAccess.sendRead(READ, delegate, index)).doubleValue(); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + private static final class FastPathAccess extends FastPathFromDoubleAccess { + + FastPathAccess(RAbstractContainer value) { + super(value); + } + + private final ValueProfile resultProfile = ValueProfile.createClassProfile(); + @Child private Node getSize = Message.GET_SIZE.createNode(); + @Child private Node read = Message.READ.createNode(); + + @Override + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(getSize, ((RForeignWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + protected double getDouble(Object internalStore, int index) { + try { + return ((Number) resultProfile.profile(ForeignAccess.sendRead(read, (TruffleObject) internalStore, index))).doubleValue(); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + @Override + public VectorAccess access() { + return new FastPathAccess(this); + } + + private static final SlowPathFromDoubleAccess SLOW_PATH_ACCESS = new SlowPathFromDoubleAccess() { + @Override + @TruffleBoundary + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(GET_SIZE, ((RForeignDoubleWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + protected double getDouble(Object store, int index) { + RForeignDoubleWrapper vector = (RForeignDoubleWrapper) store; + try { + return ((Number) ForeignAccess.sendRead(READ, vector.delegate, index)).doubleValue(); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + }; + + @Override + public VectorAccess slowPathAccess() { + return SLOW_PATH_ACCESS; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignIntWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignIntWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..68c4ca07ead520b8c62cc97ba41b58f6a5b94e98 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignIntWrapper.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.runtime.data; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +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.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.nodes.FastPathVectorAccess.FastPathFromIntAccess; +import com.oracle.truffle.r.runtime.data.nodes.SlowPathVectorAccess.SlowPathFromIntAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; + +public final class RForeignIntWrapper extends RForeignWrapper implements RAbstractIntVector { + + public RForeignIntWrapper(TruffleObject delegate) { + super(delegate); + } + + @Override + public RIntVector materialize() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + @TruffleBoundary + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + @TruffleBoundary + public int getDataAt(int index) { + try { + return ((Number) ForeignAccess.sendRead(READ, delegate, index)).intValue(); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + private static final class FastPathAccess extends FastPathFromIntAccess { + + FastPathAccess(RAbstractContainer value) { + super(value); + } + + private final ValueProfile resultProfile = ValueProfile.createClassProfile(); + @Child private Node getSize = Message.GET_SIZE.createNode(); + @Child private Node read = Message.READ.createNode(); + + @Override + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(getSize, ((RForeignWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + protected int getInt(Object internalStore, int index) { + try { + return ((Number) resultProfile.profile(ForeignAccess.sendRead(read, (TruffleObject) internalStore, index))).intValue(); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + @Override + public VectorAccess access() { + return new FastPathAccess(this); + } + + private static final SlowPathFromIntAccess SLOW_PATH_ACCESS = new SlowPathFromIntAccess() { + @Override + @TruffleBoundary + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(GET_SIZE, ((RForeignIntWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + protected int getInt(Object store, int index) { + RForeignIntWrapper vector = (RForeignIntWrapper) store; + try { + return ((Number) ForeignAccess.sendRead(READ, vector.delegate, index)).intValue(); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + }; + + @Override + public VectorAccess slowPathAccess() { + return SLOW_PATH_ACCESS; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignListWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignListWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..6a67f4c389310fd510d10f658549f03a3d35d072 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignListWrapper.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.runtime.data; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +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.UnknownIdentifierException; +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.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; +import com.oracle.truffle.r.runtime.data.nodes.FastPathVectorAccess.FastPathFromListAccess; +import com.oracle.truffle.r.runtime.data.nodes.SlowPathVectorAccess.SlowPathFromListAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; + +public final class RForeignListWrapper extends RForeignWrapper implements RAbstractListVector { + + public RForeignListWrapper(TruffleObject delegate) { + super(delegate); + } + + @Override + public RList materialize() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + @TruffleBoundary + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + @TruffleBoundary + public Object getDataAt(int index) { + try { + return ForeignAccess.sendRead(READ, delegate, index); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + private static final class FastPathAccess extends FastPathFromListAccess { + + FastPathAccess(RAbstractContainer value) { + super(value); + } + + @Child private Node getSize = Message.GET_SIZE.createNode(); + @Child private Node read = Message.READ.createNode(); + + @Override + public RType getType() { + return RType.List; + } + + @Override + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(getSize, ((RForeignWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + protected Object getListElement(Object internalStore, int index) { + try { + return ForeignAccess.sendRead(read, (TruffleObject) internalStore, index); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + @Override + public VectorAccess access() { + return new FastPathAccess(this); + } + + private static final SlowPathFromListAccess SLOW_PATH_ACCESS = new SlowPathFromListAccess() { + @Override + public RType getType() { + return RType.List; + } + + @Override + @TruffleBoundary + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(GET_SIZE, ((RForeignListWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + protected Object getListElement(Object store, int index) { + RForeignListWrapper vector = (RForeignListWrapper) store; + try { + return ForeignAccess.sendRead(READ, vector.delegate, index); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + }; + + @Override + public VectorAccess slowPathAccess() { + return SLOW_PATH_ACCESS; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignNamedListWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignNamedListWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..5c3be432639391b85ea7362c6c8bb0bc178392d2 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignNamedListWrapper.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.runtime.data; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +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.UnknownIdentifierException; +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.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; +import com.oracle.truffle.r.runtime.data.nodes.FastPathVectorAccess.FastPathFromListAccess; +import com.oracle.truffle.r.runtime.data.nodes.SlowPathVectorAccess.SlowPathFromListAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; +import com.oracle.truffle.r.runtime.interop.Foreign2R; + +public final class RForeignNamedListWrapper extends RForeignWrapper implements RAbstractListVector { + + private final RStringVector names; + + public RForeignNamedListWrapper(TruffleObject delegate, RStringVector names) { + super(delegate); + this.names = names; + } + + @Override + public Object getInternalStore() { + return this; + } + + @Override + public int getLength() { + return names.getLength(); + } + + @Override + public RStringVector getNames() { + return names; + } + + @Override + public RList materialize() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + @TruffleBoundary + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + @TruffleBoundary + public Object getDataAt(int index) { + try { + return FOREIGN_TO_R.execute(ForeignAccess.sendRead(READ, delegate, names.getDataAt(index))); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + private static final class FastPathAccess extends FastPathFromListAccess { + + FastPathAccess(RAbstractContainer value) { + super(value); + } + + @Child private Node getSize = Message.GET_SIZE.createNode(); + @Child private Node read = Message.READ.createNode(); + @Child private Foreign2R foreign2r = Foreign2R.create(); + + @Override + public RType getType() { + return RType.List; + } + + @Override + protected int getLength(RAbstractContainer vector) { + return ((RForeignNamedListWrapper) vector).getLength(); + } + + @Override + protected Object getListElement(Object internalStore, int index) { + try { + RForeignNamedListWrapper wrapper = (RForeignNamedListWrapper) internalStore; + return foreign2r.execute(ForeignAccess.sendRead(read, wrapper.delegate, wrapper.names.getDataAt(index))); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + @Override + public VectorAccess access() { + return new FastPathAccess(this); + } + + private static final Foreign2R FOREIGN_TO_R = Foreign2R.create(); + + private static final SlowPathFromListAccess SLOW_PATH_ACCESS = new SlowPathFromListAccess() { + @Override + public RType getType() { + return RType.List; + } + + @Override + @TruffleBoundary + protected int getLength(RAbstractContainer vector) { + return ((RForeignNamedListWrapper) vector).names.getLength(); + } + + @Override + protected Object getListElement(Object store, int index) { + RForeignNamedListWrapper vector = (RForeignNamedListWrapper) store; + try { + return FOREIGN_TO_R.execute(ForeignAccess.sendRead(READ, vector.delegate, vector.names.getDataAt(index))); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + }; + + @Override + public VectorAccess slowPathAccess() { + return SLOW_PATH_ACCESS; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignStringWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignStringWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..148bb9cf13a968cb98a128ef7cf69d20a3d21c8f --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignStringWrapper.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.runtime.data; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +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.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.nodes.FastPathVectorAccess.FastPathFromStringAccess; +import com.oracle.truffle.r.runtime.data.nodes.SlowPathVectorAccess.SlowPathFromStringAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; + +public final class RForeignStringWrapper extends RForeignWrapper implements RAbstractStringVector { + + public RForeignStringWrapper(TruffleObject delegate) { + super(delegate); + } + + @Override + public RStringVector materialize() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + @TruffleBoundary + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + @TruffleBoundary + public String getDataAt(int index) { + try { + return ForeignAccess.sendRead(READ, delegate, index).toString(); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + private static final class FastPathAccess extends FastPathFromStringAccess { + + FastPathAccess(RAbstractContainer value) { + super(value); + } + + private final ValueProfile resultProfile = ValueProfile.createClassProfile(); + @Child private Node getSize = Message.GET_SIZE.createNode(); + @Child private Node read = Message.READ.createNode(); + + @Override + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(getSize, ((RForeignWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + protected String getString(Object internalStore, int index) { + try { + return resultProfile.profile(ForeignAccess.sendRead(read, (TruffleObject) internalStore, index)).toString(); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + @Override + public VectorAccess access() { + return new FastPathAccess(this); + } + + private static final SlowPathFromStringAccess SLOW_PATH_ACCESS = new SlowPathFromStringAccess() { + @Override + @TruffleBoundary + protected int getLength(RAbstractContainer vector) { + try { + return (int) ForeignAccess.sendGetSize(GET_SIZE, ((RForeignStringWrapper) vector).delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + @TruffleBoundary + protected String getString(Object store, int index) { + RForeignStringWrapper vector = (RForeignStringWrapper) store; + try { + return ForeignAccess.sendRead(READ, vector.delegate, index).toString(); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + }; + + @Override + public VectorAccess slowPathAccess() { + return SLOW_PATH_ACCESS; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..79350c7cb3ec54287815eff5219e15f80f6004f4 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignWrapper.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.runtime.data; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +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.api.object.DynamicObject; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public abstract class RForeignWrapper implements RAbstractVector { + + protected static final Node GET_SIZE = Message.GET_SIZE.createNode(); + protected static final Node READ = Message.READ.createNode(); + + protected final TruffleObject delegate; + + protected RForeignWrapper(TruffleObject delegate) { + this.delegate = delegate; + } + + @Override + @TruffleBoundary + public final int getLength() { + try { + return (int) ForeignAccess.sendGetSize(GET_SIZE, delegate); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Override + public final RAbstractContainer resize(int size) { + return materialize().resize(size); + } + + @Override + public final boolean isComplete() { + return true; + } + + @Override + public final void setComplete(boolean complete) { + // sequences are always complete + } + + @Override + public final boolean hasDimensions() { + return false; + } + + @Override + public final int[] getDimensions() { + return null; + } + + @Override + public final void setDimensions(int[] newDimensions) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final RAbstractVector copy() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final RAbstractVector copyDropAttributes() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final RAbstractVector copyWithNewDimensions(int[] newDimensions) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final RStringVector getNames() { + return null; + } + + @Override + public final void setNames(RStringVector newNames) { + // should only be used on materialized sequence + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final RList getDimNames() { + return null; + } + + @Override + public final void setDimNames(RList newDimNames) { + // should only be used on materialized sequence + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final Object getRowNames() { + return RNull.instance; + } + + @Override + public final void setRowNames(RAbstractVector rowNames) { + // should only be used on materialized sequence + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final DynamicObject initAttributes() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final void initAttributes(DynamicObject newAttributes) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final DynamicObject getAttributes() { + return null; + } + + @Override + public final boolean isMatrix() { + return false; + } + + @Override + public final boolean isArray() { + return false; + } + + @Override + public final boolean isObject() { + return false; + } + + @Override + public final RTypedValue getNonShared() { + return materialize().getNonShared(); + } + + @Override + public final int getTypedValueInfo() { + return 0; + } + + @Override + public final void setTypedValueInfo(int value) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final boolean isS4() { + return false; + } + + @Override + public final Object getInternalStore() { + return delegate; + } + + @Override + public final RVector<?> copyResized(int size, boolean fillNA) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { + throw RInternalError.shouldNotReachHere(); + } +} 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 bb59cfc10cae05de573a6806be5509dc8c48a24c..43bffb637f5f30e311b4d1be0b663c15ddab6921 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 @@ -43,9 +43,16 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.FastROptions; 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.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RForeignBooleanWrapper; +import com.oracle.truffle.r.runtime.data.RForeignDoubleWrapper; +import com.oracle.truffle.r.runtime.data.RForeignIntWrapper; +import com.oracle.truffle.r.runtime.data.RForeignListWrapper; +import com.oracle.truffle.r.runtime.data.RForeignStringWrapper; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -59,9 +66,10 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class ForeignArray2R extends RBaseNode { @Child protected Node hasSize = Message.HAS_SIZE.createNode(); + @Child protected Node getSize = Message.GET_SIZE.createNode(); @Child private Foreign2R foreign2R; @Child private ForeignArray2R foreignArray2R; - @Child private Node read; + @Child private Node read = Message.READ.createNode(); @Child private Node isNull; @Child private Node isBoxed; @Child private Node unbox; @@ -91,25 +99,54 @@ public abstract class ForeignArray2R extends RBaseNode { * */ public Object convert(Object obj, boolean recursive) { - Object result = execute(obj, recursive, null, 0); - if (result instanceof ForeignArrayData) { - ForeignArrayData arrayData = (ForeignArrayData) result; - if (arrayData.elements.isEmpty()) { - return RDataFactory.createList(); + if (FastROptions.ForeignObjectWrappers.getBooleanValue()) { + if (isForeignArray(obj)) { + TruffleObject truffleObject = (TruffleObject) obj; + try { + int size = (int) ForeignAccess.sendGetSize(getSize, truffleObject); + if (size == 0) { + return new RForeignListWrapper(truffleObject); + } else { + Object firstElement = ForeignAccess.sendRead(read, truffleObject, 0); + switch (InteropTypeCheck.determineType(firstElement)) { + case BOOLEAN: + return new RForeignBooleanWrapper(truffleObject); + case DOUBLE: + return new RForeignDoubleWrapper(truffleObject); + case INTEGER: + return new RForeignIntWrapper(truffleObject); + case STRING: + return new RForeignStringWrapper(truffleObject); + default: + return new RForeignListWrapper(truffleObject); + } + } + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } + } else { + return obj; } - return asAbstractVector(arrayData); + } else { + Object result = execute(obj, recursive, null, 0); + if (result instanceof ForeignArrayData) { + ForeignArrayData arrayData = (ForeignArrayData) result; + if (arrayData.elements.isEmpty()) { + return RDataFactory.createList(); + } + return asAbstractVector(arrayData); + } + return result; } - return result; } protected abstract Object execute(Object obj, boolean recursive, ForeignArrayData arrayData, int depth); @Specialization(guards = {"isForeignArray(obj)"}) @TruffleBoundary - protected ForeignArrayData doArray(TruffleObject obj, boolean recursive, ForeignArrayData arrayData, int depth, - @Cached("GET_SIZE.createNode()") Node getSize) { + protected ForeignArrayData doArray(TruffleObject obj, boolean recursive, ForeignArrayData arrayData, int depth) { try { - return collectArrayElements(arrayData == null ? new ForeignArrayData() : arrayData, obj, recursive, getSize, depth); + return collectArrayElements(arrayData == null ? new ForeignArrayData() : arrayData, obj, recursive, depth); } catch (UnsupportedMessageException | UnknownIdentifierException e) { throw error(RError.Message.GENERIC, "error while converting array: " + e.getMessage()); } @@ -132,7 +169,7 @@ public abstract class ForeignArray2R extends RBaseNode { return obj; } - private ForeignArrayData collectArrayElements(ForeignArrayData arrayData, TruffleObject obj, boolean recursive, Node getSize, int depth) + private ForeignArrayData collectArrayElements(ForeignArrayData arrayData, TruffleObject obj, boolean recursive, int depth) throws UnsupportedMessageException, UnknownIdentifierException { int size = (int) ForeignAccess.sendGetSize(getSize, obj); @@ -152,10 +189,6 @@ public abstract class ForeignArray2R extends RBaseNode { return arrayData; } for (int i = 0; i < size; i++) { - if (read == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - read = insert(Message.READ.createNode()); - } Object element = ForeignAccess.sendRead(read, obj, i); if (recursive && (isForeignArray(element, hasSize) || isJavaIterable(element))) { recurse(arrayData, element, depth); @@ -387,6 +420,20 @@ public abstract class ForeignArray2R extends RBaseNode { private RType type = null; + public static RType determineType(Object value) { + if (value instanceof Boolean) { + return RType.BOOLEAN; + } else if (value instanceof Byte || value instanceof Integer || value instanceof Short) { + return RType.INTEGER; + } else if (value instanceof Double || value instanceof Float || value instanceof Long) { + return RType.DOUBLE; + } else if (value instanceof Character || value instanceof String) { + return RType.STRING; + } else { + return RType.NONE; + } + } + public RType checkForeign(Object value) { if (value instanceof Boolean) { setType(RType.BOOLEAN);