Skip to content

Commit b0e2b3c

Browse files
committed
Use ToEspressoNode for Polyglot.cast operations to streamline behavior
1 parent d6ddf70 commit b0e2b3c

File tree

4 files changed

+177
-223
lines changed

4 files changed

+177
-223
lines changed

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToPrimitive.java

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.oracle.truffle.api.nodes.NodeInfo;
3535
import com.oracle.truffle.api.profiles.BranchProfile;
3636
import com.oracle.truffle.espresso.meta.EspressoError;
37+
import com.oracle.truffle.espresso.runtime.dispatch.staticobject.EspressoInterop;
3738
import com.oracle.truffle.espresso.runtime.staticobject.StaticObject;
3839

3940
/**
@@ -102,8 +103,13 @@ int doHost(Integer value) {
102103
@Specialization
103104
int doEspresso(StaticObject value,
104105
@Cached BranchProfile exceptionProfile) throws UnsupportedTypeException {
105-
if (value != null && !StaticObject.isNull(value) && value.getKlass() == getMeta().java_lang_Integer) {
106-
return (int) getMeta().java_lang_Integer_value.get(value);
106+
if (value != null && !StaticObject.isNull(value) && EspressoInterop.fitsInInt(value)) {
107+
try {
108+
return EspressoInterop.asInt(value);
109+
} catch (UnsupportedMessageException e) {
110+
CompilerDirectives.transferToInterpreterAndInvalidate();
111+
throw EspressoError.shouldNotReachHere("Contract violation: if fitsInInt returns true, asInt must succeed.");
112+
}
107113
}
108114
exceptionProfile.enter();
109115
throw UnsupportedTypeException.create(new Object[]{value}, EspressoError.cat("Cannot cast ", value, " to int"));
@@ -148,8 +154,13 @@ byte doHost(Byte value) {
148154
@Specialization
149155
byte doEspresso(StaticObject value,
150156
@Cached BranchProfile exceptionProfile) throws UnsupportedTypeException {
151-
if (value != null && !StaticObject.isNull(value) && value.getKlass() == getMeta().java_lang_Byte) {
152-
return (byte) getMeta().java_lang_Byte_value.get(value);
157+
if (value != null && !StaticObject.isNull(value) && EspressoInterop.fitsInByte(value)) {
158+
try {
159+
return EspressoInterop.asByte(value);
160+
} catch (UnsupportedMessageException e) {
161+
CompilerDirectives.transferToInterpreterAndInvalidate();
162+
throw EspressoError.shouldNotReachHere("Contract violation: if fitsInByte returns true, asByte must succeed.");
163+
}
153164
}
154165
exceptionProfile.enter();
155166
throw UnsupportedTypeException.create(new Object[]{value}, EspressoError.cat("Cannot cast ", value, " to byte"));
@@ -194,8 +205,13 @@ short doHost(Short value) {
194205
@Specialization
195206
short doEspresso(StaticObject value,
196207
@Cached BranchProfile exceptionProfile) throws UnsupportedTypeException {
197-
if (value != null && !StaticObject.isNull(value) && value.getKlass() == getMeta().java_lang_Short) {
198-
return (short) getMeta().java_lang_Short_value.get(value);
208+
if (value != null && !StaticObject.isNull(value) && EspressoInterop.fitsInShort(value)) {
209+
try {
210+
return EspressoInterop.asShort(value);
211+
} catch (UnsupportedMessageException e) {
212+
CompilerDirectives.transferToInterpreterAndInvalidate();
213+
throw EspressoError.shouldNotReachHere("Contract violation: if fitsInShort returns true, asShort must succeed.");
214+
}
199215
}
200216
exceptionProfile.enter();
201217
throw UnsupportedTypeException.create(new Object[]{value}, EspressoError.cat("Cannot cast ", value, " to short"));
@@ -264,7 +280,7 @@ char doForeign(Object value,
264280
throw UnsupportedTypeException.create(new Object[]{value}, EspressoError.cat("Cannot cast ", s, " to char"));
265281
} catch (UnsupportedMessageException e) {
266282
CompilerDirectives.transferToInterpreterAndInvalidate();
267-
throw EspressoError.shouldNotReachHere("Contract violation: if fitsInInt returns true, asInt must succeed.");
283+
throw EspressoError.shouldNotReachHere("Contract violation: if isString returns true, asString must succeed.");
268284
}
269285
}
270286

@@ -292,8 +308,13 @@ long doHost(Long value) {
292308
@Specialization
293309
long doEspresso(StaticObject value,
294310
@Cached BranchProfile exceptionProfile) throws UnsupportedTypeException {
295-
if (value != null && !StaticObject.isNull(value) && value.getKlass() == getMeta().java_lang_Long) {
296-
return (long) getMeta().java_lang_Long_value.get(value);
311+
if (value != null && !StaticObject.isNull(value) && EspressoInterop.fitsInLong(value)) {
312+
try {
313+
return EspressoInterop.asLong(value);
314+
} catch (UnsupportedMessageException e) {
315+
CompilerDirectives.transferToInterpreterAndInvalidate();
316+
throw EspressoError.shouldNotReachHere("Contract violation: if fitsInLong returns true, asLong must succeed.");
317+
}
297318
}
298319
exceptionProfile.enter();
299320
throw UnsupportedTypeException.create(new Object[]{value}, EspressoError.cat("Cannot cast ", value, " to long"));
@@ -338,8 +359,13 @@ float doHost(Float value) {
338359
@Specialization
339360
float doEspresso(StaticObject value,
340361
@Cached BranchProfile exceptionProfile) throws UnsupportedTypeException {
341-
if (value != null && !StaticObject.isNull(value) && value.getKlass() == getMeta().java_lang_Float) {
342-
return (float) getMeta().java_lang_Float_value.get(value);
362+
if (value != null && !StaticObject.isNull(value) && EspressoInterop.fitsInFloat(value)) {
363+
try {
364+
return EspressoInterop.asFloat(value);
365+
} catch (UnsupportedMessageException e) {
366+
CompilerDirectives.transferToInterpreterAndInvalidate();
367+
throw EspressoError.shouldNotReachHere("Contract violation: if fitsInFloat returns true, asFloat must succeed.");
368+
}
343369
}
344370
exceptionProfile.enter();
345371
throw UnsupportedTypeException.create(new Object[]{value}, EspressoError.cat("Cannot cast ", value, " to float"));
@@ -384,8 +410,13 @@ public abstract static class ToDouble extends ToPrimitive {
384410
@Specialization
385411
double doEspresso(StaticObject value,
386412
@Cached BranchProfile exceptionProfile) throws UnsupportedTypeException {
387-
if (value != null && !StaticObject.isNull(value) && value.getKlass() == getMeta().java_lang_Double) {
388-
return (double) getMeta().java_lang_Double_value.get(value);
413+
if (value != null && !StaticObject.isNull(value) && EspressoInterop.fitsInDouble(value)) {
414+
try {
415+
return EspressoInterop.asDouble(value);
416+
} catch (UnsupportedMessageException e) {
417+
CompilerDirectives.transferToInterpreterAndInvalidate();
418+
throw EspressoError.shouldNotReachHere("Contract violation: if fitsInDouble returns true, asDouble must succeed.");
419+
}
389420
}
390421
exceptionProfile.enter();
391422
throw UnsupportedTypeException.create(new Object[]{value}, EspressoError.cat("Cannot cast ", value, " to double"));

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToReference.java

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import com.oracle.truffle.espresso.nodes.bytecodes.InstanceOf;
6262
import com.oracle.truffle.espresso.runtime.EspressoContext;
6363
import com.oracle.truffle.espresso.runtime.EspressoException;
64+
import com.oracle.truffle.espresso.runtime.dispatch.staticobject.EspressoInterop;
6465
import com.oracle.truffle.espresso.runtime.staticobject.StaticObject;
6566

6667
@NodeInfo(shortName = "Convert to Espresso StaticObject")
@@ -325,8 +326,33 @@ public abstract static class GenericToReference extends EspressoNode {
325326
@Specialization
326327
public StaticObject doStaticObject(StaticObject value, EspressoType targetType,
327328
@Cached InstanceOf.Dynamic instanceOf) throws UnsupportedTypeException {
328-
if (StaticObject.isNull(value) || instanceOf.execute(value.getKlass(), targetType.getRawType())) {
329-
return value; // pass through, NULL coercion not needed.
329+
Klass rawType = targetType.getRawType();
330+
if (StaticObject.isNull(value) || instanceOf.execute(value.getKlass(), rawType)) {
331+
return value;
332+
}
333+
try {
334+
Meta meta = getMeta();
335+
if (rawType == meta.java_lang_Double && EspressoInterop.fitsInDouble(value)) {
336+
return meta.boxDouble(EspressoInterop.asDouble(value));
337+
}
338+
if (rawType == meta.java_lang_Float && EspressoInterop.fitsInFloat(value)) {
339+
return meta.boxFloat(EspressoInterop.asFloat(value));
340+
}
341+
if (rawType == meta.java_lang_Long && EspressoInterop.fitsInLong(value)) {
342+
return meta.boxLong(EspressoInterop.asLong(value));
343+
}
344+
if (rawType == meta.java_lang_Integer && EspressoInterop.fitsInInt(value)) {
345+
return meta.boxInteger(EspressoInterop.asInt(value));
346+
}
347+
if (rawType == meta.java_lang_Short && EspressoInterop.fitsInShort(value)) {
348+
return meta.boxShort(EspressoInterop.asShort(value));
349+
}
350+
if (rawType == meta.java_lang_Byte && EspressoInterop.fitsInByte(value)) {
351+
return meta.boxByte(EspressoInterop.asByte(value));
352+
}
353+
} catch (UnsupportedMessageException ex) {
354+
CompilerDirectives.transferToInterpreterAndInvalidate();
355+
throw EspressoError.shouldNotReachHere("Contract violation: if fitsIn* returns true, as* must succeed.");
330356
}
331357
throw UnsupportedTypeException.create(new Object[]{value}, EspressoError.cat("Cannot cast ", value, " to ", targetType.getRawType().getTypeAsString()));
332358
}
@@ -498,6 +524,10 @@ public static StaticObject doGeneric(Object value, EspressoType targetType,
498524
if (result != null) {
499525
return result;
500526
}
527+
// no generic conversion to abstract target types allowed
528+
if (targetType.getRawType().isAbstract()) {
529+
throw UnsupportedTypeException.create(new Object[]{value}, targetType.getRawType().getTypeAsString());
530+
}
501531
if (targetType instanceof ObjectKlass rawType) {
502532
noConverterProfile.enter(node);
503533
checkHasAllFieldsOrThrow(value, rawType, interop, meta);
@@ -2609,6 +2639,10 @@ static StaticObject doForeignWrapper(Object value,
26092639
if (result != null) {
26102640
return result;
26112641
}
2642+
// no generic conversion to abstract target types allowed
2643+
if (target.getRawType().isAbstract()) {
2644+
throw UnsupportedTypeException.create(new Object[]{value}, target.getRawType().getTypeAsString());
2645+
}
26122646
noConverterProfile.enter(node);
26132647
checkHasAllFieldsOrThrow(value, (ObjectKlass) target.getRawType(), interop, context.getMeta());
26142648
return StaticObject.createForeign(EspressoLanguage.get(node), target.getRawType(), value, interop);

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/dispatch/staticobject/EspressoInterop.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,14 @@ public static Meta getMeta() {
100100
}
101101

102102
@ExportMessage
103-
static boolean isBoolean(StaticObject receiver) {
103+
public static boolean isBoolean(StaticObject receiver) {
104104
receiver.checkNotForeign();
105105
assert !isNull(receiver) : "Null espresso object should be dispatched to BaseInterop";
106106
return receiver.getKlass() == receiver.getKlass().getMeta().java_lang_Boolean;
107107
}
108108

109109
@ExportMessage
110-
static boolean asBoolean(StaticObject receiver) throws UnsupportedMessageException {
110+
public static boolean asBoolean(StaticObject receiver) throws UnsupportedMessageException {
111111
receiver.checkNotForeign();
112112
if (!isBoolean(receiver)) {
113113
throw UnsupportedMessageException.create();
@@ -128,7 +128,7 @@ static boolean isNumber(StaticObject receiver) {
128128
}
129129

130130
@ExportMessage
131-
static boolean fitsInByte(StaticObject receiver) {
131+
public static boolean fitsInByte(StaticObject receiver) {
132132
receiver.checkNotForeign();
133133
if (isNull(receiver)) {
134134
return false;
@@ -163,7 +163,7 @@ static boolean fitsInByte(StaticObject receiver) {
163163
}
164164

165165
@ExportMessage
166-
static boolean fitsInShort(StaticObject receiver) {
166+
public static boolean fitsInShort(StaticObject receiver) {
167167
receiver.checkNotForeign();
168168
if (isNull(receiver)) {
169169
return false;
@@ -194,7 +194,7 @@ static boolean fitsInShort(StaticObject receiver) {
194194
}
195195

196196
@ExportMessage
197-
static boolean fitsInInt(StaticObject receiver) {
197+
public static boolean fitsInInt(StaticObject receiver) {
198198
receiver.checkNotForeign();
199199
if (isNull(receiver)) {
200200
return false;
@@ -221,7 +221,7 @@ static boolean fitsInInt(StaticObject receiver) {
221221
}
222222

223223
@ExportMessage
224-
static boolean fitsInLong(StaticObject receiver) {
224+
public static boolean fitsInLong(StaticObject receiver) {
225225
receiver.checkNotForeign();
226226
if (isNull(receiver)) {
227227
return false;
@@ -244,7 +244,7 @@ static boolean fitsInLong(StaticObject receiver) {
244244
}
245245

246246
@ExportMessage
247-
static boolean fitsInFloat(StaticObject receiver) {
247+
public static boolean fitsInFloat(StaticObject receiver) {
248248
receiver.checkNotForeign();
249249
if (isNull(receiver)) {
250250
return false;
@@ -278,7 +278,7 @@ static boolean fitsInFloat(StaticObject receiver) {
278278
}
279279

280280
@ExportMessage
281-
static boolean fitsInDouble(StaticObject receiver) {
281+
public static boolean fitsInDouble(StaticObject receiver) {
282282
receiver.checkNotForeign();
283283
if (isNull(receiver)) {
284284
return false;
@@ -349,7 +349,7 @@ private static Number readNumberValue(StaticObject receiver) throws UnsupportedM
349349
}
350350

351351
@ExportMessage
352-
static byte asByte(StaticObject receiver) throws UnsupportedMessageException {
352+
public static byte asByte(StaticObject receiver) throws UnsupportedMessageException {
353353
receiver.checkNotForeign();
354354
if (!fitsInByte(receiver)) {
355355
CompilerDirectives.transferToInterpreter();
@@ -359,7 +359,7 @@ static byte asByte(StaticObject receiver) throws UnsupportedMessageException {
359359
}
360360

361361
@ExportMessage
362-
static short asShort(StaticObject receiver) throws UnsupportedMessageException {
362+
public static short asShort(StaticObject receiver) throws UnsupportedMessageException {
363363
receiver.checkNotForeign();
364364
if (!fitsInShort(receiver)) {
365365
CompilerDirectives.transferToInterpreter();
@@ -369,7 +369,7 @@ static short asShort(StaticObject receiver) throws UnsupportedMessageException {
369369
}
370370

371371
@ExportMessage
372-
static int asInt(StaticObject receiver) throws UnsupportedMessageException {
372+
public static int asInt(StaticObject receiver) throws UnsupportedMessageException {
373373
receiver.checkNotForeign();
374374
if (!fitsInInt(receiver)) {
375375
CompilerDirectives.transferToInterpreter();
@@ -379,7 +379,7 @@ static int asInt(StaticObject receiver) throws UnsupportedMessageException {
379379
}
380380

381381
@ExportMessage
382-
static long asLong(StaticObject receiver) throws UnsupportedMessageException {
382+
public static long asLong(StaticObject receiver) throws UnsupportedMessageException {
383383
receiver.checkNotForeign();
384384
if (!fitsInLong(receiver)) {
385385
CompilerDirectives.transferToInterpreter();
@@ -389,7 +389,7 @@ static long asLong(StaticObject receiver) throws UnsupportedMessageException {
389389
}
390390

391391
@ExportMessage
392-
static float asFloat(StaticObject receiver) throws UnsupportedMessageException {
392+
public static float asFloat(StaticObject receiver) throws UnsupportedMessageException {
393393
receiver.checkNotForeign();
394394
if (!fitsInFloat(receiver)) {
395395
CompilerDirectives.transferToInterpreter();
@@ -399,7 +399,7 @@ static float asFloat(StaticObject receiver) throws UnsupportedMessageException {
399399
}
400400

401401
@ExportMessage
402-
static double asDouble(StaticObject receiver) throws UnsupportedMessageException {
402+
public static double asDouble(StaticObject receiver) throws UnsupportedMessageException {
403403
receiver.checkNotForeign();
404404
if (!fitsInDouble(receiver)) {
405405
CompilerDirectives.transferToInterpreter();

0 commit comments

Comments
 (0)