From 76a5e7bfaf2fd94c551e7a53f63cd230e2bb9292 Mon Sep 17 00:00:00 2001 From: Lukas Stadler <lukas.stadler@oracle.com> Date: Wed, 15 Nov 2017 17:03:44 +0100 Subject: [PATCH] convert ToString node to VectorAccess --- .../truffle/r/nodes/builtin/base/Cat.java | 4 +- .../r/nodes/unary/CastStringBaseNode.java | 2 +- .../truffle/r/nodes/unary/CastSymbolNode.java | 2 +- .../truffle/r/nodes/unary/ToStringNode.java | 187 +++++++----------- 4 files changed, 79 insertions(+), 116 deletions(-) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java index a4b42e74a1..cee07fbd4b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java @@ -141,11 +141,11 @@ public abstract class Cat extends RBuiltinNode.Arg6 { } else { validateType(i + 1, obj); for (int j = 0; j < objVec.getLength(); j++) { - stringVecs.add(toString.executeString(objVec.getDataAtAsObject(j), false, "")); + stringVecs.add(toString.executeString(objVec.getDataAtAsObject(j), "")); } } } else { - stringVecs.add(toString.executeString(obj, false, "")); + stringVecs.add(toString.executeString(obj, "")); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java index 8d3a0456e3..aca07494f8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java @@ -52,7 +52,7 @@ public abstract class CastStringBaseNode extends CastBaseNode { } protected String toString(Object value) { - return toString.executeString(value, false, ToStringNode.DEFAULT_SEPARATOR); + return toString.executeString(value, ToStringNode.DEFAULT_SEPARATOR); } @Specialization diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java index 2b45b6639a..034b53109f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java @@ -58,7 +58,7 @@ public abstract class CastSymbolNode extends CastBaseNode { public abstract Object executeSymbol(Object o); private String toString(Object value) { - return toString.executeString(value, true, ToStringNode.DEFAULT_SEPARATOR); + return toString.executeString(value, ToStringNode.DEFAULT_SEPARATOR); } @Specialization diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java index c28ada80ed..1aeae5ca87 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java @@ -22,7 +22,8 @@ */ package com.oracle.truffle.r.nodes.unary; -import com.oracle.truffle.api.CompilerAsserts; +import java.util.EnumMap; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; @@ -32,23 +33,19 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypes; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -60,72 +57,58 @@ public abstract class ToStringNode extends RBaseNode { @Child private ToStringNode recursiveToString; - private final ConditionProfile isCachedIntProfile = ConditionProfile.createBinaryProfile(); - private final NACheck naCheck = NACheck.create(); - - private String toStringRecursive(Object o, boolean quotes, String separator) { + private String toStringRecursive(Object o, String separator) { if (recursiveToString == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); recursiveToString = insert(ToStringNodeGen.create()); } - return recursiveToString.executeString(o, quotes, separator); + return recursiveToString.executeString(o, separator); } - public abstract String executeString(Object o, boolean quotes, String separator); + public abstract String executeString(Object o, String separator); - @SuppressWarnings("unused") @Specialization - protected String toString(String value, boolean quotes, String separator) { - if (RRuntime.isNA(value)) { - return value; - } - if (quotes) { - return RRuntime.escapeString(value, false, true); - } + protected String toString(String value, @SuppressWarnings("unused") String separator) { return value; } - @SuppressWarnings("unused") @Specialization - protected String toString(RNull vector, boolean quotes, String separator) { + protected String toString(@SuppressWarnings("unused") RNull vector, @SuppressWarnings("unused") String separator) { return "NULL"; } - @SuppressWarnings("unused") @Specialization - protected String toString(RFunction function, boolean quotes, String separator) { + protected String toString(RFunction function, @SuppressWarnings("unused") String separator) { return RRuntime.toString(function); } - @SuppressWarnings("unused") @Specialization - protected String toString(RSymbol symbol, boolean quotes, String separator) { + protected String toString(RSymbol symbol, @SuppressWarnings("unused") String separator) { return symbol.getName(); } - @SuppressWarnings("unused") @Specialization - protected String toString(RComplex complex, boolean quotes, String separator) { + protected String toString(RComplex complex, @SuppressWarnings("unused") String separator, + @Cached("create()") NACheck naCheck) { naCheck.enable(complex); return naCheck.convertComplexToString(complex); } - @SuppressWarnings("unused") @Specialization - protected String toString(RRaw raw, boolean quotes, String separator) { + protected String toString(RRaw raw, @SuppressWarnings("unused") String separator) { return RRuntime.rawToHexString(raw.getValue()); } - @SuppressWarnings("unused") @Specialization - protected String toString(int operand, boolean quotes, String separator) { + protected String toString(int operand, @SuppressWarnings("unused") String separator) { return RRuntime.intToString(operand); } - @SuppressWarnings("unused") @Specialization - protected String toString(double operand, boolean quotes, String separator) { + protected String toString(double operand, @SuppressWarnings("unused") String separator, + @Cached("createBinaryProfile()") ConditionProfile isCachedIntProfile, + @Cached("create()") NACheck naCheck) { int intValue = (int) operand; if (isCachedIntProfile.profile(intValue == operand && RRuntime.isCachedNumberString(intValue))) { return RRuntime.getCachedNumberString(intValue); @@ -134,104 +117,84 @@ public abstract class ToStringNode extends RBaseNode { return naCheck.convertDoubleToString(operand); } - @SuppressWarnings("unused") @Specialization - protected String toString(byte operand, boolean quotes, String separator) { + protected String toString(byte operand, @SuppressWarnings("unused") String separator) { return RRuntime.logicalToString(operand); } @Specialization - protected String toString(RS4Object obj, @SuppressWarnings("unused") boolean quotes, String separator, - @Cached(value = "createWithImplicit()") ClassHierarchyNode hierarchy) { + @TruffleBoundary + protected String toString(RS4Object obj, @SuppressWarnings("unused") String separator, + @Cached("createWithImplicit()") ClassHierarchyNode hierarchy) { RStringVector classHierarchy = hierarchy.execute(obj); - Object clazz; - if (classHierarchy.getLength() > 0) { - clazz = toString(classHierarchy.getDataAt(0), true, separator); - } else { + if (classHierarchy.getLength() == 0) { throw RInternalError.shouldNotReachHere("S4 object has no class"); } - return Utils.stringFormat("<S4 object of class %s>", clazz); + return "<S4 object of class \"" + classHierarchy.getDataAt(0) + "\">"; } - @FunctionalInterface - private interface ElementFunction { - String apply(int index, boolean quotes, String separator); - } + private static final EnumMap<RType, String> EMPTY = new EnumMap<>(RType.class); - private static String createResultForVector(RAbstractVector vector, boolean quotes, String separator, String empty, ElementFunction elementFunction) { - CompilerAsserts.neverPartOfCompilation(); - int length = vector.getLength(); - if (length == 0) { - return empty; - } - StringBuilder b = new StringBuilder(); - for (int i = 0; i < length; i++) { - if (i > 0) { - b.append(separator); - } - b.append(elementFunction.apply(i, quotes, separator)); - } - return b.toString(); + static { + EMPTY.put(RType.Integer, "integer(0)"); + EMPTY.put(RType.Double, "numeric(0)"); + EMPTY.put(RType.Character, "character(0)"); + EMPTY.put(RType.Logical, "logical(0)"); + EMPTY.put(RType.Raw, "raw(0)"); + EMPTY.put(RType.Complex, "complex(0)"); + EMPTY.put(RType.List, "list()"); } - @Specialization - @TruffleBoundary - protected String toString(RAbstractIntVector vector, boolean quotes, String separator) { - return createResultForVector(vector, quotes, separator, "integer(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s)); - } - - @Specialization @TruffleBoundary - protected String toString(RAbstractDoubleVector vector, boolean quotes, String separator) { - return createResultForVector(vector, quotes, separator, "numeric(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s)); - } - - @Specialization - @TruffleBoundary - protected String toString(RAbstractStringVector vector, boolean quotes, String separator) { - return createResultForVector(vector, quotes, separator, "character(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s)); - } - - @Specialization - @TruffleBoundary - protected String toString(RAbstractLogicalVector vector, boolean quotes, String separator) { - return createResultForVector(vector, quotes, separator, "logical(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s)); - } - - @Specialization - @TruffleBoundary - protected String toString(RAbstractRawVector vector, boolean quotes, String separator) { - return createResultForVector(vector, quotes, separator, "raw(0)", (index, q, s) -> RRuntime.rawToHexString(vector.getRawDataAt(index))); + private String vectorToString(RAbstractVector vector, String separator, VectorAccess vectorAccess) { + try (SequentialIterator iter = vectorAccess.access(vector)) { + int length = vectorAccess.getLength(iter); + if (length == 0) { + return EMPTY.get(vectorAccess.getType()); + } + StringBuilder b = new StringBuilder(); + if (vectorAccess.next(iter)) { + while (true) { + if (vectorAccess.getType() == RType.List) { + Object value = vectorAccess.getListElement(iter); + if (value instanceof RAbstractListVector) { + RAbstractListVector l = (RAbstractListVector) value; + if (l.getLength() == 0) { + b.append("list()"); + } else { + b.append("list(").append(toStringRecursive(l, separator)).append(')'); + } + } else { + b.append(toStringRecursive(value, separator)); + } + } else { + b.append(vectorAccess.getString(iter)); + } + if (!vectorAccess.next(iter)) { + break; + } + b.append(separator); + } + } + return b.toString(); + } } - @Specialization - @TruffleBoundary - protected String toString(RAbstractComplexVector vector, boolean quotes, String separator) { - return createResultForVector(vector, quotes, separator, "complex(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s)); + @Specialization(guards = "vectorAccess.supports(vector)") + protected String toStringVectorCached(RAbstractVector vector, String separator, + @Cached("vector.access()") VectorAccess vectorAccess) { + return vectorToString(vector, separator, vectorAccess); } - @Specialization - @TruffleBoundary - protected String toString(RList vector, boolean quotes, String separator) { - return createResultForVector(vector, quotes, separator, "list()", (index, q, s) -> { - Object value = vector.getDataAt(index); - if (value instanceof RList) { - RList l = (RList) value; - if (l.getLength() == 0) { - return "list()"; - } else { - return "list(" + toStringRecursive(l, q, s) + ')'; - } - } else { - return toStringRecursive(value, q, s); - } - }); + @Specialization(replaces = "toStringVectorCached") + protected String toStringVectorGeneric(RAbstractVector vector, String separator) { + return vectorToString(vector, separator, vector.slowPathAccess()); } @SuppressWarnings("unused") @Specialization @TruffleBoundary - protected String toString(REnvironment env, boolean quotes, String separator) { + protected String toString(REnvironment env, String separator) { return env.toString(); } } -- GitLab