|
41 | 41 | package com.oracle.graal.python.builtins.objects;
|
42 | 42 |
|
43 | 43 | import static com.oracle.graal.python.builtins.PythonBuiltinClassType.AttributeError;
|
| 44 | +import static com.oracle.graal.python.nodes.SpecialMethodNames.__BOOL__; |
44 | 45 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__CALL__;
|
45 | 46 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__DELETE__;
|
46 | 47 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__DELITEM__;
|
|
53 | 54 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__HASH__;
|
54 | 55 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__INDEX__;
|
55 | 56 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__ITER__;
|
| 57 | +import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__; |
56 | 58 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEXT__;
|
57 | 59 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__SETITEM__;
|
58 | 60 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__SET__;
|
|
107 | 109 | import com.oracle.graal.python.nodes.object.GetClassNode;
|
108 | 110 | import com.oracle.graal.python.nodes.object.GetLazyClassNode;
|
109 | 111 | import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
|
| 112 | +import com.oracle.graal.python.nodes.util.CastToJavaBooleanNode; |
110 | 113 | import com.oracle.graal.python.nodes.util.CastToJavaIntNode;
|
111 | 114 | import com.oracle.graal.python.nodes.util.CastToJavaLongNode;
|
112 | 115 | import com.oracle.graal.python.runtime.exception.PException;
|
@@ -377,7 +380,7 @@ private boolean isInBounds(LookupAndCallUnaryDynamicNode callLenNode, PInteropSu
|
377 | 380 | }
|
378 | 381 |
|
379 | 382 | private long getArraySizeSafe(LookupAndCallUnaryDynamicNode callLenNode) {
|
380 |
| - Object lenObj = callLenNode.executeObject(this, SpecialMethodNames.__LEN__); |
| 383 | + Object lenObj = callLenNode.executeObject(this, __LEN__); |
381 | 384 | if (lenObj instanceof Number) {
|
382 | 385 | return ((Number) lenObj).longValue();
|
383 | 386 | } else if (lenObj instanceof PInt) {
|
@@ -599,7 +602,7 @@ public int lengthWithState(ThreadState state,
|
599 | 602 | @Exclusive @Cached CallNode callNode,
|
600 | 603 | @Exclusive @Cached PRaiseNode raiseNode,
|
601 | 604 | @Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib) {
|
602 |
| - Object lenFunc = getLenNode.execute(this, SpecialMethodNames.__LEN__); |
| 605 | + Object lenFunc = getLenNode.execute(this, __LEN__); |
603 | 606 | if (hasLen.profile(lenFunc != PNone.NO_VALUE)) {
|
604 | 607 | Object lenResult;
|
605 | 608 | int len;
|
@@ -635,8 +638,8 @@ public boolean isSequenceType(
|
635 | 638 | @Shared("getItemProfile") @Cached("createBinaryProfile()") ConditionProfile getItemProfile) {
|
636 | 639 | if (isLazyClass.profile(this instanceof LazyPythonClass)) {
|
637 | 640 | LazyPythonClass type = (LazyPythonClass) this; // guaranteed to succeed because of guard
|
638 |
| - if (lenProfile.profile(hasLenNode.execute(type, SpecialMethodNames.__LEN__) != PNone.NO_VALUE)) { |
639 |
| - return getItemProfile.profile(hasGetItemNode.execute(type, SpecialMethodNames.__GETITEM__) != PNone.NO_VALUE); |
| 641 | + if (lenProfile.profile(hasLenNode.execute(type, __LEN__) != PNone.NO_VALUE)) { |
| 642 | + return getItemProfile.profile(hasGetItemNode.execute(type, __GETITEM__) != PNone.NO_VALUE); |
640 | 643 | }
|
641 | 644 | }
|
642 | 645 | return false;
|
@@ -694,6 +697,50 @@ public final boolean isCallable(@Exclusive @Cached LookupInheritedAttributeNode.
|
694 | 697 | return PGuards.isCallable(call);
|
695 | 698 | }
|
696 | 699 |
|
| 700 | + @ExportMessage |
| 701 | + public boolean isTrueWithState(ThreadState state, |
| 702 | + @Exclusive @Cached("createBinaryProfile()") ConditionProfile gotState, |
| 703 | + @Exclusive @Cached("createBinaryProfile()") ConditionProfile hasBool, |
| 704 | + @Exclusive @Cached("createBinaryProfile()") ConditionProfile hasLen, |
| 705 | + @Exclusive @Cached LookupInheritedAttributeNode.Dynamic lookupAttrs, |
| 706 | + @Exclusive @Cached CastToJavaBooleanNode castToBoolean, |
| 707 | + @Exclusive @Cached PRaiseNode raiseNode, |
| 708 | + @Exclusive @CachedLibrary("this") PythonObjectLibrary lib, |
| 709 | + @Exclusive @Cached CallNode callNode) { |
| 710 | + // n.b.: CPython's early returns for PyTrue/PyFalse/PyNone are handled |
| 711 | + // in the message impls in PNone and PInt |
| 712 | + Object boolAttr = lookupAttrs.execute(this, __BOOL__); |
| 713 | + if (hasBool.profile(boolAttr != PNone.NO_VALUE)) { |
| 714 | + // this inlines the work done in sq_nb_bool when __bool__ is used. |
| 715 | + // when __len__ would be used, this is the same as the branch below |
| 716 | + // calling __len__ |
| 717 | + Object result; |
| 718 | + if (gotState.profile(state == null)) { |
| 719 | + result = callNode.execute(boolAttr, this); |
| 720 | + } else { |
| 721 | + result = callNode.execute(PArguments.frameForCall(state), boolAttr, this); |
| 722 | + } |
| 723 | + try { |
| 724 | + return castToBoolean.execute(result); |
| 725 | + } catch (CastToJavaBooleanNode.CannotCastException e) { |
| 726 | + // cast node will act as a branch profile already for the compiler |
| 727 | + throw raiseNode.raise(PythonBuiltinClassType.TypeError, "__bool__ should return bool, returned %p", result); |
| 728 | + } |
| 729 | + } else { |
| 730 | + Object lenAttr = lookupAttrs.execute(this, __LEN__); |
| 731 | + if (hasLen.profile(lenAttr != PNone.NO_VALUE)) { |
| 732 | + if (gotState.profile(state == null)) { |
| 733 | + return lib.length(this) > 0; |
| 734 | + } else { |
| 735 | + return lib.lengthWithState(this, state) > 0; |
| 736 | + } |
| 737 | + } else { |
| 738 | + // like CPython, anything else is true-ish |
| 739 | + return true; |
| 740 | + } |
| 741 | + } |
| 742 | + } |
| 743 | + |
697 | 744 | @ExportMessage
|
698 | 745 | public final boolean isHashable(@Exclusive @Cached LookupInheritedAttributeNode.Dynamic lookupHashAttributeNode,
|
699 | 746 | @CachedLibrary(limit = "1") PythonObjectLibrary dataModelLibrary) {
|
@@ -1288,7 +1335,7 @@ Object doSpecialObject(Object primary, Object index,
|
1288 | 1335 | @Cached CallNode callGetItemNode,
|
1289 | 1336 | @Cached PRaiseNode raiseNode,
|
1290 | 1337 | @Cached("createBinaryProfile()") ConditionProfile profile) {
|
1291 |
| - Object attrGetItem = lookupGetItemNode.execute(primary, SpecialMethodNames.__GETITEM__); |
| 1338 | + Object attrGetItem = lookupGetItemNode.execute(primary, __GETITEM__); |
1292 | 1339 | if (profile.profile(attrGetItem == PNone.NO_VALUE)) {
|
1293 | 1340 | throw raiseNode.raise(PythonBuiltinClassType.TypeError, "'%p' object is not subscriptable", primary);
|
1294 | 1341 | }
|
|
0 commit comments