Skip to content

Commit

Permalink
Merge commit '30eb913081cb57319d554f83681e206cf5409a0c' into release/…
Browse files Browse the repository at this point in the history
…graal-vm/1.0
  • Loading branch information
ansalond committed Oct 30, 2018
2 parents 78d84e9 + 30eb913 commit 3a3e6cf
Show file tree
Hide file tree
Showing 24 changed files with 799 additions and 33 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# 1.0 RC 9

New features

* various improvements in handling of foreign objects in R

Added missing R builtins and C API

* eapply builtin
* rapply builtin

Bug fixes:

* colon builtin calculated length incorrectly in some circumstances
* `storage.mode<-` works with NULL
* Rf_coerceVector works with pairlists and language objects
* allow formal parameter names: '..1', '..1=default', '...=default'

# 1.0 RC 8

Bug fixes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,36 @@ protected Object convert(RAbstractVector v) {
return current;
}

@Specialization
protected Object convert(RNull x) {
if (type == SEXPTYPE.LISTSXP) {
return x;
} else {
return doFallback(x);
}
}

@Specialization
protected Object convert(RPairList list) {
if (list.isLanguage() || type == SEXPTYPE.LISTSXP) {
return list;
} else {
return doFallback(list);
}
}

@Fallback
@TruffleBoundary
protected Object doFallback(Object x) {
throw error(Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, Utils.getTypeName(x), "coercePairList");
}

