Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 65b8816dfb0d
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: bdac068412fe
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on May 24, 2016

  1. Copy the full SHA
    686392b View commit details
  2. Copy the full SHA
    bdac068 View commit details
Original file line number Diff line number Diff line change
@@ -14,41 +14,40 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.utilities.CyclicAssumption;
import org.jcodings.specific.UTF8Encoding;
import org.joda.time.DateTimeZone;
import org.jruby.truffle.core.rope.Rope;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.core.time.TimeNodes.TimeZoneParser;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.SnippetNode;

public abstract class ReadTimeZoneNode extends RubyNode {
public abstract class GetTimeZoneNode extends RubyNode {

protected static final CyclicAssumption TZ_UNCHANGED = new CyclicAssumption("ENV['TZ'] is unmodified");

public static void invalidateTZ() {
TZ_UNCHANGED.invalidate();
}

private static final Rope DEFAULT_ZONE = StringOperations.encodeRope(DateTimeZone.getDefault().toString(), UTF8Encoding.INSTANCE);

@Child SnippetNode snippetNode = new SnippetNode();

public abstract DateTimeZone executeGetTimeZone(VirtualFrame frame);

@Specialization(assumptions = "TZ_UNCHANGED.getAssumption()")
public DynamicObject getTZ(VirtualFrame frame,
@Cached("getTZValue(frame)") DynamicObject tzValue) {
return tzValue;
public DateTimeZone getTimeZone(VirtualFrame frame,
@Cached("getTimeZone(frame)") DateTimeZone zone) {
return zone;
}

protected DynamicObject getTZValue(VirtualFrame frame) {
protected DateTimeZone getTimeZone(VirtualFrame frame) {
Object tz = snippetNode.execute(frame, "ENV['TZ']");

// TODO CS 4-May-15 not sure how TZ ends up being nil

if (tz == nil()) {
return createString(DEFAULT_ZONE);
return DateTimeZone.getDefault();
} else if (RubyGuards.isRubyString(tz)) {
return (DynamicObject) tz;
return TimeZoneParser.parse(this, StringOperations.getString(getContext(), (DynamicObject) tz));
} else {
throw new UnsupportedOperationException();
}
57 changes: 26 additions & 31 deletions truffle/src/main/java/org/jruby/truffle/core/time/TimeNodes.java
Original file line number Diff line number Diff line change
@@ -33,7 +33,6 @@
import org.jruby.truffle.builtins.PrimitiveArrayArgumentsNode;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.NotProvided;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.SnippetNode;
import org.jruby.truffle.language.control.RaiseException;
@@ -94,17 +93,17 @@ public Object internalOffset(DynamicObject time) {

@CoreMethod(names = "localtime_internal", optional = 1)
public abstract static class LocalTimeNode extends CoreMethodArrayArgumentsNode {
@Child private ReadTimeZoneNode readTimeZoneNode;

@Child private GetTimeZoneNode getTimeZoneNode;

public LocalTimeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readTimeZoneNode = ReadTimeZoneNodeGen.create();
getTimeZoneNode = GetTimeZoneNodeGen.create();
}

@Specialization
public DynamicObject localtime(VirtualFrame frame, DynamicObject time, NotProvided offset) {
final DynamicObject zoneName = (DynamicObject) readTimeZoneNode.execute(frame);
final DateTimeZone dateTimeZone = TimeZoneParser.parse(this, StringOperations.getString(getContext(), zoneName));
final DateTimeZone dateTimeZone = getTimeZoneNode.executeGetTimeZone(frame);
final String shortZoneName = TimeZoneParser.getShortZoneName(time, dateTimeZone);
final DynamicObject zone = createString(StringOperations.encodeRope(shortZoneName, UTF8Encoding.INSTANCE));
final DateTime dateTime = Layouts.TIME.getDateTime(time);
@@ -218,36 +217,35 @@ public DynamicObject allocate(DynamicObject rubyClass) {
public static abstract class TimeSNowPrimitiveNode extends PrimitiveArrayArgumentsNode {

@Child private AllocateObjectNode allocateObjectNode;
@Child private ReadTimeZoneNode readTimeZoneNode;
@Child private GetTimeZoneNode getTimeZoneNode;

public TimeSNowPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
allocateObjectNode = AllocateObjectNodeGen.create(context, sourceSection, null, null);
readTimeZoneNode = ReadTimeZoneNodeGen.create();
getTimeZoneNode = GetTimeZoneNodeGen.create();
}

@Specialization
public DynamicObject timeSNow(VirtualFrame frame, DynamicObject timeClass) {
// TODO CS 4-Mar-15 whenever we get time we have to convert lookup and time zone to a string and look it up - need to cache somehow...
return allocateObjectNode.allocate(timeClass, now((DynamicObject) readTimeZoneNode.execute(frame)), 0, nil(), nil(), false, false);
return allocateObjectNode.allocate(timeClass, now(getTimeZoneNode.executeGetTimeZone(frame)), 0, nil(), nil(), false, false);
}

@TruffleBoundary
private DateTime now(DynamicObject timeZone) {
assert RubyGuards.isRubyString(timeZone);
return DateTime.now(TimeZoneParser.parse(this, StringOperations.getString(getContext(), timeZone)));
private DateTime now(DateTimeZone timeZone) {
return DateTime.now(timeZone);
}

}

@Primitive(name = "time_s_specific", needsSelf = false, lowerFixnumParameters = { 1 })
public static abstract class TimeSSpecificPrimitiveNode extends PrimitiveArrayArgumentsNode {

@Child private ReadTimeZoneNode readTimeZoneNode;
@Child private GetTimeZoneNode getTimeZoneNode;

public TimeSSpecificPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readTimeZoneNode = ReadTimeZoneNodeGen.create();
getTimeZoneNode = GetTimeZoneNodeGen.create();
}

@Specialization(guards = { "isUTC" })
@@ -260,7 +258,8 @@ public DynamicObject timeSSpecificUTC(long seconds, int nanoseconds, boolean isU
public DynamicObject timeSSpecific(VirtualFrame frame, long seconds, int nanoseconds, boolean isUTC, Object offset) {
final long milliseconds = getMillis(seconds, nanoseconds);
return Layouts.TIME.createTime(coreLibrary().getTimeFactory(),
localtime(milliseconds, (DynamicObject) readTimeZoneNode.execute(frame)), nanoseconds % 1_000_000, nil(), offset, false, isUTC);
localtime(milliseconds, getTimeZoneNode.executeGetTimeZone(frame)),
nanoseconds % 1_000_000, nil(), offset, false, isUTC);
}

@Specialization(guards = { "!isUTC" })
@@ -290,9 +289,8 @@ private DateTime offsetTime(long milliseconds, long offset) {
}

@TruffleBoundary
private DateTime localtime(long milliseconds, DynamicObject zoneName) {
assert RubyGuards.isRubyString(zoneName);
return new DateTime(milliseconds, TimeZoneParser.parse(this, StringOperations.getString(getContext(), zoneName)));
private DateTime localtime(long milliseconds, DateTimeZone timeZone) {
return new DateTime(milliseconds, timeZone);
}

}
@@ -321,11 +319,8 @@ public long timeUSeconds(DynamicObject time) {
@Primitive(name = "time_decompose")
public static abstract class TimeDecomposePrimitiveNode extends PrimitiveArrayArgumentsNode {

@Child private ReadTimeZoneNode readTimeZoneNode;

public TimeDecomposePrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readTimeZoneNode = ReadTimeZoneNodeGen.create();
}

@TruffleBoundary
@@ -383,12 +378,12 @@ public DynamicObject timeStrftime(DynamicObject time, DynamicObject format) {
@Primitive(name = "time_s_from_array", needsSelf = true, lowerFixnumParameters = { 0 /*sec*/, 1 /* min */, 2 /* hour */, 3 /* mday */, 4 /* month */, 5 /* year */, 6 /*nsec*/, 7 /*isdst*/ })
public static abstract class TimeSFromArrayPrimitiveNode extends PrimitiveArrayArgumentsNode {

@Child ReadTimeZoneNode readTimeZoneNode;
@Child GetTimeZoneNode getTimeZoneNode;
@Child AllocateObjectNode allocateObjectNode;

public TimeSFromArrayPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readTimeZoneNode = ReadTimeZoneNodeGen.create();
getTimeZoneNode = GetTimeZoneNodeGen.create();
allocateObjectNode = AllocateObjectNodeGen.create(context, sourceSection, null, null);
}

@@ -397,25 +392,25 @@ public DynamicObject timeSFromArray(VirtualFrame frame, DynamicObject timeClass,
int nsec, int isdst, boolean fromutc, DynamicObject utcoffset,
@Cached("new()") SnippetNode snippetNode) {

DynamicObject envZon = null;
DateTimeZone envZone = null;
if (!fromutc && utcoffset == nil()) {
envZon = (DynamicObject) readTimeZoneNode.execute(frame);
envZone = getTimeZoneNode.executeGetTimeZone(frame);
}

final int millis = cast(snippetNode.execute(frame, "(offset * 1000).to_i", "offset", utcoffset));

return buildTime(timeClass, sec, min, hour, mday, month, year, nsec, isdst, fromutc, utcoffset, envZon, millis);
return buildTime(timeClass, sec, min, hour, mday, month, year, nsec, isdst, fromutc, utcoffset, envZone, millis);
}

@Specialization(guards = "(fromutc || !isDynamicObject(utcoffset)) || isNil(utcoffset)")
public DynamicObject timeSFromArray(VirtualFrame frame, DynamicObject timeClass, int sec, int min, int hour, int mday, int month, int year,
int nsec, int isdst, boolean fromutc, Object utcoffset) {

DynamicObject envZon = null;
DateTimeZone envZone = null;
if (!fromutc && utcoffset == nil()) {
envZon = (DynamicObject) readTimeZoneNode.execute(frame);
envZone = getTimeZoneNode.executeGetTimeZone(frame);
}
return buildTime(timeClass, sec, min, hour, mday, month, year, nsec, isdst, fromutc, utcoffset, envZon, -1);
return buildTime(timeClass, sec, min, hour, mday, month, year, nsec, isdst, fromutc, utcoffset, envZone, -1);
}

@Specialization(guards = "!isInteger(sec) || !isInteger(nsec)")
@@ -426,7 +421,7 @@ public DynamicObject timeSFromArrayFallback(VirtualFrame frame, DynamicObject ti

@TruffleBoundary
private DynamicObject buildTime(DynamicObject timeClass, int sec, int min, int hour, int mday, int month, int year,
int nsec, int isdst, boolean fromutc, Object utcoffset, DynamicObject envZon, int millis) {
int nsec, int isdst, boolean fromutc, Object utcoffset, DateTimeZone envZone, int millis) {
if (sec < 0 || sec > 59 ||
min < 0 || min > 59 ||
hour < 0 || hour > 23 ||
@@ -452,7 +447,7 @@ private DynamicObject buildTime(DynamicObject timeClass, int sec, int min, int h
relativeOffset = false;
zoneToStore = nil();
} else if (utcoffset == nil()) {
zone = TimeZoneParser.parse(this, StringOperations.getString(getContext(), envZon));
zone = envZone;
// TODO BJF 16-Feb-2016 verify which zone the following date time should be in
final String zoneName = TimeZoneParser.getShortZoneName(dt.withZoneRetainFields(zone), zone);
zoneToStore = createString(StringOperations.encodeRope(zoneName, UTF8Encoding.INSTANCE));
@@ -593,7 +588,7 @@ public static String getShortZoneName(DateTime dateTime, DateTimeZone zone) {
return zone.getShortName(dateTime.getMillis());
}

@TruffleBoundary
@TruffleBoundary(throwsControlFlowException = true)
public static DateTimeZone parse(RubyNode node, String zone) {
String upZone = zone.toUpperCase(Locale.ENGLISH);

Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@
import org.jruby.truffle.core.rope.RopeNodesFactory;
import org.jruby.truffle.extra.ffi.PointerPrimitiveNodes;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.core.time.ReadTimeZoneNode;
import org.jruby.truffle.core.time.GetTimeZoneNode;
import org.jruby.truffle.language.NotProvided;
import org.jruby.truffle.language.SnippetNode;
import org.jruby.truffle.language.control.RaiseException;
@@ -286,7 +286,7 @@ public abstract static class SetenvNode extends CoreMethodArrayArgumentsNode {
public int setenv(DynamicObject name, DynamicObject value, int overwrite) {
final String nameString = decodeUTF8(name);
if (nameString.equals("TZ")) {
ReadTimeZoneNode.invalidateTZ();
GetTimeZoneNode.invalidateTZ();
}
return posix().setenv(nameString, decodeUTF8(value), overwrite);
}