Skip to content

Commit 42c9c49

Browse files
committed
[GR-27762] Fix unwrapping PExceptions from interop
PullRequest: graalpython/1426
2 parents 873be12 + 49b1eb4 commit 42c9c49

File tree

8 files changed

+65
-26
lines changed

8 files changed

+65
-26
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/interop/InteropLibraryTest.java

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,27 @@
4040
*/
4141
package com.oracle.graal.python.test.interop;
4242

43-
import org.junit.After;
44-
import org.junit.Before;
45-
import org.junit.Test;
46-
import static org.junit.Assert.assertFalse;
4743
import static org.junit.Assert.assertEquals;
44+
import static org.junit.Assert.assertFalse;
45+
import static org.junit.Assert.assertNotEquals;
4846
import static org.junit.Assert.assertTrue;
47+
import static org.junit.Assert.fail;
48+
49+
import java.util.Arrays;
50+
import java.util.Iterator;
51+
import java.util.List;
4952

5053
import org.graalvm.polyglot.Context;
5154
import org.graalvm.polyglot.Context.Builder;
55+
import org.graalvm.polyglot.PolyglotException;
5256
import org.graalvm.polyglot.Value;
5357
import org.graalvm.polyglot.proxy.ProxyArray;
58+
import org.junit.After;
59+
import org.junit.Before;
60+
import org.junit.Test;
5461

5562
import com.oracle.graal.python.test.PythonTests;
5663