private static void adjustSharing(RAbstractVector origin, Object element) {
if (origin instanceof RShareable) {
int v = getSharingLevel((RShareable) origin);
if (element instanceof RShareable) {
RShareable r = (RShareable) element;
if (v == 2) {
if (v >= 2) {
// we play it safe: if the caller wants this instance to be shared, they may
// expect it to never become non-shared again, which could happen in FastR
r.makeSharedPermanent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@
import com.oracle.truffle.r.nodes.unary.UnaryArithmeticSpecial;
import com.oracle.truffle.r.nodes.unary.UnaryNotNode;
import com.oracle.truffle.r.nodes.unary.UnaryNotNodeGen;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.RVisibility;
import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
Expand Down Expand Up @@ -628,6 +629,7 @@ public BasePackage() {
add(LaFunctions.LaLibrary.class, LaFunctionsFactory.LaLibraryNodeGen::create);
add(LaFunctions.Backsolve.class, LaFunctionsFactory.BacksolveNodeGen::create);
add(Lapply.class, LapplyNodeGen::create);
add(Rapply.class, RapplyNodeGen::create);
add(Length.class, LengthNodeGen::create);
add(Lengths.class, LengthsNodeGen::create);
add(License.class, LicenseNodeGen::create);
Expand Down Expand Up @@ -854,6 +856,10 @@ private void addBinaryCompare(Class<?> builtinClass, BooleanOperationFactory fac

private static void addFastPath(MaterializedFrame baseFrame, String name, FastPathFactory factory) {
RFunction function = ReadVariableNode.lookupFunction(name, baseFrame);
if (function == null) {
throw new RInternalError("failed adding the fast path for the R function " + name +
". The function was not found. This could be due to previous errors that prevented it from being loaded.");
}
((RRootNode) function.getRootNode()).setFastPath(factory);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ public abstract static class IsNumeric extends RBuiltinNode.Arg1 {
createCasts(IsNumeric.class);
}

@Child private InheritsCheckNode inheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR);
@Child private InheritsCheckNode inheritsCheck = InheritsCheckNode.create(RRuntime.CLASS_FACTOR);

protected boolean isFactor(Object o) {
return inheritsCheck.execute(o);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private static NewNames updateNewNames(RAbstractStringVector names, VectorReuse
NewNames nn = newNames;
if (nn == null) {
RAbstractStringVector res = reuse.getResult(names);
VectorAccess access = reuse.access(res);
VectorAccess access = res.slowPathAccess();
VectorAccess.RandomIterator iter = access.randomAccess(res);
nn = new NewNames(res, access, iter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ protected RIntVector match(RAbstractVector x, RNull table, int nomatch, Object i
return RDataFactory.createIntVector(data, na.profile(!RRuntime.isNA(nomatch)));
}

@Child private InheritsCheckNode factorInheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR);
@Child private InheritsCheckNode factorInheritsCheck = InheritsCheckNode.create(RRuntime.CLASS_FACTOR);

protected boolean isFactor(Object o) {
return factorInheritsCheck.execute(o);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
/*
* Copyright (c) 1995-2015, The R Core Team
* Copyright (c) 2016, 2018, Oracle and/or its affiliates
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, a copy is available at
* https://www.R-project.org/Licenses/
*/
package com.oracle.truffle.r.nodes.builtin.base;

import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue;
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant;
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
import static com.oracle.truffle.r.nodes.builtin.base.Lapply.createCallSourceSection;
import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.FrameSlotKind;
import com.oracle.truffle.api.frame.FrameSlotTypeException;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.profiles.LoopConditionProfile;
import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNodeGen;
import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.base.RapplyNodeGen.RapplyInternalNodeGen;
import com.oracle.truffle.r.nodes.control.RLengthNode;
import com.oracle.truffle.r.nodes.function.RCallBaseNode;
import com.oracle.truffle.r.nodes.function.RCallNode;
import com.oracle.truffle.r.nodes.unary.InheritsNode;
import com.oracle.truffle.r.nodes.unary.InheritsNodeGen;
import com.oracle.truffle.r.runtime.ArgumentsSignature;
import com.oracle.truffle.r.runtime.RArguments;
import com.oracle.truffle.r.runtime.RError.Message;
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.builtins.RBuiltin;
import com.oracle.truffle.r.runtime.context.RContext;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RFunction;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RListBase;
import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
import com.oracle.truffle.r.runtime.nodes.RBaseNode;
import com.oracle.truffle.r.runtime.nodes.RNode;
import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode;
import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;

@RBuiltin(name = "rapply", kind = INTERNAL, parameterNames = {"object", "f", "classes", "deflt", "how"}, splitCaller = true, behavior = COMPLEX)
public abstract class Rapply extends RBuiltinNode.Arg5 {

@Child private RapplyInternalNode rapply = RapplyInternalNode.create();

static {
Casts casts = new Casts(Rapply.class);
casts.arg("object").mustBe(RAbstractListVector.class, Message.GENERIC, "'object' must be a list");
casts.arg("f").mustBe(RFunction.class);
casts.arg("classes").mapNull(constant("ANY")).mapMissing(constant("ANY")).mustBe(stringValue()).asStringVector().findFirst().mustNotBeNA();
casts.arg("deflt").allowNull().mapMissing(nullConstant()).mustBe(anyValue());
casts.arg("how").mapNull(constant("unlist")).mapMissing(constant("unlist")).mustBe(stringValue()).asStringVector().findFirst().mustNotBeNA();
}

@Specialization(guards = "!isReplace(how)")
protected Object rapplyReplace(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how, @Cached("create()") UnaryCopyAttributesNode attri) {

return attri.execute(RDataFactory.createList((Object[]) rapply.execute(frame, object, f, classes, deflt, how)), object);
}

@Specialization(guards = "isReplace(how)")
protected Object rapply(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how) {

return rapply.execute(frame, object, f, classes, deflt, how);
}

protected static boolean isReplace(String how) {
return RapplyInternalNode.isReplace(how);
}

private static final class ExtractElementInternal extends RSourceSectionNode implements RSyntaxCall {

@Child private ExtractVectorNode extractElementNode = ExtractVectorNodeGen.create(ElementAccessMode.SUBSCRIPT, false);
private final FrameSlot vectorSlot;
private final FrameSlot indexSlot;

protected ExtractElementInternal(FrameSlot vectorSlot, FrameSlot indexSlot) {
super(RSyntaxNode.LAZY_DEPARSE);
this.vectorSlot = vectorSlot;
this.indexSlot = indexSlot;
}

@Override
public Object execute(VirtualFrame frame) {
RArguments.getCall(frame);
try {
return extractElementNode.apply(FrameSlotChangeMonitor.getObject(vectorSlot, frame), new Object[]{frame.getInt(indexSlot)}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE);
} catch (FrameSlotTypeException e) {
CompilerDirectives.transferToInterpreter();
throw RInternalError.shouldNotReachHere("frame type mismatch in rapply");
}
}

@Override
public RSyntaxElement getSyntaxLHS() {
return RSyntaxLookup.createDummyLookup(LAZY_DEPARSE, "list", true);
}

@Override
public ArgumentsSignature getSyntaxSignature() {
return ArgumentsSignature.empty(2);
}

@Override
public RSyntaxElement[] getSyntaxArguments() {
return new RSyntaxElement[]{RSyntaxLookup.createDummyLookup(LAZY_DEPARSE, "object", false), RSyntaxLookup.createDummyLookup(LAZY_DEPARSE, "i", false)};
}
}

public abstract static class RapplyInternalNode extends RBaseNode implements InternalRSyntaxNodeChildren {

@Child private InheritsNode inheritsNode = InheritsNodeGen.create();
@Child private RapplyInternalNode rapply;

protected static final String VECTOR_NAME = "object";
protected static final String INDEX_NAME = "i";

public abstract Object execute(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how);

protected static FrameSlot createIndexSlot(Frame frame) {
return FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), INDEX_NAME, FrameSlotKind.Int);
}

protected static FrameSlot createVectorSlot(Frame frame) {
return FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), VECTOR_NAME, FrameSlotKind.Object);
}

@Specialization(guards = "isReplace(how)")
protected RListBase cachedLapplyReplace(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how,
@Cached("createIndexSlot(frame)") FrameSlot indexSlot,
@Cached("createVectorSlot(frame)") FrameSlot vectorSlot,
@Cached("create()") RLengthNode lengthNode,
@Cached("createCountingProfile()") LoopConditionProfile loop,
@Cached("createCallNode(vectorSlot, indexSlot)") RCallBaseNode callNode) {

int length = lengthNode.executeInteger(object);
RListBase result = (RListBase) object.copy();
FrameSlotChangeMonitor.setObject(frame, vectorSlot, object);

if (length > 0) {
reportWork(this, length);
loop.profileCounted(length);
for (int i = 0; loop.inject(i < length); i++) {
frame.setInt(indexSlot, i + 1);
Object element = object.getDataAt(i);
if (element instanceof RAbstractListVector) {
result.setDataAt(i, getRapply().execute(frame, (RAbstractListVector) element, f, classes, deflt, how));
FrameSlotChangeMonitor.setObject(frame, vectorSlot, object);
} else if (isRNull(element)) {
result.setDataAt(i, element);
} else if (classes.equals("ANY") || inheritsNode.execute(element, RDataFactory.createStringVector(classes), false).equals(RRuntime.LOGICAL_TRUE)) {
result.setDataAt(i, callNode.execute(frame, f));
} else {
result.setDataAt(i, element);
}
}
}
return result;
}

private RapplyInternalNode getRapply() {
if (rapply == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
rapply = insert(RapplyInternalNodeGen.create());
}
return rapply;
}

@Specialization(guards = "!isReplace(how)")
protected Object[] cachedLapply(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how,
@Cached("createIndexSlot(frame)") FrameSlot indexSlot,
@Cached("createVectorSlot(frame)") FrameSlot vectorSlot,
@Cached("create()") RLengthNode lengthNode,
@Cached("create()") UnaryCopyAttributesNode attri,
@Cached("createCountingProfile()") LoopConditionProfile loop,
@Cached("createCallNode(vectorSlot, indexSlot)") RCallBaseNode callNode) {

int length = lengthNode.executeInteger(object);
Object[] result = new Object[length];
FrameSlotChangeMonitor.setObject(frame, vectorSlot, object);

if (length > 0) {
reportWork(this, length);
loop.profileCounted(length);
for (int i = 0; loop.inject(i < length); i++) {
frame.setInt(indexSlot, i + 1);
Object element = object.getDataAt(i);
if (element instanceof RAbstractListVector) {
RList newlist = RDataFactory.createList((Object[]) getRapply().execute(frame, (RAbstractListVector) element, f, classes, deflt, how));
attri.execute(newlist, (RAbstractListVector) element);
result[i] = newlist;
FrameSlotChangeMonitor.setObject(frame, vectorSlot, object);
} else if (isRNull(element)) {
result[i] = RDataFactory.createList();
} else if (classes.equals("ANY") || inheritsNode.execute(element, RDataFactory.createStringVector(classes), false).equals(RRuntime.LOGICAL_TRUE)) {
result[i] = callNode.execute(frame, f);
} else {
result[i] = deflt;
}
}
}
return result;
}

protected RCallBaseNode createCallNode(FrameSlot vectorSlot, FrameSlot indexSlot) {
CompilerAsserts.neverPartOfCompilation();

ExtractElementInternal element = new ExtractElementInternal(vectorSlot, indexSlot);
RSyntaxNode readArgs = ReadVariableNode.wrap(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any));
RNode function = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, "f", false).asRNode();

return RCallNode.createCall(createCallSourceSection(), function, ArgumentsSignature.get(null, "..."), element, readArgs);
}

protected static boolean isReplace(String how) {
return how.equals("replace");
}

public static RapplyInternalNode create() {
return RapplyInternalNodeGen.create();
}
}

public static Rapply create() {
return RapplyNodeGen.create();
}
}
Loading

0 comments on commit 3a3e6cf

Please sign in to comment.