From 166a709ea221043862138c212c61b2d48a83b692 Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Fri, 14 Jun 2024 08:44:32 +0200 Subject: [PATCH] make sure we attempt type converters for not otherwise directly mapped target types (cherry picked from commit f4b024a998e8abd9ab165cbffaa75ba633f1de38) --- .../nodes/interop/ToEspressoNode.java | 7 + .../espresso/nodes/interop/ToReference.java | 127 +++++++++++++----- 2 files changed, 98 insertions(+), 36 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToEspressoNode.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToEspressoNode.java index fbd491469983..27ac5cf6a927 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToEspressoNode.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToEspressoNode.java @@ -264,6 +264,9 @@ public Object doInternalTypeConverter(Object value, Klass targetType, public Object doGeneric(Object value, Klass targetType, @Bind("getMeta()") Meta meta, @CachedLibrary(limit = "LIMIT") InteropLibrary interop, + @Cached LookupTypeConverterNode lookupTypeConverterNode, + @Cached LookupInternalTypeConverterNode lookupInternalTypeConverterNode, + @Cached ToReference.DynamicToReference converterToEspresso, @Cached InlinedBranchProfile unknownProfile) throws UnsupportedTypeException { ToEspressoNode uncachedToEspresso = getUncachedToEspresso(targetType, meta); if (uncachedToEspresso != null) { @@ -272,6 +275,10 @@ public Object doGeneric(Object value, Klass targetType, unknownProfile.enter(this); // hit the unknown type case, so inline generic handling for that here if (targetType instanceof ObjectKlass) { + StaticObject result = ToReference.tryConverterForUnknownTarget(value, interop, lookupTypeConverterNode, lookupInternalTypeConverterNode, converterToEspresso, meta); + if (result != null) { + return result; + } try { checkHasAllFieldsOrThrow(value, (ObjectKlass) targetType, interop, getMeta()); return StaticObject.createForeign(getLanguage(), targetType, value, interop); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToReference.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToReference.java index d442e297f0e4..c3ae733c7287 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToReference.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToReference.java @@ -454,6 +454,10 @@ public StaticObject doInternalTypeConverter(Object value, @SuppressWarnings("unu public StaticObject doGeneric(Object value, Klass targetType, @Bind("getMeta()") Meta meta, @CachedLibrary(limit = "LIMIT") InteropLibrary interop, + @Cached LookupTypeConverterNode lookupTypeConverterNode, + @Cached LookupInternalTypeConverterNode lookupInternalTypeConverterNode, + @Cached ToReference.DynamicToReference converterToEspresso, + @Cached InlinedBranchProfile noConverterProfile, @Cached InlinedBranchProfile unknownProfile) throws UnsupportedTypeException { ToReference uncachedToReference = getUncachedToReference(targetType, meta); if (uncachedToReference != null) { @@ -462,7 +466,12 @@ public StaticObject doGeneric(Object value, Klass targetType, unknownProfile.enter(this); // hit the unknown type case, so inline generic handling for that here if (targetType instanceof ObjectKlass) { + StaticObject result = ToReference.tryConverterForUnknownTarget(value, interop, lookupTypeConverterNode, lookupInternalTypeConverterNode, converterToEspresso, meta); + if (result != null) { + return result; + } try { + noConverterProfile.enter(this); checkHasAllFieldsOrThrow(value, (ObjectKlass) targetType, interop, getMeta()); return StaticObject.createForeign(getLanguage(), targetType, value, interop); } catch (ClassCastException e) { @@ -1237,45 +1246,78 @@ StaticObject doForeignObject(Object value, StaticObject doUnsupportedType(Object value) throws UnsupportedTypeException { throw UnsupportedTypeException.create(new Object[]{value}, "java.lang.Object"); } + } - private StaticObject tryTypeConversion(Object value, InteropLibrary interop, LookupProxyKlassNode lookupProxyKlassNode, LookupTypeConverterNode lookupTypeConverterNode, - LookupInternalTypeConverterNode lookupInternalTypeConverterNode, - ToReference.DynamicToReference converterToEspresso, BranchProfile errorProfile, Meta meta) throws UnsupportedTypeException { - try { - Object metaObject = getMetaObjectOrThrow(value, interop); - String metaName = getMetaName(metaObject, interop); - - // check if there's a specific type mapping available - PolyglotTypeMappings.InternalTypeConverter internalConverter = lookupInternalTypeConverterNode.execute(metaName); - if (internalConverter != null) { - return internalConverter.convertInternal(interop, value, meta, converterToEspresso); - } else { - PolyglotTypeMappings.TypeConverter converter = lookupTypeConverterNode.execute(metaName); - if (converter != null) { - if (interop.isException(value)) { - return (StaticObject) converter.convert(StaticObject.createForeignException(getContext(), value, interop)); - } else { - return (StaticObject) converter.convert(StaticObject.createForeign(getLanguage(), meta.java_lang_Object, value, interop)); - } - } + static StaticObject tryTypeConversion(Object value, InteropLibrary interop, LookupProxyKlassNode lookupProxyKlassNode, LookupTypeConverterNode lookupTypeConverterNode, + LookupInternalTypeConverterNode lookupInternalTypeConverterNode, + ToReference.DynamicToReference converterToEspresso, BranchProfile errorProfile, Meta meta) throws UnsupportedTypeException { + try { + Object metaObject = getMetaObjectOrThrow(value, interop); + String metaName = getMetaName(metaObject, interop); - // check if foreign exception + // check if there's a specific type mapping available + PolyglotTypeMappings.InternalTypeConverter internalConverter = lookupInternalTypeConverterNode.execute(metaName); + if (internalConverter != null) { + return internalConverter.convertInternal(interop, value, meta, converterToEspresso); + } else { + PolyglotTypeMappings.TypeConverter converter = lookupTypeConverterNode.execute(metaName); + if (converter != null) { if (interop.isException(value)) { - return StaticObject.createForeignException(getContext(), value, interop); + return (StaticObject) converter.convert(StaticObject.createForeignException(converterToEspresso.getContext(), value, interop)); + } else { + return (StaticObject) converter.convert(StaticObject.createForeign(converterToEspresso.getLanguage(), meta.java_lang_Object, value, interop)); } - // see if a generated proxy can be used for interface mapped types - WrappedProxyKlass proxyKlass = lookupProxyKlassNode.execute(metaObject, metaName, meta.java_lang_Object); - if (proxyKlass != null) { - return proxyKlass.createProxyInstance(value, getLanguage(), interop); + } + + // check if foreign exception + if (interop.isException(value)) { + return StaticObject.createForeignException(converterToEspresso.getContext(), value, interop); + } + // see if a generated proxy can be used for interface mapped types + WrappedProxyKlass proxyKlass = lookupProxyKlassNode.execute(metaObject, metaName, meta.java_lang_Object); + if (proxyKlass != null) { + return proxyKlass.createProxyInstance(value, converterToEspresso.getLanguage(), interop); + } + return StaticObject.createForeign(converterToEspresso.getLanguage(), meta.java_lang_Object, value, interop); + } + } catch (ClassCastException e) { + errorProfile.enter(); + throw UnsupportedTypeException.create(new Object[]{value}, + EspressoError.format("Could not cast foreign object to %s: due to: %s", meta.java_lang_Object.getNameAsString(), e.getMessage())); + } + } + + static StaticObject tryConverterForUnknownTarget(Object value, InteropLibrary interop, LookupTypeConverterNode lookupTypeConverterNode, + LookupInternalTypeConverterNode lookupInternalTypeConverterNode, + ToReference.DynamicToReference converterToEspresso, Meta meta) throws UnsupportedTypeException { + try { + Object metaObject = getMetaObjectOrThrow(value, interop); + String metaName = getMetaName(metaObject, interop); + + // check if there's a specific type mapping available + PolyglotTypeMappings.InternalTypeConverter internalConverter = lookupInternalTypeConverterNode.execute(metaName); + if (internalConverter != null) { + return internalConverter.convertInternal(interop, value, meta, converterToEspresso); + } else { + PolyglotTypeMappings.TypeConverter converter = lookupTypeConverterNode.execute(metaName); + // check if foreign exception + boolean isException = interop.isException(value); + StaticObject foreignWrapper = isException ? StaticObject.createForeignException(converterToEspresso.getContext(), value, interop) : null; + + if (converter != null) { + if (foreignWrapper == null) { + // not exception + foreignWrapper = StaticObject.createForeign(converterToEspresso.getLanguage(), meta.java_lang_Object, value, interop); } - return StaticObject.createForeign(getLanguage(), meta.java_lang_Object, value, interop); + return (StaticObject) converter.convert(foreignWrapper); } - } catch (ClassCastException e) { - errorProfile.enter(); - throw UnsupportedTypeException.create(new Object[]{value}, - EspressoError.format("Could not cast foreign object to %s: due to: %s", meta.java_lang_Object.getNameAsString(), e.getMessage())); + return foreignWrapper; + } + } catch (ClassCastException e) { + // fall through, since there was no converter available } + return null; } @NodeInfo(shortName = "j.l.String target type") @@ -2398,14 +2440,27 @@ public StaticObject doEspresso(StaticObject value) throws UnsupportedTypeExcepti StaticObject doForeignWrapper(Object value, @Cached.Shared("value") @CachedLibrary(limit = "LIMIT") InteropLibrary interop, @SuppressWarnings("unused") @Bind("getContext()") EspressoContext context, + @Cached LookupTypeConverterNode lookupTypeConverterNode, + @Cached LookupInternalTypeConverterNode lookupInternalTypeConverterNode, + @Cached ToReference.DynamicToReference converterToEspresso, + @Cached InlinedBranchProfile unknownProfile, + @Cached InlinedBranchProfile noConverterProfile, @Bind("getMeta()") Meta meta) throws UnsupportedTypeException { + ToReference uncachedToReference = getUncachedToReference(targetType, meta); + if (uncachedToReference != null) { + return uncachedToReference.execute(value); + } + unknownProfile.enter(this); + // hit the unknown type case, so inline generic handling for that here + StaticObject result = ToReference.tryConverterForUnknownTarget(value, interop, lookupTypeConverterNode, lookupInternalTypeConverterNode, converterToEspresso, meta); + if (result != null) { + return result; + } try { - if (targetType.isInterface()) { - throw UnsupportedTypeException.create(new Object[]{value}, targetType.getTypeAsString()); - } - checkHasAllFieldsOrThrow(value, targetType, interop, meta); + noConverterProfile.enter(this); + checkHasAllFieldsOrThrow(value, targetType, interop, getMeta()); return StaticObject.createForeign(getLanguage(), targetType, value, interop); - } catch (ClassCastException ex) { + } catch (ClassCastException e) { throw UnsupportedTypeException.create(new Object[]{value}, targetType.getTypeAsString()); } }