Skip to content
Snippets Groups Projects
Commit 4a81767a authored by stepan's avatar stepan
Browse files

RFFI Fix: ATTRIB should return RList not DynamicObject

parent 08672289
No related branches found
No related tags found
No related merge requests found
......@@ -264,7 +264,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
@Override
public Object ATTRIB(Object obj) {
if (obj instanceof RAttributable) {
return ((RAttributable) obj).getAttributes();
return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.ATTRIB).call(obj);
}
return RNull.instance;
}
......
/*
* 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.ffi.impl.nodes;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.r.nodes.attributes.GetAttributesNode;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RError.Message;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.data.RAttributable;
import com.oracle.truffle.r.runtime.data.RNull;
public abstract class ATTRIB extends FFIUpCallNode.Arg1 {
@Child private GetAttributesNode getAttributesNode = GetAttributesNode.create();
@Specialization
public Object doAttributable(RAttributable obj) {
return getAttributesNode.execute(obj);
}
@Fallback
public RNull doOthers(Object obj) {
if (obj == RNull.instance || RRuntime.isForeignObject(obj)) {
return RNull.instance;
} else {
CompilerDirectives.transferToInterpreter();
String type = obj == null ? "null" : obj.getClass().getSimpleName();
throw RError.error(RError.NO_CALLER, Message.GENERIC, "object of type '" + type + "' cannot be attributed");
}
}
}
......@@ -90,6 +90,7 @@ public final class FFIUpCallRootNode extends RootNode {
}
public static void register() {
FFIUpCallRootNode.add(RFFIUpCallTable.ATTRIB, ATTRIBNodeGen::create);
FFIUpCallRootNode.add(RFFIUpCallTable.Rf_asReal, AsRealNodeGen::create);
FFIUpCallRootNode.add(RFFIUpCallTable.Rf_asLogical, AsLogicalNodeGen::create);
FFIUpCallRootNode.add(RFFIUpCallTable.Rf_asInteger, AsIntegerNodeGen::create);
......
......@@ -35,6 +35,7 @@ import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.r.nodes.attributes.GetAttributeNode;
import com.oracle.truffle.r.nodes.attributes.GetAttributesNode;
import com.oracle.truffle.r.nodes.attributes.IterableAttributeNode;
import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetRowNamesAttributeNode;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
......@@ -47,11 +48,9 @@ import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
import com.oracle.truffle.r.runtime.data.RAttributable;
import com.oracle.truffle.r.runtime.data.RAttributesLayout;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RMissing;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@RBuiltin(name = "attr", kind = PRIMITIVE, parameterNames = {"x", "which", "exact"}, behavior = PURE)
public abstract class Attr extends RBuiltinNode.Arg3 {
......@@ -124,7 +123,7 @@ public abstract class Attr extends RBuiltinNode.Arg3 {
if (attributes == null) {
return RNull.instance;
} else {
return getFullRowNames(getRowNamesNode.getRowNames(container));
return GetAttributesNode.getFullRowNames(getRowNamesNode.getRowNames(container));
}
}
......@@ -143,20 +142,6 @@ public abstract class Attr extends RBuiltinNode.Arg3 {
}
}
public static Object getFullRowNames(Object a) {
if (a == RNull.instance) {
return RNull.instance;
} else {
if (a instanceof RAbstractIntVector) {
RAbstractIntVector rowNames = (RAbstractIntVector) a;
if (rowNames.getLength() == 2 && RRuntime.isNA(rowNames.getDataAt(0))) {
return RDataFactory.createIntSequence(1, 1, Math.abs(rowNames.getDataAt(1)));
}
}
return a;
}
}
protected static boolean isRowNamesAttr(String name) {
return name.equals(RRuntime.ROWNAMES_ATTR_KEY);
}
......
......@@ -25,109 +25,44 @@ package com.oracle.truffle.r.nodes.builtin.base;
import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
import java.util.Arrays;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
import com.oracle.truffle.r.nodes.attributes.GetAttributesNode;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
import com.oracle.truffle.r.runtime.data.RAttributable;
import com.oracle.truffle.r.runtime.data.RAttributesLayout;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RLanguage;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
import com.oracle.truffle.r.runtime.env.REnvironment;
@RBuiltin(name = "attributes", kind = PRIMITIVE, parameterNames = {"obj"}, behavior = PURE)
public abstract class Attributes extends RBuiltinNode.Arg1 {
private final BranchProfile rownamesBranch = BranchProfile.create();
@Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
@Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
@Child private GetAttributesNode getAttributesNode = GetAttributesNode.create();
static {
Casts.noCasts(Attributes.class);
}
@Specialization
protected Object attributesNull(RAbstractContainer container,
@Cached("createBinaryProfile()") ConditionProfile hasAttributesProfile) {
if (hasAttributesProfile.profile(hasAttributes(container))) {
return createResult(container, container instanceof RLanguage);
} else {
return RNull.instance;
}
protected Object attributesNull(RAbstractContainer container) {
return getAttributesNode.execute(container);
}
/**
* Unusual cases that it is not worth specializing on as they are not performance-centric,
* basically any type that is not an {@link RAbstractContainer} but is {@link RAttributable},
* e.g. {@link REnvironment}.
* Unusual cases that it is not worth specializing on as they are not performance-centric.
*/
@Fallback
@TruffleBoundary
protected Object attributes(Object object) {
if (object instanceof RAttributable) {
if (!hasAttributes((RAttributable) object)) {
return RNull.instance;
} else {
return createResult((RAttributable) object, false);
}
return getAttributesNode.execute((RAttributable) object);
} else if (object == RNull.instance || RRuntime.isForeignObject(object)) {
return RNull.instance;
} else {
throw RError.nyi(this, "object cannot be attributed");
}
}
/**
* {@code language} objects behave differently regarding "names"; they don't get included.
*/
private Object createResult(RAttributable attributable, boolean ignoreNames) {
DynamicObject attributes = attributable.getAttributes();
int size = attributes.size();
String[] names = new String[size];
Object[] values = new Object[size];
int z = 0;
for (RAttributesLayout.RAttribute attr : arrayAttrAccess.execute(attributes)) {
String name = attr.getName();
if (ignoreNames && name.equals(RRuntime.NAMES_ATTR_KEY)) {
continue;
}
names[z] = name;
if (name.equals(RRuntime.ROWNAMES_ATTR_KEY)) {
rownamesBranch.enter();
values[z] = Attr.getFullRowNames(attr.getValue());
} else {
values[z] = attr.getValue();
}
z++;
}
if (ignoreNames && z != names.length) {
if (z == 0) {
return RNull.instance;
} else {
names = Arrays.copyOfRange(names, 0, names.length - 1);
values = Arrays.copyOfRange(values, 0, values.length - 1);
}
}
RList result = RDataFactory.createList(values);
setNamesNode.setNames(result, RDataFactory.createStringVector(names, true));
return result;
}
private static boolean hasAttributes(RAttributable attributable) {
return attributable.getAttributes() != null && !attributable.getAttributes().isEmpty();
}
}
/*
* 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.nodes.attributes;
import java.util.Arrays;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.data.RAttributable;
import com.oracle.truffle.r.runtime.data.RAttributesLayout;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RLanguage;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
import com.oracle.truffle.r.runtime.env.REnvironment;
import com.oracle.truffle.r.runtime.nodes.RBaseNode;
/**
* Transforms the attributes from {@link DynamicObject} into {@link RList}.
*/
public abstract class GetAttributesNode extends RBaseNode {
private final BranchProfile rownamesBranch = BranchProfile.create();
@Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
@Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
public static GetAttributesNode create() {
return GetAttributesNodeGen.create();
}
public abstract Object execute(RAttributable attributable);
@Specialization
protected Object attributesNull(RAbstractContainer container,
@Cached("createBinaryProfile()") ConditionProfile hasAttributesProfile) {
if (hasAttributesProfile.profile(hasAttributes(container))) {
return createResult(container, container instanceof RLanguage);
} else {
return RNull.instance;
}
}
/**
* Unusual cases that it is not worth specializing on as they are not performance-centric,
* basically any type that is not an {@link RAbstractContainer} but is {@link RAttributable},
* e.g. {@link REnvironment}.
*/
@Fallback
@TruffleBoundary
protected Object attributes(RAttributable object) {
if (hasAttributes(object)) {
return createResult(object, false);
} else {
return RNull.instance;
}
}
public static Object getFullRowNames(Object a) {
if (a == RNull.instance) {
return RNull.instance;
} else {
if (a instanceof RAbstractIntVector) {
RAbstractIntVector rowNames = (RAbstractIntVector) a;
if (rowNames.getLength() == 2 && RRuntime.isNA(rowNames.getDataAt(0))) {
return RDataFactory.createIntSequence(1, 1, Math.abs(rowNames.getDataAt(1)));
}
}
return a;
}
}
/**
* {@code language} objects behave differently regarding "names"; they don't get included.
*/
private Object createResult(RAttributable attributable, boolean ignoreNames) {
DynamicObject attributes = attributable.getAttributes();
int size = attributes.size();
String[] names = new String[size];
Object[] values = new Object[size];
int z = 0;
for (RAttributesLayout.RAttribute attr : arrayAttrAccess.execute(attributes)) {
String name = attr.getName();
if (ignoreNames && name.equals(RRuntime.NAMES_ATTR_KEY)) {
continue;
}
names[z] = name;
if (name.equals(RRuntime.ROWNAMES_ATTR_KEY)) {
rownamesBranch.enter();
values[z] = getFullRowNames(attr.getValue());
} else {
values[z] = attr.getValue();
}
z++;
}
if (ignoreNames && z != names.length) {
if (z == 0) {
return RNull.instance;
} else {
names = Arrays.copyOfRange(names, 0, names.length - 1);
values = Arrays.copyOfRange(values, 0, values.length - 1);
}
}
RList result = RDataFactory.createList(values);
setNamesNode.setNames(result, RDataFactory.createStringVector(names, true));
return result;
}
private static boolean hasAttributes(RAttributable attributable) {
return attributable.getAttributes() != null && !attributable.getAttributes().isEmpty();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment