Skip to content

Commit

Permalink
[GR-44107] Expand Espresso interop with date and time related target …
Browse files Browse the repository at this point in the history
…types.

PullRequest: graal/13773
  • Loading branch information
javeleon committed Feb 24, 2023
2 parents 8cc2315 + 7d80c46 commit e0e5679
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@ public static void ensureInitialized() {
public static final Symbol<Name> toLocalDate = StaticSymbols.putName("toLocalDate");
public static final Symbol<Name> toLocalTime = StaticSymbols.putName("toLocalTime");
public static final Symbol<Name> toInstant = StaticSymbols.putName("toInstant");
public static final Symbol<Name> from = StaticSymbols.putName("from");
public static final Symbol<Name> ofInstant = StaticSymbols.putName("ofInstant");
public static final Symbol<Name> getZone = StaticSymbols.putName("getZone");
public static final Symbol<Name> getId = StaticSymbols.putName("getId");
public static final Symbol<Name> of = StaticSymbols.putName("of");
Expand All @@ -472,6 +474,7 @@ public static void ensureInitialized() {
public static final Symbol<Name> second = StaticSymbols.putName("second");
public static final Symbol<Name> nano = StaticSymbols.putName("nano");
public static final Symbol<Name> atZone = StaticSymbols.putName("atZone");
public static final Symbol<Name> ofEpochSecond = StaticSymbols.putName("ofEpochSecond");

// Map / List / Iterator
public static final Symbol<Name> get = StaticSymbols.putName("get");
Expand Down Expand Up @@ -912,9 +915,15 @@ public static void ensureInitialized() {

public static final Symbol<Signature> Class = StaticSymbols.putSignature(Type.java_lang_Class);
public static final Symbol<Signature> LocalDate = StaticSymbols.putSignature(Type.java_time_LocalDate);
public static final Symbol<Signature> LocalDate_int_int_int = StaticSymbols.putSignature(Type.java_time_LocalDate, Type._int, Type._int, Type._int);
public static final Symbol<Signature> LocalTime = StaticSymbols.putSignature(Type.java_time_LocalTime);
public static final Symbol<Signature> LocalDateTime_LocalDate_LocalTime = StaticSymbols.putSignature(Type.java_time_LocalDateTime, Type.java_time_LocalDate, Type.java_time_LocalTime);
public static final Symbol<Signature> LocalTime_int_int_int_int = StaticSymbols.putSignature(Type.java_time_LocalTime, Type._int, Type._int, Type._int, Type._int);
public static final Symbol<Signature> Instant = StaticSymbols.putSignature(Type.java_time_Instant);
public static final Symbol<Signature> Date_Instant = StaticSymbols.putSignature(Type.java_util_Date, Type.java_time_Instant);
public static final Symbol<Signature> Instant_long_long = StaticSymbols.putSignature(Type.java_time_Instant, Type._long, Type._long);
public static final Symbol<Signature> ZoneId = StaticSymbols.putSignature(Type.java_time_ZoneId);
public static final Symbol<Signature> ZonedDateTime_Instant_ZoneId = StaticSymbols.putSignature(Type.java_time_ZonedDateTime, Type.java_time_Instant, Type.java_time_ZoneId);
public static final Symbol<Signature> ZonedDateTime_ZoneId = StaticSymbols.putSignature(Type.java_time_ZonedDateTime, Type.java_time_ZoneId);
public static final Symbol<Signature> ZoneId_String = StaticSymbols.putSignature(Type.java_time_ZoneId, Type.java_lang_String);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -768,17 +768,20 @@ public Meta(EspressoContext context) {
java_time_Instant_nanos = java_time_Instant.requireDeclaredField(Name.nanos, Type._int);
java_time_Instant_atZone = java_time_Instant.requireDeclaredMethod(Name.atZone, Signature.ZonedDateTime_ZoneId);
assert java_time_Instant_atZone.isFinalFlagSet() || java_time_Instant.isFinalFlagSet();
java_time_Instant_ofEpochSecond = java_time_Instant.requireDeclaredMethod(Name.ofEpochSecond, Signature.Instant_long_long);

java_time_LocalTime = knownKlass(Type.java_time_LocalTime);
java_time_LocalTime_hour = java_time_LocalTime.requireDeclaredField(Name.hour, Type._byte);
java_time_LocalTime_minute = java_time_LocalTime.requireDeclaredField(Name.minute, Type._byte);
java_time_LocalTime_second = java_time_LocalTime.requireDeclaredField(Name.second, Type._byte);
java_time_LocalTime_nano = java_time_LocalTime.requireDeclaredField(Name.nano, Type._int);
java_time_LocalTime_of = java_time_LocalTime.requireDeclaredMethod(Name.of, Signature.LocalTime_int_int_int_int);

java_time_LocalDateTime = knownKlass(Type.java_time_LocalDateTime);
java_time_LocalDateTime_toLocalDate = java_time_LocalDateTime.requireDeclaredMethod(Name.toLocalDate, Signature.LocalDate);
java_time_LocalDateTime_toLocalTime = java_time_LocalDateTime.requireDeclaredMethod(Name.toLocalTime, Signature.LocalTime);
assert java_time_LocalDateTime_toLocalTime.isFinalFlagSet() || java_time_LocalDateTime.isFinalFlagSet();
java_time_LocalDateTime_of = java_time_LocalDateTime.requireDeclaredMethod(Name.of, Signature.LocalDateTime_LocalDate_LocalTime);

java_time_LocalDate = knownKlass(Type.java_time_LocalDate);
java_time_LocalDate_year = java_time_LocalDate.requireDeclaredField(Name.year, Type._int);
Expand All @@ -787,6 +790,7 @@ public Meta(EspressoContext context) {
assert java_time_LocalDate_month.getKind() == JavaKind.Short;
java_time_LocalDate_day = java_time_LocalDate.requireDeclaredField(Name.day, Type._short);
assert java_time_LocalDate_day.getKind() == JavaKind.Short;
java_time_LocalDate_of = java_time_LocalDate.requireDeclaredMethod(Name.of, Signature.LocalDate_int_int_int);

java_time_ZonedDateTime = knownKlass(Type.java_time_ZonedDateTime);
java_time_ZonedDateTime_toLocalTime = java_time_ZonedDateTime.requireDeclaredMethod(Name.toLocalTime, Signature.LocalTime);
Expand All @@ -799,9 +803,11 @@ public Meta(EspressoContext context) {
assert java_time_ZonedDateTime_getZone.isFinalFlagSet() || java_time_ZonedDateTime.isFinalFlagSet();
java_time_ZonedDateTime_toInstant = java_time_ZonedDateTime.requireMethod(Name.toInstant, Signature.Instant); // default
assert java_time_ZonedDateTime_toInstant.isFinalFlagSet() || java_time_ZonedDateTime.isFinalFlagSet();
java_time_ZonedDateTime_ofInstant = java_time_ZonedDateTime.requireDeclaredMethod(Name.ofInstant, Signature.ZonedDateTime_Instant_ZoneId);

java_util_Date = knownKlass(Type.java_util_Date);
java_util_Date_toInstant = java_util_Date.requireDeclaredMethod(Name.toInstant, Signature.Instant);
java_util_Date_from = java_util_Date.requireDeclaredMethod(Name.from, Signature.Date_Instant);
java_time_ZoneId = knownKlass(Type.java_time_ZoneId);
java_time_ZoneId_getId = java_time_ZoneId.requireDeclaredMethod(Name.getId, Signature.String);
java_time_ZoneId_of = java_time_ZoneId.requireDeclaredMethod(Name.of, Signature.ZoneId_String);
Expand Down Expand Up @@ -1425,29 +1431,35 @@ private DiffVersionLoadHelper diff() {
public final Field java_time_Instant_seconds;
public final Field java_time_Instant_nanos;
public final Method java_time_Instant_atZone;
public final Method java_time_Instant_ofEpochSecond;

public final ObjectKlass java_time_LocalTime;
public final Field java_time_LocalTime_hour;
public final Field java_time_LocalTime_minute;
public final Field java_time_LocalTime_second;
public final Field java_time_LocalTime_nano;
public final Method java_time_LocalTime_of;

public final ObjectKlass java_time_LocalDate;
public final Field java_time_LocalDate_year;
public final Field java_time_LocalDate_month;
public final Field java_time_LocalDate_day;
public final Method java_time_LocalDate_of;

public final ObjectKlass java_time_LocalDateTime;
public final Method java_time_LocalDateTime_toLocalTime;
public final Method java_time_LocalDateTime_toLocalDate;
public final Method java_time_LocalDateTime_of;
public final ObjectKlass java_time_ZonedDateTime;
public final Method java_time_ZonedDateTime_toLocalTime;
public final Method java_time_ZonedDateTime_toLocalDate;
public final Method java_time_ZonedDateTime_getZone;
public final Method java_time_ZonedDateTime_toInstant;
public final Method java_time_ZonedDateTime_ofInstant;

public final ObjectKlass java_util_Date;
public final Method java_util_Date_toInstant;
public final Method java_util_Date_from;
public final ObjectKlass java_time_ZoneId;
public final Method java_time_ZoneId_getId;
public final Method java_time_ZoneId_of;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, 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
Expand All @@ -22,6 +22,12 @@
*/
package com.oracle.truffle.espresso.nodes.interop;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
Expand Down Expand Up @@ -79,6 +85,38 @@ static boolean isStringCompatible(Meta meta, Klass klass) {
return klass.isAssignableFrom(meta.java_lang_String);
}

static boolean isZonedDateTime(Meta meta, Klass klass) {
return meta.java_time_ZonedDateTime.equals(klass);
}

static boolean isLocalDate(Meta meta, Klass klass) {
return meta.java_time_LocalDate.equals(klass);
}

static boolean isLocalTime(Meta meta, Klass klass) {
return meta.java_time_LocalTime.equals(klass);
}

static boolean isLocalDateTime(Meta meta, Klass klass) {
return meta.java_time_LocalDateTime.equals(klass);
}

static boolean isInstant(Meta meta, Klass klass) {
return meta.java_time_Instant.equals(klass);
}

static boolean isDate(Meta meta, Klass klass) {
return meta.java_util_Date.equals(klass);
}

static boolean isZoneId(Meta meta, Klass klass) {
return meta.java_time_ZoneId.equals(klass);
}

static boolean isDuration(Meta meta, Klass klass) {
return meta.java_time_Duration.equals(klass);
}

static boolean isByteArray(Meta meta, Klass klass) {
return meta._byte_array.equals(klass);
}
Expand Down Expand Up @@ -238,6 +276,134 @@ Object doForeignString(Object value, @SuppressWarnings("unused") ObjectKlass kla
}
}

@Specialization(guards = {
"isZonedDateTime(meta, klass)",
"!isStaticObject(value)",
"interop.isInstant(value)",
"interop.isTimeZone(value)",
})
Object doForeignDateTime(Object value, @SuppressWarnings("unused") ObjectKlass klass,
@Shared("value") @CachedLibrary(limit = "LIMIT") InteropLibrary interop,
@Bind("getMeta()") Meta meta) {
StaticObject guestInstant = (StaticObject) doForeignInstant(value, meta.java_time_Instant, interop, meta);
StaticObject guestZoneID = (StaticObject) doForeignZoneId(value, meta.java_time_ZoneId, interop, meta);

return meta.java_time_ZonedDateTime_ofInstant.invokeDirect(null, guestInstant, guestZoneID);
}

@Specialization(guards = {
"isLocalDate(meta, klass)",
"!isStaticObject(value)",
"interop.isDate(value)",
})
Object doForeignLocalDate(Object value, @SuppressWarnings("unused") ObjectKlass klass,
@Shared("value") @CachedLibrary(limit = "LIMIT") InteropLibrary interop,
@Bind("getMeta()") Meta meta) {
try {
LocalDate localDate = interop.asDate(value);
return meta.java_time_LocalDate_of.invokeDirect(null, localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw EspressoError.shouldNotReachHere("Contract violation: if isLocalDate returns true, asDate must succeed.");
}
}

@Specialization(guards = {
"isLocalTime(meta, klass)",
"!isStaticObject(value)",
"interop.isTime(value)",
})
Object doForeignLocalTime(Object value, @SuppressWarnings("unused") ObjectKlass klass,
@Shared("value") @CachedLibrary(limit = "LIMIT") InteropLibrary interop,
@Bind("getMeta()") Meta meta) {
try {
LocalTime localTime = interop.asTime(value);
return meta.java_time_LocalTime_of.invokeDirect(null, localTime.getHour(), localTime.getMinute(), localTime.getSecond(), localTime.getNano());
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw EspressoError.shouldNotReachHere("Contract violation: if isLocalTime returns true, asTime must succeed.");
}
}

@Specialization(guards = {
"isLocalDateTime(meta, klass)",
"!isStaticObject(value)",
"interop.isTime(value)",
"interop.isDate(value)",
})
Object doForeignLocalDateTime(Object value, @SuppressWarnings("unused") ObjectKlass klass,
@Shared("value") @CachedLibrary(limit = "LIMIT") InteropLibrary interop,
@Bind("getMeta()") Meta meta) {
return meta.java_time_LocalDateTime_of.invokeDirect(null,
doForeignLocalDate(value, meta.java_time_LocalDate, interop, meta),
doForeignLocalTime(value, meta.java_time_LocalTime, interop, meta));
}

@Specialization(guards = {
"isInstant(meta, klass)",
"!isStaticObject(value)",
"interop.isInstant(value)",
})
Object doForeignInstant(Object value, @SuppressWarnings("unused") ObjectKlass klass,
@Shared("value") @CachedLibrary(limit = "LIMIT") InteropLibrary interop,
@Bind("getMeta()") Meta meta) {
try {
Instant instant = interop.asInstant(value);
return meta.java_time_Instant_ofEpochSecond.invokeDirect(null, instant.getEpochSecond(), (long) instant.getNano());
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw EspressoError.shouldNotReachHere("Contract violation: if isInstant returns true, asInstant must succeed.");
}
}

@Specialization(guards = {
"isDate(meta, klass)",
"!isStaticObject(value)",
"interop.isInstant(value)",
})
Object doForeignDate(Object value, @SuppressWarnings("unused") ObjectKlass klass,
@Shared("value") @CachedLibrary(limit = "LIMIT") InteropLibrary interop,
@Bind("getMeta()") Meta meta) {
return meta.java_util_Date_from.invokeDirect(null, doForeignInstant(value, meta.java_time_Instant, interop, meta));
}

@Specialization(guards = {
"isZoneId(meta, klass)",
"!isStaticObject(value)",
"interop.isTimeZone(value)",
})
Object doForeignZoneId(Object value, @SuppressWarnings("unused") ObjectKlass klass,
@Shared("value") @CachedLibrary(limit = "LIMIT") InteropLibrary interop,
@Bind("getMeta()") Meta meta) {
try {
ZoneId zoneId = interop.asTimeZone(value);
return meta.java_time_ZoneId_of.invokeDirect(null, meta.toGuestString(zoneId.getId()));
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw EspressoError.shouldNotReachHere("Contract violation: if isZoneId returns true, asTimeZone must succeed.");
}
}

@Specialization(guards = {
"isDuration(meta, klass)",
"!isStaticObject(value)",
"interop.isDuration(value)",
})
Object doForeignDuration(Object value, @SuppressWarnings("unused") ObjectKlass klass,
@Shared("value") @CachedLibrary(limit = "LIMIT") InteropLibrary interop,
@Bind("getMeta()") Meta meta) {
try {
Duration duration = interop.asDuration(value);
StaticObject guestDuration = meta.getAllocator().createNew(meta.java_time_Duration);
meta.java_time_Duration_seconds.setLong(guestDuration, duration.getSeconds());
meta.java_time_Duration_nanos.setInt(guestDuration, duration.getNano());
return guestDuration;
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw EspressoError.shouldNotReachHere("Contract violation: if isDuration returns true, asDuration must succeed.");
}
}

@Specialization(guards = {
"isForeignException(context.getMeta(), klass)",
"!isStaticObject(value)",
Expand Down

0 comments on commit e0e5679

Please sign in to comment.