Skip to content
Snippets Groups Projects
Commit 4afad71f authored by Adam Welc's avatar Adam Welc
Browse files

Added partial support for primitive methods.

parent e41b9d96
No related branches found
No related tags found
No related merge requests found
......@@ -28,6 +28,8 @@ import com.oracle.truffle.r.nodes.objects.ExecuteMethod;
import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen;
import com.oracle.truffle.r.runtime.ArgumentsSignature;
import com.oracle.truffle.r.runtime.PrimitiveMethodsInfo;
import com.oracle.truffle.r.runtime.PrimitiveMethodsInfo.MethodCode;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.RRuntime;
......@@ -41,6 +43,7 @@ import com.oracle.truffle.r.runtime.data.RLanguage;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.RPromise;
import com.oracle.truffle.r.runtime.data.RS4Object;
import com.oracle.truffle.r.runtime.data.RTypedValue;
import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
......@@ -136,28 +139,76 @@ public class MethodsListDispatch {
@Specialization
@TruffleBoundary
protected byte setPrimitiveMethods(Object fname, Object op, Object codeVec, @SuppressWarnings("unused") Object fundef, @SuppressWarnings("unused") Object mlist) {
@SuppressWarnings("unused")
protected Object setPrimitiveMethods(Object fname, Object op, Object codeVec, RTypedValue fundef, Object mlist) {
String fnameString = RRuntime.asString(fname);
String codeVecString = RRuntime.asString(codeVec);
if (codeVecString == null) {
throw RError.error(this, RError.Message.GENERIC, "argument 'code' must be a character string");
}
// TODO: implement proper primitive method setting
if (op == RNull.instance) {
@SuppressWarnings("unused")
byte value = RRuntime.asLogical(RContext.getInstance().allowPrimitiveMethods());
if (codeVecString.length() > 0) {
if (codeVecString.charAt(0) == 'C') {
if (codeVecString.charAt(0) == 'c' || codeVecString.charAt(0) == 'C') {
RContext.getInstance().setAllowPrimitiveMethods(false);
} else if (codeVecString.charAt(0) == 'S') {
} else if (codeVecString.charAt(0) == 's' || codeVecString.charAt(0) == 'S') {
RContext.getInstance().setAllowPrimitiveMethods(true);
}
}
return RRuntime.LOGICAL_FALSE; // value;
return value;
}
setPrimitiveMethodsInternal(op, codeVecString, fundef, mlist);
return fnameString;
}
private static void setPrimitiveMethodsInternal(Object op, String codeVec, RTypedValue fundef, Object mlist) {
MethodCode code;
if (codeVec.charAt(0) == 'c') {
code = MethodCode.NO_METHODS;
}
else if (codeVec.charAt(0) == 'r') {
code = MethodCode.NEEDS_RESET;
}
else if (codeVec.startsWith("se")) {
code = MethodCode.HAS_METHODS;
}
else if (codeVec.startsWith("su")) {
code = MethodCode.SUPPRESSED;
}
else {
throw RError.error(RError.NO_NODE, RError.Message.INVALID_PRIM_METHOD_CODE, codeVec);
}
if (!(op instanceof RFunction) || !((RFunction) op).isBuiltin()) {
throw RError.error(RError.NO_NODE, RError.Message.GENERIC, "invalid object: must be a primitive function");
}
int primMethodIndex = ((RFunction) op).getRBuiltin().getPrimMethodIndex();
assert primMethodIndex != PrimitiveMethodsInfo.INVALID_INDEX;
PrimitiveMethodsInfo primMethodsInfo = RContext.getInstance().getPrimitiveMethodsInfo();
if (primMethodIndex >= primMethodsInfo.getSize()) {
primMethodsInfo = primMethodsInfo.resize(primMethodIndex + 1);
}
primMethodsInfo.setPrimMethodCode(primMethodIndex, code);
RFunction value = primMethodsInfo.getPrimGeneric(primMethodIndex);
if (code != MethodCode.SUPPRESSED) {
assert fundef != null; // explicitly checked in GNU R
if (code == MethodCode.NO_METHODS && value != null) {
primMethodsInfo.setPrimGeneric(primMethodIndex, null);
primMethodsInfo.setPrimMethodList(primMethodIndex, null);
} else if (fundef != RNull.instance && value == null) {
if (!(fundef instanceof RFunction)) {
throw RError.error(RError.NO_NODE, RError.Message.PRIM_GENERIC_NOT_FUNCTION, fundef.getRType().getName());
}
primMethodsInfo.setPrimGeneric(primMethodIndex, (RFunction) fundef);
}
}
if (code == MethodCode.HAS_METHODS) {
assert mlist != null; // explicitly checked in GNU R
if (mlist != RNull.instance) {
primMethodsInfo.setPrimMethodList(primMethodIndex, (REnvironment) mlist);
}
}
return RRuntime.LOGICAL_FALSE;
// throw RInternalError.unimplemented();
}
}
......
/*
* This material is distributed under the GNU General Public License
* Version 2. You may review the terms of this license at
* http://www.gnu.org/licenses/gpl-2.0.html
*
* Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka
* Copyright (c) 1995-2014, The R Core Team
* Copyright (c) 2002-2008, The R Foundation
* Copyright (c) 2016, Oracle and/or its affiliates
*
* All rights reserved.
*/
package com.oracle.truffle.r.runtime;
import java.util.Arrays;
import com.oracle.truffle.r.runtime.data.RFunction;
import com.oracle.truffle.r.runtime.env.REnvironment;
public class PrimitiveMethodsInfo {
public static final int INVALID_INDEX = -1;
public enum MethodCode {
NO_METHODS,
NEEDS_RESET,
HAS_METHODS,
SUPPRESSED
}
private MethodCode[] primMethodCodes;
private RFunction[] primGenerics;
private REnvironment[] primMethodsList;
public PrimitiveMethodsInfo() {
// start with length 0 is it's not filled consecutively anyway
this(new MethodCode[0], new RFunction[0], new REnvironment[0]);
}
private PrimitiveMethodsInfo(MethodCode[] primMethodCodes, RFunction[] primGenerics, REnvironment[] primMethodList) {
this.primMethodCodes = primMethodCodes;
this.primGenerics = primGenerics;
this.primMethodsList = primMethodList;
}
public MethodCode getPrimMethodCode(int index) {
return primMethodCodes[index];
}
public void setPrimMethodCode(int index, MethodCode code) {
primMethodCodes[index] = code;
}
public RFunction getPrimGeneric(int index) {
return primGenerics[index];
}
public void setPrimGeneric(int index, RFunction generic) {
primGenerics[index] = generic;
}
public REnvironment getPrimMethodList(int index) {
return primMethodsList[index];
}
public void setPrimMethodList(int index, REnvironment methodsList) {
primMethodsList[index] = methodsList;
}
public int getSize() {
return primMethodCodes.length;
}
public PrimitiveMethodsInfo resize(int size) {
assert size >= getSize();
primMethodCodes = Arrays.copyOf(primMethodCodes, size);
primGenerics = Arrays.copyOf(primGenerics, size);
primMethodsList = Arrays.copyOf(primMethodsList, size);
return this;
}
public PrimitiveMethodsInfo duplicate() {
return new PrimitiveMethodsInfo(Arrays.copyOf(primMethodCodes, getSize()), Arrays.copyOf(primGenerics, getSize()), Arrays.copyOf(primMethodsList, getSize()));
}
}
......@@ -656,7 +656,9 @@ public final class RError extends RuntimeException {
NON_EMPTY_STRING("'%s' must be a non-empty string; got an empty string"),
SINGLE_STRING_WRONG_TYPE("'%s' must be a single string (got an object of class \"%s\")"),
NO_GENERIC_FUN("no generic function definition found for '%s'"),
NO_GENERIC_FUN_IN_ENV("no generic function definition found for '%s' in the supplied environment");
NO_GENERIC_FUN_IN_ENV("no generic function definition found for '%s' in the supplied environment"),
INVALID_PRIM_METHOD_CODE("invalid primitive methods code (\"%s\"): should be \"clear\", \"reset\", \"set\", or \"suppress\""),
PRIM_GENERIC_NOT_FUNCTION("the formal definition of a primitive generic must be a function object (got type '%s')");
public final String message;
final boolean hasArgs;
......
......@@ -40,6 +40,7 @@ import com.oracle.truffle.api.nodes.InvalidAssumptionException;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.vm.PolyglotEngine;
import com.oracle.truffle.r.runtime.LazyDBCache;
import com.oracle.truffle.r.runtime.PrimitiveMethodsInfo;
import com.oracle.truffle.r.runtime.RBuiltinKind;
import com.oracle.truffle.r.runtime.RBuiltinLookup;
import com.oracle.truffle.r.runtime.RCmdOptions;
......@@ -290,6 +291,8 @@ public final class RContext extends ExecutionContext implements TruffleObject {
private boolean active;
private PrimitiveMethodsInfo primitiveMethodsInfo;
/**
* A (hopefully) temporary workaround to ignore the setting of {@link #resultVisible} for
* benchmarks. Set across all contexts.
......@@ -378,6 +381,20 @@ public final class RContext extends ExecutionContext implements TruffleObject {
this.info = initialInfo;
}
// this must happen before engine activation in the code below
if (info.getKind() == ContextKind.SHARE_NOTHING) {
if (info.getParent() == null) {
this.primitiveMethodsInfo = new PrimitiveMethodsInfo();
} else {
// share nothing contexts need their own copy of the primitive methods meta-data as
// they can run (and update this meta data) concurrently with the parent;
// alternative would be to copy on-write but we would need some kind of locking
// machinery to avoid races
assert info.getParent().getPrimitiveMethodsInfo() != null;
this.primitiveMethodsInfo = info.getParent().getPrimitiveMethodsInfo().duplicate();
}
}
this.env = env;
if (info.getConsoleHandler() == null) {
throw Utils.fail("no console handler set");
......@@ -551,6 +568,19 @@ public final class RContext extends ExecutionContext implements TruffleObject {
s4ExtendsTable.put(key, value);
}
public PrimitiveMethodsInfo getPrimitiveMethodsInfo() {
if (primitiveMethodsInfo == null) {
// shared contexts do not run concurrently with their parent and re-use primitive
// methods information
assert info.getKind() != ContextKind.SHARE_NOTHING;
assert info.getParent() != null;
return info.getParent().getPrimitiveMethodsInfo();
}
else {
return primitiveMethodsInfo;
}
}
public boolean isInteractive() {
return info.getConsoleHandler().isInteractive();
}
......
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2016, 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
......@@ -26,8 +26,12 @@ import java.util.*;
import com.oracle.truffle.api.CompilerDirectives.*;
import com.oracle.truffle.r.runtime.*;
import com.oracle.truffle.r.runtime.context.RContext;
public abstract class RBuiltinDescriptor {
private static int primitiveMethodCount;
private final String name;
private final String[] aliases;
private final RBuiltinKind kind;
......@@ -37,6 +41,7 @@ public abstract class RBuiltinDescriptor {
private final boolean alwaysSplit;
private final RDispatch dispatch;
private final RGroupGenerics group;
private final int primitiveMethodIndex;
@CompilationFinal private final boolean[] evaluatesArgument;
public RBuiltinDescriptor(String name, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature, int[] nonEvalArgs, boolean splitCaller, boolean alwaysSplit, RDispatch dispatch) {
......@@ -56,6 +61,16 @@ public abstract class RBuiltinDescriptor {
assert evaluatesArgument[index] : "duplicate nonEvalArgs entry " + index + " in " + this;
evaluatesArgument[index] = false;
}
if (kind == RBuiltinKind.PRIMITIVE) {
// TODO: assert that static count is only incremented in the primordial context (it's
// currently tough to do as builtin descriptors seem to be created before the primordial
// context is fully initialized but code inspection shows that the assertion holds)
primitiveMethodIndex = primitiveMethodCount++;
}
else {
primitiveMethodIndex = PrimitiveMethodsInfo.INVALID_INDEX;
}
}
public String getName() {
......@@ -97,4 +112,8 @@ public abstract class RBuiltinDescriptor {
public boolean evaluatesArg(int index) {
return evaluatesArgument[index];
}
public int getPrimMethodIndex() {
return primitiveMethodIndex;
}
}
......@@ -206,6 +206,7 @@ com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mm/MarsagliaMu
com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java,hiroshima.copyright
com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java,gnu_r.copyright
com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java,gnu_r.copyright
com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java,gnu_r_gentleman_ihaka.copyright
com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java,gnu_r.copyright
com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java,gnu_r.copyright
com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java,gnu_r.copyright
......
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