Skip to content

Commit 3a3e6cf

Browse files
committed
Merge commit '30eb913081cb57319d554f83681e206cf5409a0c' into release/graal-vm/1.0
2 parents 78d84e9 + 30eb913 commit 3a3e6cf

File tree

24 files changed

+799
-33
lines changed

24 files changed

+799
-33
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
# 1.0 RC 9
2+
3+
New features
4+
5+
* various improvements in handling of foreign objects in R
6+
7+
Added missing R builtins and C API
8+
9+
* eapply builtin
10+
* rapply builtin
11+
12+
Bug fixes:
13+
14+
* colon builtin calculated length incorrectly in some circumstances
15+
* `storage.mode<-` works with NULL
16+
* Rf_coerceVector works with pairlists and language objects
17+
* allow formal parameter names: '..1', '..1=default', '...=default'
18+
119
# 1.0 RC 8
220

321
Bug fixes

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceNodes.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,36 @@ protected Object convert(RAbstractVector v) {
106106
return current;
107107
}
108108

109+
@Specialization
110+
protected Object convert(RNull x) {
111+
if (type == SEXPTYPE.LISTSXP) {
112+
return x;
113+
} else {
114+
return doFallback(x);
115+
}
116+
}
117+
118+
@Specialization
119+
protected Object convert(RPairList list) {
120+
if (list.isLanguage() || type == SEXPTYPE.LISTSXP) {
121+
return list;
122+
} else {
123+
return doFallback(list);
124+
}
125+
}
126+
127+
@Fallback
128+
@TruffleBoundary
129+
protected Object doFallback(Object x) {
130+
throw error(Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, Utils.getTypeName(x), "coercePairList");
131+
}
132+
109133
private static void adjustSharing(RAbstractVector origin, Object element) {
110134
if (origin instanceof RShareable) {
111135
int v = getSharingLevel((RShareable) origin);
112136
if (element instanceof RShareable) {
113137
RShareable r = (RShareable) element;
114-
if (v == 2) {
138+
if (v >= 2) {
115139
// we play it safe: if the caller wants this instance to be shared, they may
116140
// expect it to never become non-shared again, which could happen in FastR
117141
r.makeSharedPermanent();

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@
165165
import com.oracle.truffle.r.nodes.unary.UnaryArithmeticSpecial;
166166
import com.oracle.truffle.r.nodes.unary.UnaryNotNode;
167167
import com.oracle.truffle.r.nodes.unary.UnaryNotNodeGen;
168+
import com.oracle.truffle.r.runtime.RInternalError;
168169
import com.oracle.truffle.r.runtime.RVisibility;
169170
import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
170171
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -628,6 +629,7 @@ public BasePackage() {
628629
add(LaFunctions.LaLibrary.class, LaFunctionsFactory.LaLibraryNodeGen::create);
629630
add(LaFunctions.Backsolve.class, LaFunctionsFactory.BacksolveNodeGen::create);
630631
add(Lapply.class, LapplyNodeGen::create);
632+
add(Rapply.class, RapplyNodeGen::create);
631633
add(Length.class, LengthNodeGen::create);
632634
add(Lengths.class, LengthsNodeGen::create);
633635
add(License.class, LicenseNodeGen::create);
@@ -854,6 +856,10 @@ private void addBinaryCompare(Class<?> builtinClass, BooleanOperationFactory fac
854856

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

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ public abstract static class IsNumeric extends RBuiltinNode.Arg1 {
429429
createCasts(IsNumeric.class);
430430
}
431431

432-
@Child private InheritsCheckNode inheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR);
432+
@Child private InheritsCheckNode inheritsCheck = InheritsCheckNode.create(RRuntime.CLASS_FACTOR);
433433

434434
protected boolean isFactor(Object o) {
435435
return inheritsCheck.execute(o);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ private static NewNames updateNewNames(RAbstractStringVector names, VectorReuse
117117
NewNames nn = newNames;
118118
if (nn == null) {
119119
RAbstractStringVector res = reuse.getResult(names);
120-
VectorAccess access = reuse.access(res);
120+
VectorAccess access = res.slowPathAccess();
121121
VectorAccess.RandomIterator iter = access.randomAccess(res);
122122
nn = new NewNames(res, access, iter);
123123
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ protected RIntVector match(RAbstractVector x, RNull table, int nomatch, Object i
110110
return RDataFactory.createIntVector(data, na.profile(!RRuntime.isNA(nomatch)));
111111
}
112112

113-
@Child private InheritsCheckNode factorInheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR);
113+
@Child private InheritsCheckNode factorInheritsCheck = InheritsCheckNode.create(RRuntime.CLASS_FACTOR);
114114

115115
protected boolean isFactor(Object o) {
116116
return factorInheritsCheck.execute(o);
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
/*
2+
* Copyright (c) 1995-2015, The R Core Team
3+
* Copyright (c) 2016, 2018, Oracle and/or its affiliates
4+
*
5+
* This program is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation; either version 2 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program; if not, a copy is available at
17+
* https://www.R-project.org/Licenses/
18+
*/
19+
package com.oracle.truffle.r.nodes.builtin.base;
20+
21+
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue;
22+
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
23+
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant;
24+
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
25+
import static com.oracle.truffle.r.nodes.builtin.base.Lapply.createCallSourceSection;
26+
import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
27+
import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
28+
29+
import com.oracle.truffle.api.CompilerAsserts;
30+
import com.oracle.truffle.api.CompilerDirectives;
31+
import com.oracle.truffle.api.dsl.Cached;
32+
import com.oracle.truffle.api.dsl.Specialization;
33+
import com.oracle.truffle.api.frame.Frame;
34+
import com.oracle.truffle.api.frame.FrameSlot;
35+
import com.oracle.truffle.api.frame.FrameSlotKind;
36+
import com.oracle.truffle.api.frame.FrameSlotTypeException;
37+
import com.oracle.truffle.api.frame.VirtualFrame;
38+
import com.oracle.truffle.api.profiles.LoopConditionProfile;
39+
import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
40+
import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
41+
import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
42+
import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNodeGen;
43+
import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
44+
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
45+
import com.oracle.truffle.r.nodes.builtin.base.RapplyNodeGen.RapplyInternalNodeGen;
46+
import com.oracle.truffle.r.nodes.control.RLengthNode;
47+
import com.oracle.truffle.r.nodes.function.RCallBaseNode;
48+
import com.oracle.truffle.r.nodes.function.RCallNode;
49+
import com.oracle.truffle.r.nodes.unary.InheritsNode;
50+
import com.oracle.truffle.r.nodes.unary.InheritsNodeGen;
51+
import com.oracle.truffle.r.runtime.ArgumentsSignature;
52+
import com.oracle.truffle.r.runtime.RArguments;
53+
import com.oracle.truffle.r.runtime.RError.Message;
54+
import com.oracle.truffle.r.runtime.RInternalError;
55+
import com.oracle.truffle.r.runtime.RRuntime;
56+
import com.oracle.truffle.r.runtime.RType;
57+
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
58+
import com.oracle.truffle.r.runtime.context.RContext;
59+
import com.oracle.truffle.r.runtime.data.RDataFactory;
60+
import com.oracle.truffle.r.runtime.data.RFunction;
61+
import com.oracle.truffle.r.runtime.data.RList;
62+
import com.oracle.truffle.r.runtime.data.RListBase;
63+
import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
64+
import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
65+
import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
66+
import com.oracle.truffle.r.runtime.nodes.RBaseNode;
67+
import com.oracle.truffle.r.runtime.nodes.RNode;
68+
import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode;
69+
import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
70+
import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
71+
import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
72+
import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
73+
74+
@RBuiltin(name = "rapply", kind = INTERNAL, parameterNames = {"object", "f", "classes", "deflt", "how"}, splitCaller = true, behavior = COMPLEX)
75+
public abstract class Rapply extends RBuiltinNode.Arg5 {
76+
77+
@Child private RapplyInternalNode rapply = RapplyInternalNode.create();
78+
79+
static {
80+
Casts casts = new Casts(Rapply.class);
81+
casts.arg("object").mustBe(RAbstractListVector.class, Message.GENERIC, "'object' must be a list");
82+
casts.arg("f").mustBe(RFunction.class);
83+
casts.arg("classes").mapNull(constant("ANY")).mapMissing(constant("ANY")).mustBe(stringValue()).asStringVector().findFirst().mustNotBeNA();
84+
casts.arg("deflt").allowNull().mapMissing(nullConstant()).mustBe(anyValue());
85+
casts.arg("how").mapNull(constant("unlist")).mapMissing(constant("unlist")).mustBe(stringValue()).asStringVector().findFirst().mustNotBeNA();
86+
}
87+
88+
@Specialization(guards = "!isReplace(how)")
89+
protected Object rapplyReplace(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how, @Cached("create()") UnaryCopyAttributesNode attri) {
90+
91+
return attri.execute(RDataFactory.createList((Object[]) rapply.execute(frame, object, f, classes, deflt, how)), object);
92+
}
93+
94+
@Specialization(guards = "isReplace(how)")
95+
protected Object rapply(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how) {
96+
97+
return rapply.execute(frame, object, f, classes, deflt, how);
98+
}
99+
100+
protected static boolean isReplace(String how) {
101+
return RapplyInternalNode.isReplace(how);
102+
}
103+
104+
private static final class ExtractElementInternal extends RSourceSectionNode implements RSyntaxCall {
105+
106+
@Child private ExtractVectorNode extractElementNode = ExtractVectorNodeGen.create(ElementAccessMode.SUBSCRIPT, false);
107+
private final FrameSlot vectorSlot;
108+
private final FrameSlot indexSlot;
109+
110+
protected ExtractElementInternal(FrameSlot vectorSlot, FrameSlot indexSlot) {
111+
super(RSyntaxNode.LAZY_DEPARSE);
112+
this.vectorSlot = vectorSlot;
113+
this.indexSlot = indexSlot;
114+
}
115+
116+
@Override
117+
public Object execute(VirtualFrame frame) {
118+
RArguments.getCall(frame);
119+
try {
120+
return extractElementNode.apply(FrameSlotChangeMonitor.getObject(vectorSlot, frame), new Object[]{frame.getInt(indexSlot)}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE);
121+
} catch (FrameSlotTypeException e) {
122+
CompilerDirectives.transferToInterpreter();
123+
throw RInternalError.shouldNotReachHere("frame type mismatch in rapply");
124+
}
125+
}
126+
127+
@Override
128+
public RSyntaxElement getSyntaxLHS() {
129+
return RSyntaxLookup.createDummyLookup(LAZY_DEPARSE, "list", true);
130+
}
131+
132+
@Override
133+
public ArgumentsSignature getSyntaxSignature() {
134+
return ArgumentsSignature.empty(2);
135+
}
136+
137+
@Override
138+
public RSyntaxElement[] getSyntaxArguments() {
139+
return new RSyntaxElement[]{RSyntaxLookup.createDummyLookup(LAZY_DEPARSE, "object", false), RSyntaxLookup.createDummyLookup(LAZY_DEPARSE, "i", false)};
140+
}
141+
}
142+
143+
public abstract static class RapplyInternalNode extends RBaseNode implements InternalRSyntaxNodeChildren {
144+
145+
@Child private InheritsNode inheritsNode = InheritsNodeGen.create();
146+
@Child private RapplyInternalNode rapply;
147+
148+
protected static final String VECTOR_NAME = "object";
149+
protected static final String INDEX_NAME = "i";
150+
151+
public abstract Object execute(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how);
152+
153+
protected static FrameSlot createIndexSlot(Frame frame) {
154+
return FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), INDEX_NAME, FrameSlotKind.Int);
155+
}
156+
157+
protected static FrameSlot createVectorSlot(Frame frame) {
158+
return FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), VECTOR_NAME, FrameSlotKind.Object);
159+
}
160+
161+
@Specialization(guards = "isReplace(how)")
162+
protected RListBase cachedLapplyReplace(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how,
163+
@Cached("createIndexSlot(frame)") FrameSlot indexSlot,
164+
@Cached("createVectorSlot(frame)") FrameSlot vectorSlot,
165+
@Cached("create()") RLengthNode lengthNode,
166+
@Cached("createCountingProfile()") LoopConditionProfile loop,
167+
@Cached("createCallNode(vectorSlot, indexSlot)") RCallBaseNode callNode) {
168+
169+
int length = lengthNode.executeInteger(object);
170+
RListBase result = (RListBase) object.copy();
171+
FrameSlotChangeMonitor.setObject(frame, vectorSlot, object);
172+
173+
if (length > 0) {
174+
reportWork(this, length);
175+
loop.profileCounted(length);
176+
for (int i = 0; loop.inject(i < length); i++) {
177+
frame.setInt(indexSlot, i + 1);
178+
Object element = object.getDataAt(i);
179+
if (element instanceof RAbstractListVector) {
180+
result.setDataAt(i, getRapply().execute(frame, (RAbstractListVector) element, f, classes, deflt, how));
181+
FrameSlotChangeMonitor.setObject(frame, vectorSlot, object);
182+
} else if (isRNull(element)) {
183+
result.setDataAt(i, element);
184+
} else if (classes.equals("ANY") || inheritsNode.execute(element, RDataFactory.createStringVector(classes), false).equals(RRuntime.LOGICAL_TRUE)) {
185+
result.setDataAt(i, callNode.execute(frame, f));
186+
} else {
187+
result.setDataAt(i, element);
188+
}
189+
}
190+
}
191+
return result;
192+
}
193+
194+
private RapplyInternalNode getRapply() {
195+
if (rapply == null) {
196+
CompilerDirectives.transferToInterpreterAndInvalidate();
197+
rapply = insert(RapplyInternalNodeGen.create());
198+
}
199+
return rapply;
200+
}
201+
202+
@Specialization(guards = "!isReplace(how)")
203+
protected Object[] cachedLapply(VirtualFrame frame, RAbstractListVector object, RFunction f, String classes, Object deflt, String how,
204+
@Cached("createIndexSlot(frame)") FrameSlot indexSlot,
205+
@Cached("createVectorSlot(frame)") FrameSlot vectorSlot,
206+
@Cached("create()") RLengthNode lengthNode,
207+
@Cached("create()") UnaryCopyAttributesNode attri,
208+
@Cached("createCountingProfile()") LoopConditionProfile loop,
209+
@Cached("createCallNode(vectorSlot, indexSlot)") RCallBaseNode callNode) {
210+
211+
int length = lengthNode.executeInteger(object);
212+
Object[] result = new Object[length];
213+
FrameSlotChangeMonitor.setObject(frame, vectorSlot, object);
214+
215+
if (length > 0) {
216+
reportWork(this, length);
217+
loop.profileCounted(length);
218+
for (int i = 0; loop.inject(i < length); i++) {
219+
frame.setInt(indexSlot, i + 1);
220+
Object element = object.getDataAt(i);
221+
if (element instanceof RAbstractListVector) {
222+
RList newlist = RDataFactory.createList((Object[]) getRapply().execute(frame, (RAbstractListVector) element, f, classes, deflt, how));
223+
attri.execute(newlist, (RAbstractListVector) element);
224+
result[i] = newlist;
225+
FrameSlotChangeMonitor.setObject(frame, vectorSlot, object);
226+
} else if (isRNull(element)) {
227+
result[i] = RDataFactory.createList();
228+
} else if (classes.equals("ANY") || inheritsNode.execute(element, RDataFactory.createStringVector(classes), false).equals(RRuntime.LOGICAL_TRUE)) {
229+
result[i] = callNode.execute(frame, f);
230+
} else {
231+
result[i] = deflt;
232+
}
233+
}
234+
}
235+
return result;
236+
}
237+
238+
protected RCallBaseNode createCallNode(FrameSlot vectorSlot, FrameSlot indexSlot) {
239+
CompilerAsserts.neverPartOfCompilation();
240+
241+
ExtractElementInternal element = new ExtractElementInternal(vectorSlot, indexSlot);
242+
RSyntaxNode readArgs = ReadVariableNode.wrap(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any));
243+
RNode function = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, "f", false).asRNode();
244+
245+
return RCallNode.createCall(createCallSourceSection(), function, ArgumentsSignature.get(null, "..."), element, readArgs);
246+
}
247+
248+
protected static boolean isReplace(String how) {
249+
return how.equals("replace");
250+
}
251+
252+
public static RapplyInternalNode create() {
253+
return RapplyInternalNodeGen.create();
254+
}
255+
}
256+
257+
public static Rapply create() {
258+
return RapplyNodeGen.create();
259+
}
260+
}

0 commit comments

Comments
 (0)