diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java index 967be7aeeff45a46ba52aeeec43e85ae574f509f..9c89ec3258afce7e357a46d969db49005a1e40c4 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java @@ -131,8 +131,6 @@ import sun.misc.Unsafe; */ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { - private final Map<String, Object> nameSymbolCache = new ConcurrentHashMap<>(); - private static RuntimeException implementedAsNode() { // TODO: Exception handling over native boundaries is currently missing. Once this works, // remove the following two lines. @@ -270,6 +268,11 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { while (env != REnvironment.emptyEnv()) { Object value = env.get(name.getName()); if (value != null) { + if (value instanceof RPromise && ((RPromise) value).isOptimized()) { + // From the point of view of RFFI, optimized promises (i.e. promises with null + // env) should not show up + return ((RPromise) value).getRawValue(); + } return value; } if (!inherits) { @@ -350,12 +353,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { @Override @TruffleBoundary public Object Rf_install(String name) { - Object ret = nameSymbolCache.get(name); - if (ret == null) { - ret = RDataFactory.createSymbolInterned(name); - nameSymbolCache.put(name, ret); - } - return ret; + return RDataFactory.createSymbolInterned(name); } @Override diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java index 61fa874e2c41ff9556ba9ef288fc7eb4fd5b9d25..379adb56840d43fc6fecbed3ea96407bed54f423 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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,20 +26,13 @@ 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.dsl.TypeSystemReference; -import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CAARNodeGen; -import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CAD4RNodeGen; -import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CADDDRNodeGen; -import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CADDRNodeGen; -import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CADRNodeGen; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CARNodeGen; -import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CDARNodeGen; -import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CDDDRNodeGen; -import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CDDRNodeGen; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CDRNodeGen; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.SETCARNodeGen; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode; import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.CharSXPWrapper; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLanguage; @@ -75,7 +68,7 @@ public final class ListAccessNodes { @Specialization protected Object car(RSymbol sym) { - return sym; + return CharSXPWrapper.create(sym.getName()); } @Specialization @@ -98,57 +91,6 @@ public final class ListAccessNodes { } } - @TypeSystemReference(RTypes.class) - public abstract static class CAARNode extends FFIUpCallNode.Arg1 { - - @Child private CARNode car1 = CARNode.create(); - @Child private CARNode car2 = CARNode.create(); - - @Specialization - protected Object caar(Object value) { - return car2.executeObject(car1.executeObject(value)); - } - - public static CAARNode create() { - return CAARNodeGen.create(); - } - } - - @TypeSystemReference(RTypes.class) - public static final class SETCADRNode extends FFIUpCallNode.Arg2 { - @Child private SETCARNode setcarNode = SETCARNode.create(); - @Child private CDRNode cdrNode = CDRNode.create(); - - @Override - public Object executeObject(Object x, Object y) { - return setcarNode.executeObject(cdrNode.executeObject(x), y); - } - } - - @TypeSystemReference(RTypes.class) - public abstract static class SETCARNode extends FFIUpCallNode.Arg2 { - public static SETCARNode create() { - return SETCARNodeGen.create(); - } - - @Specialization - protected Object doRLang(RLanguage x, Object y) { - x.getPairList().setCar(y); - return y; - } - - @Specialization - protected Object doRLang(RPairList x, Object y) { - x.setCar(y); - return y; - } - - @Fallback - protected Object car(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object y) { - throw RInternalError.unimplemented("SETCAR only works on pair lists or language objects"); - } - } - @TypeSystemReference(RTypes.class) public abstract static class CDRNode extends FFIUpCallNode.Arg1 { @Specialization @@ -183,6 +125,16 @@ public final class ListAccessNodes { return copy; } + @Specialization + protected RNull cdr(@SuppressWarnings("unused") RSymbol symbol) { + return RNull.instance; + } + + @Specialization + protected RNull handleNull(@SuppressWarnings("unused") RNull rNull) { + return rNull; + } + @Fallback protected Object cdr(@SuppressWarnings("unused") Object obj) { throw RInternalError.unimplemented("CDR only works on pair lists, language objects, and argument lists"); @@ -194,153 +146,161 @@ public final class ListAccessNodes { } @TypeSystemReference(RTypes.class) - public abstract static class CADRNode extends FFIUpCallNode.Arg1 { + public static final class CAARNode extends FFIUpCallNode.Arg1 { + + @Child private CARNode car1 = CARNode.create(); + @Child private CARNode car2 = CARNode.create(); + + @Override + public Object executeObject(Object x) { + return car2.executeObject(car1.executeObject(x)); + } + + public static CAARNode create() { + return new CAARNode(); + } + } + + @TypeSystemReference(RTypes.class) + public static final class SETCADRNode extends FFIUpCallNode.Arg2 { + @Child private SETCARNode setcarNode = SETCARNode.create(); + @Child private CDRNode cdrNode = CDRNode.create(); + + @Override + public Object executeObject(Object x, Object y) { + return setcarNode.executeObject(cdrNode.executeObject(x), y); + } + } + + @TypeSystemReference(RTypes.class) + public abstract static class SETCARNode extends FFIUpCallNode.Arg2 { + public static SETCARNode create() { + return SETCARNodeGen.create(); + } + @Specialization - protected Object cadr(RPairList pl) { - return pl.cadr(); + protected Object doRLang(RLanguage x, Object y) { + x.getPairList().setCar(y); + return y; } @Specialization - protected Object cadr(RLanguage lang) { - return lang.getDataAtAsObject(1); + protected Object doRPairList(RPairList x, Object y) { + x.setCar(y); + return y; } @Fallback - protected Object cadr(@SuppressWarnings("unused") Object obj) { - throw RInternalError.unimplemented("CADR only works on pair lists and language objects"); + protected Object car(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object y) { + throw RInternalError.unimplemented("SETCAR only works on pair lists or language objects"); + } + } + + @TypeSystemReference(RTypes.class) + public static final class CADRNode extends FFIUpCallNode.Arg1 { + @Child private CDRNode cdr = CDRNode.create(); + @Child private CARNode car = CARNode.create(); + + @Override + public Object executeObject(Object x) { + return car.executeObject(cdr.executeObject(x)); } public static CADRNode create() { - return CADRNodeGen.create(); + return new CADRNode(); } } @TypeSystemReference(RTypes.class) - public abstract static class CDARNode extends FFIUpCallNode.Arg1 { + public static final class CDARNode extends FFIUpCallNode.Arg1 { @Child private CARNode car = CARNode.create(); @Child private CDRNode cdr = CDRNode.create(); - @Specialization - protected Object cdar(Object value) { - return cdr.executeObject(car.executeObject(value)); + @Override + public Object executeObject(Object x) { + return cdr.executeObject(car.executeObject(x)); } public static CDARNode create() { - return CDARNodeGen.create(); + return new CDARNode(); } } @TypeSystemReference(RTypes.class) - public abstract static class CADDRNode extends FFIUpCallNode.Arg1 { - @Specialization - protected Object caddr(RPairList pl) { - return pl.caddr(); - } - - @Specialization - protected Object caddr(RLanguage lang) { - return lang.getDataAtAsObject(2); - } + public static final class CADDRNode extends FFIUpCallNode.Arg1 { + @Child private CARNode car = CARNode.create(); + @Child private CDRNode cdr1 = CDRNode.create(); + @Child private CDRNode cdr2 = CDRNode.create(); - @Fallback - protected Object caddr(@SuppressWarnings("unused") Object obj) { - throw RInternalError.unimplemented("CADDR only works on pair lists and language objects"); + @Override + public Object executeObject(Object x) { + return car.executeObject(cdr1.executeObject(cdr2.executeObject(x))); } public static CADDRNode create() { - return CADDRNodeGen.create(); + return new CADDRNode(); } } @TypeSystemReference(RTypes.class) - public abstract static class CADDDRNode extends FFIUpCallNode.Arg1 { - @Specialization - protected Object cadddr(RPairList pl) { - RPairList tmp = (RPairList) pl.cddr(); - return tmp.cadr(); - } - - @Specialization - protected Object cadddr(RLanguage lang) { - return lang.getDataAtAsObject(3); - } + public static final class CADDDRNode extends FFIUpCallNode.Arg1 { + @Child private CARNode car = CARNode.create(); + @Child private CDRNode cdr1 = CDRNode.create(); + @Child private CDRNode cdr2 = CDRNode.create(); + @Child private CDRNode cdr3 = CDRNode.create(); - @Fallback - protected Object cadddr(@SuppressWarnings("unused") Object obj) { - throw RInternalError.unimplemented("CADDDR only works on pair lists and language objects"); + @Override + public Object executeObject(Object x) { + return car.executeObject(cdr1.executeObject(cdr2.executeObject(cdr3.executeObject(x)))); } public static CADDDRNode create() { - return CADDDRNodeGen.create(); + return new CADDDRNode(); } } @TypeSystemReference(RTypes.class) - public abstract static class CAD4RNode extends FFIUpCallNode.Arg1 { - @Specialization - protected Object cad4r(RPairList pl) { - RPairList tmp = (RPairList) pl.cddr(); - return tmp.caddr(); - } - - @Specialization - protected Object cad4r(RLanguage lang) { - return lang.getDataAtAsObject(4); - } + public static final class CAD4RNode extends FFIUpCallNode.Arg1 { + @Child private CADDDRNode cadddr = CADDDRNode.create(); + @Child private CDRNode cdr = CDRNode.create(); - @Fallback - protected Object cad4r(@SuppressWarnings("unused") Object obj) { - throw RInternalError.unimplemented("CAD4R only works on pair lists and language objects"); + @Override + public Object executeObject(Object x) { + return cadddr.executeObject(cdr.executeObject(x)); } public static CAD4RNode create() { - return CAD4RNodeGen.create(); + return new CAD4RNode(); } } @TypeSystemReference(RTypes.class) - public abstract static class CDDRNode extends FFIUpCallNode.Arg1 { - @Specialization - protected Object cddr(RPairList pl) { - return pl.cddr(); - } + public static final class CDDRNode extends FFIUpCallNode.Arg1 { + @Child private CDRNode cdr1 = CDRNode.create(); + @Child private CDRNode cdr2 = CDRNode.create(); - @Specialization - protected Object cddr(RLanguage lang) { - RPairList l = lang.getPairList(); - return l.cddr(); - } - - @Fallback - protected Object cddr(@SuppressWarnings("unused") Object obj) { - throw RInternalError.unimplemented("CDDR only works on pair lists and language objects"); + @Override + public Object executeObject(Object x) { + return cdr1.executeObject(cdr2.executeObject(x)); } public static CDDRNode create() { - return CDDRNodeGen.create(); + return new CDDRNode(); } } @TypeSystemReference(RTypes.class) - public abstract static class CDDDRNode extends FFIUpCallNode.Arg1 { - @Specialization - protected Object cdddr(RPairList pl) { - return pl.cddr(); - } - - @Specialization - protected Object cdddr(RLanguage lang) { - RPairList l = (RPairList) lang.getPairList().cddr(); - return l.cdr(); - } + public static final class CDDDRNode extends FFIUpCallNode.Arg1 { + @Child CDDRNode cddr = CDDRNode.create(); + @Child CDRNode cdr = CDRNode.create(); - @Fallback - protected Object cdddr(@SuppressWarnings("unused") Object obj) { - throw RInternalError.unimplemented("CDDDR only works on pair lists and language objects"); + @Override + public Object executeObject(Object x) { + return cdr.executeObject(cddr.executeObject(x)); } public static CDDDRNode create() { - return CDDDRNodeGen.create(); + return new CDDDRNode(); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java index 769b288779887581dabdaab4d381bac80220b5c9..3f1214d0f8bcab8f3a7a9eb3e3811f2ac26270e6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2012, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2014, 2017, Oracle and/or its affiliates + * Copyright (c) 2014, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -27,6 +27,7 @@ import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; @@ -79,10 +80,24 @@ public class DatePOSIXFunctions { public final int[] yday; public final int[] isdst; private boolean complete = true; - private final String zone; - - POSIXltBuilder(int length, String zone) { - this.zone = zone; + private final RAbstractStringVector zone; + + private final TimeZone realZone; + + POSIXltBuilder(int length, String explicitZone) { + String[] zones = new String[3]; + zones[0] = explicitZone; + realZone = explicitZone.isEmpty() ? RContext.getInstance().stateREnvVars.getSystemTimeZone() : TimeZone.getTimeZone(explicitZone); + // getTimeZone returns the default if the ID does not exist, by comparing the return's + // value ID to the explicit one we can find out the if the zone was found. + if (explicitZone.isEmpty() || realZone.getID().equals(explicitZone)) { + zones[1] = realZone.getDisplayName(false, TimeZone.SHORT); + zones[2] = realZone.useDaylightTime() ? realZone.getDisplayName(true, TimeZone.SHORT) : ""; + } else { + zones[1] = explicitZone; + zones[2] = ""; + } + this.zone = RDataFactory.createStringVector(zones, RDataFactory.COMPLETE_VECTOR); sec = new double[length]; min = new int[length]; hour = new int[length]; @@ -94,6 +109,10 @@ public class DatePOSIXFunctions { isdst = new int[length]; } + public TimeZone getRealZone() { + return realZone; + } + public void setEntry(int index, double newSec, int newMin, int newHour, int newMDay, int newMon, int newYear, int newWDay, int newYDay, int newIsDst) { sec[index] = newSec; min[index] = newMin; @@ -151,14 +170,13 @@ public class DatePOSIXFunctions { @TruffleBoundary protected RList doDate2POSIXlt(RAbstractDoubleVector x) { int xLen = x.getLength(); - TimeZone zone = TimeZone.getTimeZone("UTC"); POSIXltBuilder builder = new POSIXltBuilder(xLen, "UTC"); for (int i = 0; i < xLen; i++) { double d = x.getDataAt(i); if (RRuntime.isFinite(d)) { int day = (int) Math.floor(d); Instant instant = Instant.ofEpochSecond(day * 3600L * 24L); - ZonedDateTime date = ZonedDateTime.ofInstant(instant, zone.toZoneId()); + ZonedDateTime date = ZonedDateTime.ofInstant(instant, builder.getRealZone().toZoneId()); builder.setEntry(i, 0, 0, 0, date.getDayOfMonth(), date.getMonthValue() - 1, date.getYear() - 1900, date.getDayOfWeek().ordinal(), date.getDayOfYear(), 0); } else { builder.setIncompleteEntry(i); @@ -187,20 +205,16 @@ public class DatePOSIXFunctions { @Specialization @TruffleBoundary protected RList asPOSIXlt(RAbstractDoubleVector x, String tz) { - TimeZone zone; - if (tz.isEmpty()) { - zone = RContext.getInstance().stateREnvVars.getSystemTimeZone(); - } else { - zone = TimeZone.getTimeZone(tz); - } int xLen = x.getLength(); - POSIXltBuilder builder = new POSIXltBuilder(xLen, zone.getDisplayName(false, TimeZone.SHORT)); + POSIXltBuilder builder = new POSIXltBuilder(xLen, tz); for (int i = 0; i < xLen; i++) { double second = x.getDataAt(i); if (RRuntime.isFinite(second)) { Instant instant = Instant.ofEpochSecond((long) second); - ZonedDateTime date = ZonedDateTime.ofInstant(instant, zone.toZoneId()); - builder.setEntry(i, date.getSecond(), date.getMinute(), date.getHour(), date.getDayOfMonth(), date.getMonthValue() - 1, date.getYear() - 1900, date.getDayOfWeek().ordinal(), + double miliseconds = second - Math.floor(second); + ZonedDateTime date = ZonedDateTime.ofInstant(instant, builder.getRealZone().toZoneId()); + builder.setEntry(i, date.getSecond() + miliseconds, date.getMinute(), date.getHour(), date.getDayOfMonth(), date.getMonthValue() - 1, date.getYear() - 1900, + date.getDayOfWeek().ordinal(), date.getDayOfYear(), 0); } else { builder.setIncompleteEntry(i); @@ -403,15 +417,9 @@ public class DatePOSIXFunctions { @Specialization @TruffleBoundary protected RList strptime(RAbstractStringVector x, RAbstractStringVector format, RAbstractStringVector tz) { - TimeZone zone; String zoneString = RRuntime.asString(tz); - if (zoneString.isEmpty()) { - zone = RContext.getInstance().stateREnvVars.getSystemTimeZone(); - } else { - zone = TimeZone.getTimeZone(zoneString); - } int length = x.getLength(); - POSIXltBuilder builder = new POSIXltBuilder(length, zone.getDisplayName(false, TimeZone.SHORT)); + POSIXltBuilder builder = new POSIXltBuilder(length, zoneString); DateTimeFormatterBuilder[] builders = createFormatters(format, true); DateTimeFormatter[] formatters = new DateTimeFormatter[builders.length]; for (int i = 0; i < builders.length; i++) { @@ -436,7 +444,8 @@ public class DatePOSIXFunctions { LocalTime tm = LocalTime.from(parse); time = LocalDateTime.of(LocalDate.now(), tm); } - builder.setEntry(i, time.getSecond(), time.getMinute(), time.getHour(), time.getDayOfMonth(), time.getMonthValue() - 1, time.getYear() - 1900, time.getDayOfWeek().ordinal(), + double ms = (time.toInstant(ZoneOffset.UTC).toEpochMilli() % 1000) / 1000; + builder.setEntry(i, time.getSecond() + ms, time.getMinute(), time.getHour(), time.getDayOfMonth(), time.getMonthValue() - 1, time.getYear() - 1900, time.getDayOfWeek().ordinal(), time.getDayOfYear(), 0); continue; } catch (DateTimeException e) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java index 1c929edaefe02a2a67214fabea519029792f1e77..3883d7ba9515f1b3213b6294cd5e5b8468ae1f18 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -35,6 +35,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.dsl.Cached; @@ -609,12 +610,13 @@ public class EnvFunctions { casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT); } - private BranchProfile frameSlotBranchProfile; + @CompilationFinal private BranchProfile frameSlotBranchProfile; @TruffleBoundary @Specialization protected Object makeActiveBinding(RSymbol sym, RFunction fun, REnvironment env) { if (frameSlotBranchProfile == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); frameSlotBranchProfile = BranchProfile.create(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java index 589957931b9e004908c86a8c8e179fa72438065d..41a88e9b7e122875e265287329a7cf4e3245338a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2012, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2013, 2017, Oracle and/or its affiliates + * Copyright (c) 2013, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -167,7 +167,7 @@ public class RRuntime { public static final String OP_NAMESPACE_SCOPE_EXPORTED = "::"; - public static final RSymbol DEFERRED_DEFAULT_MARKER = new RSymbol("__Deferred_Default_Marker__"); + public static final RSymbol DEFERRED_DEFAULT_MARKER = RSymbol.install("__Deferred_Default_Marker__"); public static final String R_TARGET = "target"; public static final String R_DOT_TARGET = ".target"; @@ -184,7 +184,7 @@ public class RRuntime { public static final String R_SRCFILE = "srcfile"; public static final String NULL = "NULL"; - public static final RSymbol PSEUDO_NULL = new RSymbol("\u0001NULL\u0001"); + public static final RSymbol PSEUDO_NULL = RSymbol.install("\u0001NULL\u0001"); public static final String UNBOUND = "UNBOUND"; @CompilationFinal(dimensions = 1) private static final String[] rawStringCache = new String[256]; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java index 4d2214df1c02417d30f4c278add801cdc54dd65d..131261bdbcadb195a67839841f5e971ac0f5ee19 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -618,7 +618,7 @@ public final class RDataFactory { public final RSymbol createSymbol(String name) { assert Utils.isInterned(name); - return traceDataCreated(new RSymbol(name)); + return traceDataCreated(RSymbol.install(name)); } /* @@ -1197,7 +1197,7 @@ public final class RDataFactory { public static RSymbol createSymbol(String name) { assert Utils.isInterned(name); - return traceDataCreated(new RSymbol(name)); + return traceDataCreated(RSymbol.install(name)); } /* diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java index 8f4bc9a99b1ab10abef07b05c514614fafe3da45..acf61beac80b4fda379e5b6517a6084091d2608f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -215,6 +215,14 @@ public class RPromise extends RObject implements RTypedValue { this.value = newValue; } + /** + * Promises to constants can be optimized, which means that they only hold the value, but do not + * need to keep the frame and will never need the frame. + */ + public boolean isOptimized() { + return this.execFrame == null; + } + /** * Returns {@code true} if this promise has been evaluated? */ diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java index ad8f31449e1039194392bc5b23d1f525e9bc34cc..903fd638fde1b7af7ef77d0d6d91db62ea5939ca 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -22,6 +22,12 @@ */ package com.oracle.truffle.r.runtime.data; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.r.runtime.RType; @@ -32,14 +38,24 @@ import com.oracle.truffle.r.runtime.RType; @ValueType public final class RSymbol extends RAttributeStorage { + /** + * Note: GnuR caches all symbols and some packages rely on their identity. + */ + private static final ConcurrentHashMap<String, RSymbol> symbolTable = new ConcurrentHashMap<>(); + public static final RSymbol MISSING = RDataFactory.createSymbol(""); private final String name; - public RSymbol(String name) { + private RSymbol(String name) { this.name = name; } + public static RSymbol install(String name) { + CompilerAsserts.neverPartOfCompilation(); + return symbolTable.computeIfAbsent(name, RSymbol::new); + } + @Override public RType getRType() { return RType.Symbol; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java index f65913a8cd94b99ae1ea3cfad3a33298ae275f7e..8bc97e9541f25710bfa63ed68ae7826661a1d3f6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java @@ -105,7 +105,8 @@ public class DLL { @Override public void beforeDispose(RContext contextArg) { - if (!isShareDLLKind(context.getKind())) { + // Note: the first entry should be RLib + if (!isShareDLLKind(context.getKind()) && list.size() > 1) { RootCallTarget closeCallTarget = DLCloseRootNode.create(contextArg); for (int i = 1; i < list.size(); i++) { DLLInfo dllInfo = list.get(i); @@ -341,7 +342,9 @@ public class DLL { data[3] = rnt.dotSymbol.numArgs; klass[0] = rnt.nst.name() + "Routine"; } - return RDataFactory.createList(data, n > 3 ? NAMES_4_VEC : NAMES_3_VEC); + RList result = RDataFactory.createList(data, n > 3 ? NAMES_4_VEC : NAMES_3_VEC); + result.setClassAttr(RDataFactory.createStringVector(klass, RDataFactory.COMPLETE_VECTOR)); + return result; } } diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R index cf85ab25b37bee4c3d962a1907f945a09187c62d..37a36ada6542ff5b75b6ffaa2ebfee172d9c3279 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R @@ -114,3 +114,8 @@ for(i in seq(5000)) { # Following code calls Rf_eval with a language object that contains a promise instead of the expected function set.seed(42) rffi.RfEvalWithPromiseInPairList() + +# CAR/CDR tests +rffi.CAR(NULL) +rffi.CDR(NULL) +invisible(rffi.CAR(as.symbol('a'))) # TODO: printing CHARSEXP not implemented in FastR diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 0b0edf26d2e95aab427b005ab75b9a49b2247d73..f1573834db43b803314f84bbb2b0bf2a351c7d46 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -5780,6 +5780,10 @@ Error in .Internal(as.POSIXlt(, 1)) : argument 1 is empty #.Internal(as.POSIXlt(2, )) Error in .Internal(as.POSIXlt(2, )) : argument 2 is empty +##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt# +#{ q <- Sys.time(); as.vector(unclass(as.POSIXct(as.POSIXlt(q))) - unclass(q)) } +[1] 0 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt1# #argv <- list(structure(c(2147483648.4, 2147483648.8), class = c('POSIXct', 'POSIXt'), tzone = ''), ''); .Internal(as.POSIXlt(argv[[1]], argv[[2]])) [1] "2038-01-19 03:14:08 GMT" "2038-01-19 03:14:08 GMT" diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java index eec124843f68e15f9f428b858505bf64deedb105..fcab2aa69722a50bdff80345438519aacad9a6b3 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2014, Purdue University - * Copyright (c) 2014, 2017, Oracle and/or its affiliates + * Copyright (c) 2014, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -76,5 +76,6 @@ public class TestBuiltin_asPOSIXlt extends TestBase { public void testasPOSIXlt() { assertEval(Output.MayIgnoreErrorContext, ".Internal(as.POSIXlt(, 1))"); assertEval(Output.MayIgnoreErrorContext, ".Internal(as.POSIXlt(2, ))"); + assertEval("{ q <- Sys.time(); as.vector(unclass(as.POSIXct(as.POSIXlt(q))) - unclass(q)) }"); } }