57-
import java.util.Arrays;
58-
import java.util.Iterator;
59-
import java.util.List;
60-
6164
public class InteropLibraryTest extends PythonTests {
6265
private Context context;
6366

@@ -165,6 +168,28 @@ public void testForItemInLazyArray() {
165168
assertEquals(list.size() * 3, tripples.getArraySize());
166169
}
167170

171+
@Test
172+
public void testException() {
173+
try {
174+
context.eval("python", "1/0");
175+
} catch (PolyglotException e) {
176+
Value exception = e.getGuestObject();
177+
assertTrue(exception.isException());
178+
Value clazz = exception.getMetaObject();
179+
assertTrue(clazz.isMetaObject());
180+
assertEquals("ZeroDivisionError", clazz.getMetaSimpleName());
181+
assertTrue(exception.hasMember("args"));
182+
Value args = exception.getMember("args");
183+
assertTrue(args.hasArrayElements());
184+
assertEquals(1, args.getArraySize());
185+
assertEquals("division by zero", args.getArrayElement(0).asString());
186+
// This excercises isIdenticalOrUndefined message internally
187+
assertNotEquals(exception, args);
188+
return;
189+
}
190+
fail("didn't throw exception");
191+
}
192+
168193
private static final class LazyArray implements ProxyArray {
169194

170195
private final Iterator<?> it;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.oracle.graal.python.nodes.ErrorMessages;
3939
import com.oracle.graal.python.nodes.PRaiseNode;
4040
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
41+
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
4142
import com.oracle.graal.python.runtime.PythonContext;
4243
import com.oracle.truffle.api.CompilerAsserts;
4344
import com.oracle.truffle.api.CompilerDirectives;
@@ -618,8 +619,9 @@ static boolean isMetaObject(@SuppressWarnings("unused") PythonBuiltinClassType s
618619
@ExportMessage
619620
static boolean isMetaInstance(PythonBuiltinClassType self, Object instance,
620621
@CachedLibrary(limit = "3") PythonObjectLibrary lib,
622+
@Cached PForeignToPTypeNode convert,
621623
@Cached IsSubtypeNode isSubtype) {
622-
return isSubtype.execute(lib.getLazyPythonClass(instance), self);
624+
return isSubtype.execute(lib.getLazyPythonClass(convert.executeConvert(instance)), self);
623625
}
624626

625627
@ExportMessage

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/PythonAbstractObject.java

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -235,16 +235,16 @@ private boolean isAbstractMapping(PythonObjectLibrary thisLib) {
235235

236236
@ExportMessage
237237
public void writeMember(String key, Object value,
238-
@Exclusive @Cached PInteropSubscriptAssignNode setItemNode,
238+
@Shared("setItemNode") @Cached PInteropSubscriptAssignNode setItemNode,
239239
@CachedLibrary("this") PythonObjectLibrary dataModelLibrary,
240240
@Exclusive @Cached KeyForAttributeAccess getAttributeKey,
241241
@Exclusive @Cached KeyForItemAccess getItemKey,
242-
@Cached PInteropSetAttributeNode writeNode,
242+
@Cached PInteropSetAttributeNode setAttributeNode,
243243
@Shared("attributeErrorProfile") @Cached IsBuiltinClassProfile attrErrorProfile) throws UnsupportedMessageException, UnknownIdentifierException {
244244
try {
245245
String attrKey = getAttributeKey.execute(key);
246246
if (attrKey != null) {
247-
writeNode.execute(this, attrKey, value);
247+
setAttributeNode.execute(this, attrKey, value);
248248
return;
249249
}
250250

@@ -256,14 +256,14 @@ public void writeMember(String key, Object value,
256256

257257
if (this instanceof PythonObject) {
258258
if (objectHasAttribute(this, key)) {
259-
writeNode.execute(this, key, value);
259+
setAttributeNode.execute(this, key, value);
260260
return;
261261
}
262262
}
263263
if (isAbstractMapping(dataModelLibrary)) {
264264
setItemNode.execute(this, key, value);
265265
} else {
266-
writeNode.execute(this, key, value);
266+
setAttributeNode.execute(this, key, value);
267267
}
268268
} catch (PException e) {
269269
e.expectAttributeError(attrErrorProfile);
@@ -347,7 +347,7 @@ public Object readArrayElement(long key,
347347
@ExportMessage
348348
public void writeArrayElement(long key, Object value,
349349
@CachedLibrary("this") PythonObjectLibrary dataModelLibrary,
350-
@Exclusive @Cached PInteropSubscriptAssignNode setItemNode) throws UnsupportedMessageException, InvalidArrayIndexException {
350+
@Shared("setItemNode") @Cached PInteropSubscriptAssignNode setItemNode) throws UnsupportedMessageException, InvalidArrayIndexException {
351351
if (dataModelLibrary.isSequence(this)) {
352352
try {
353353
setItemNode.execute(this, key, value);
@@ -1867,13 +1867,14 @@ public abstract static class PInteropSubscriptAssignNode extends Node {
18671867

18681868
@Specialization
18691869
static void doSpecialObject(PythonAbstractObject primary, Object key, Object value,
1870+
@Cached PForeignToPTypeNode convert,
18701871
@Cached PInteropGetAttributeNode getAttributeNode,
18711872
@Cached CallBinaryMethodNode callSetItemNode,
18721873
@Cached ConditionProfile profile) throws UnsupportedMessageException {
18731874

18741875
Object attrSetitem = getAttributeNode.execute(primary, __SETITEM__);
18751876
if (profile.profile(attrSetitem != PNone.NO_VALUE)) {
1876-
callSetItemNode.executeObject(attrSetitem, key, value);
1877+
callSetItemNode.executeObject(attrSetitem, key, convert.executeConvert(value));
18771878
} else {
18781879
throw UnsupportedMessageException.create();
18791880
}
@@ -1890,15 +1891,16 @@ public abstract static class PInteropSetAttributeNode extends Node {
18901891
public abstract void execute(Object primary, String attrName, Object value) throws UnsupportedMessageException, UnknownIdentifierException;
18911892

18921893
@Specialization
1893-
public void doSpecialObject(PythonAbstractObject primary, String attrName, Object value,
1894+
public static void doSpecialObject(PythonAbstractObject primary, String attrName, Object value,
1895+
@Cached PForeignToPTypeNode convert,
18941896
@Cached LookupInheritedAttributeNode.Dynamic lookupSetAttrNode,
18951897
@Cached CallTernaryMethodNode callSetAttrNode,
18961898
@Cached ConditionProfile profile,
18971899
@Cached IsBuiltinClassProfile attrErrorProfile) throws UnsupportedMessageException, UnknownIdentifierException {
1898-
Object attrGetattribute = lookupSetAttrNode.execute(primary, SpecialMethodNames.__SETATTR__);
1899-
if (profile.profile(attrGetattribute != PNone.NO_VALUE)) {
1900+
Object attrSetattr = lookupSetAttrNode.execute(primary, SpecialMethodNames.__SETATTR__);
1901+
if (profile.profile(attrSetattr != PNone.NO_VALUE)) {
19001902
try {
1901-
callSetAttrNode.execute(null, attrGetattribute, primary, attrName, value);
1903+
callSetAttrNode.execute(null, attrSetattr, primary, attrName, convert.executeConvert(value));
19021904
} catch (PException e) {
19031905
e.expectAttributeError(attrErrorProfile);
19041906
// TODO(fa) not accurate; distinguish between read-only and non-existing
@@ -2086,9 +2088,11 @@ public static int systemHashCode(Object value) {
20862088
}
20872089

20882090
@ExportMessage
2089-
public TriState isIdenticalOrUndefined(Object other,
2091+
public TriState isIdenticalOrUndefined(Object otherInterop,
2092+
@Cached PForeignToPTypeNode convert,
20902093
@CachedLibrary(limit = "3") InteropLibrary otherLib,
20912094
@CachedLibrary("this") PythonObjectLibrary objectLib) {
2095+
Object other = convert.executeConvert(otherInterop);
20922096
if (this == other) {
20932097
return TriState.TRUE;
20942098
} else if (otherLib.hasIdentity(other)) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import com.oracle.graal.python.nodes.ErrorMessages;
6868
import com.oracle.graal.python.nodes.PRaiseNode;
6969
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
70+
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
7071
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
7172
import com.oracle.truffle.api.Assumption;
7273
import com.oracle.truffle.api.CompilerAsserts;
@@ -319,11 +320,12 @@ boolean isMetaObject(
319320
boolean isMetaInstance(Object instance,
320321
@Shared("isType") @Cached TypeNodes.IsTypeNode isType,
321322
@CachedLibrary(limit = "3") PythonObjectLibrary plib,
323+
@Cached PForeignToPTypeNode convert,
322324
@Cached IsSubtypeNode isSubtype) throws UnsupportedMessageException {
323325
if (!isType.execute(this)) {
324326
throw UnsupportedMessageException.create();
325327
}
326-
return isSubtype.execute(plib.getLazyPythonClass(instance), this);
328+
return isSubtype.execute(plib.getLazyPythonClass(convert.executeConvert(instance)), this);
327329
}
328330

329331
@ExportMessage

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/PList.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
3030
import com.oracle.graal.python.builtins.objects.ints.PInt;
3131
import com.oracle.graal.python.nodes.ErrorMessages;
32+
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
3233
import com.oracle.graal.python.nodes.literal.ListLiteralNode;
3334
import com.oracle.graal.python.runtime.exception.PException;
3435
import com.oracle.graal.python.runtime.sequence.PSequence;
@@ -187,9 +188,10 @@ public boolean isArrayElementRemovable(long index,
187188

188189
@ExportMessage
189190
public void writeArrayElement(long index, Object value,
191+
@Cached PForeignToPTypeNode convert,
190192
@Cached.Exclusive @Cached SequenceStorageNodes.SetItemScalarNode setItem) throws InvalidArrayIndexException {
191193
try {
192-
setItem.execute(store, PInt.intValueExact(index), value);
194+
setItem.execute(store, PInt.intValueExact(index), convert.executeConvert(value));
193195
} catch (OverflowException e) {
194196
CompilerDirectives.transferToInterpreterAndInvalidate();
195197
throw InvalidArrayIndexException.create(index);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
3434
import com.oracle.graal.python.nodes.ErrorMessages;
3535
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
36+
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
3637
import com.oracle.truffle.api.CompilerAsserts;
3738
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
3839
import com.oracle.truffle.api.dsl.Cached;
@@ -87,8 +88,9 @@ boolean isMetaObject() {
8788
@SuppressWarnings("static-method")
8889
boolean isMetaInstance(Object instance,
8990
@CachedLibrary(limit = "3") PythonObjectLibrary plib,
91+
@Cached PForeignToPTypeNode convert,
9092
@Cached IsSubtypeNode isSubtype) {
91-
return isSubtype.execute(plib.getLazyPythonClass(instance), this);
93+
return isSubtype.execute(plib.getLazyPythonClass(convert.executeConvert(instance)), this);
9294
}
9395

9496
@ExportMessage

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
3030
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode;
3131
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
32+
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
3233
import com.oracle.truffle.api.dsl.Cached;
3334
import com.oracle.truffle.api.dsl.Cached.Shared;
3435
import com.oracle.truffle.api.interop.InteropLibrary;
@@ -64,8 +65,9 @@ boolean isMetaObject() {
6465
@ExportMessage
6566
boolean isMetaInstance(Object instance,
6667
@CachedLibrary(limit = "3") PythonObjectLibrary plib,
68+
@Cached PForeignToPTypeNode convert,
6769
@Cached IsSubtypeNode isSubtype) {
68-
return isSubtype.execute(plib.getLazyPythonClass(instance), this);
70+
return isSubtype.execute(plib.getLazyPythonClass(convert.executeConvert(instance)), this);
6971
}
7072

7173
@ExportMessage

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/interop/PForeignToPTypeNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public abstract class PForeignToPTypeNode extends Node {
6060
public abstract Object executeConvert(Object value);
6161

6262
protected static boolean isOtherClass(Class<?> clazz) {
63-
return !(clazz == Byte.class || clazz == Short.class || clazz == Float.class || clazz == Character.class);
63+
return !(clazz == Byte.class || clazz == Short.class || clazz == Float.class || clazz == Character.class || clazz == PException.class);
6464
}
6565

6666
@Specialization(guards = {"value.getClass() == cachedClass", "isOtherClass(cachedClass)"}, limit = "1")

0 commit comments

Comments
 (0)