Skip to content

Commit 7b8393c

Browse files
committed
[GR-20143] Add isTrue Python object library message
PullRequest: graalpython/770
2 parents 7c192cc + 7e82daf commit 7b8393c

15 files changed

+306
-49
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixSubprocessModuleBuiltins.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -63,7 +63,6 @@
6363
import com.oracle.graal.python.builtins.objects.list.PList;
6464
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
6565
import com.oracle.graal.python.builtins.objects.str.PString;
66-
import com.oracle.graal.python.nodes.expression.CastToBooleanNode;
6766
import com.oracle.graal.python.nodes.expression.CastToListExpressionNode.CastToListNode;
6867
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
6968
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
@@ -235,13 +234,10 @@ int forkExecDefault(VirtualFrame frame, Object args, Object executable_list, Obj
235234
Object restore_signals, Object call_setsid, PNone preexec_fn,
236235
@Cached CastToListNode castArgs,
237236
@Cached CastToListNode castExecList,
238-
@Cached("createIfTrueNode()") CastToBooleanNode castCloseFds,
239237
@Cached CastToListNode castFdsToKeep,
240238
@Cached CastToJavaStringNode castCwd,
241239
@Cached CastToListNode castEnv,
242-
@CachedLibrary(limit = "3") PythonObjectLibrary lib,
243-
@Cached("createIfTrueNode()") CastToBooleanNode castRestoreSignals,
244-
@Cached("createIfTrueNode()") CastToBooleanNode castSetsid) {
240+
@CachedLibrary(limit = "3") PythonObjectLibrary lib) {
245241

246242
String actualCwd;
247243
if (cwd instanceof PNone) {
@@ -257,7 +253,8 @@ int forkExecDefault(VirtualFrame frame, Object args, Object executable_list, Obj
257253
actualEnv = castEnv.execute(frame, env);
258254
}
259255

260-
return forkExec(castArgs.execute(frame, args), castExecList.execute(frame, executable_list), castCloseFds.executeBoolean(frame, close_fds),
256+
return forkExec(castArgs.execute(frame, args), castExecList.execute(frame, executable_list),
257+
lib.isTrueWithState(close_fds, PArguments.getThreadState(frame)),
261258
castFdsToKeep.execute(frame, fdsToKeep), actualCwd, actualEnv,
262259
lib.asSizeWithState(p2cread, PArguments.getThreadState(frame)),
263260
lib.asSizeWithState(p2cwrite, PArguments.getThreadState(frame)),
@@ -267,7 +264,8 @@ int forkExecDefault(VirtualFrame frame, Object args, Object executable_list, Obj
267264
lib.asSizeWithState(errwrite, PArguments.getThreadState(frame)),
268265
lib.asSizeWithState(errpipe_read, PArguments.getThreadState(frame)),
269266
lib.asSizeWithState(errpipe_write, PArguments.getThreadState(frame)),
270-
castRestoreSignals.executeBoolean(frame, restore_signals), castSetsid.executeBoolean(frame, call_setsid), preexec_fn);
267+
lib.isTrueWithState(restore_signals, PArguments.getThreadState(frame)),
268+
lib.isTrueWithState(call_setsid, PArguments.getThreadState(frame)), preexec_fn);
271269
}
272270
}
273271
}

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -26,6 +26,7 @@
2626
package com.oracle.graal.python.builtins.objects;
2727

2828
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
29+
import com.oracle.graal.python.builtins.objects.function.PArguments.ThreadState;
2930
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
3031
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
3132
import com.oracle.truffle.api.CompilerAsserts;
@@ -65,4 +66,10 @@ static boolean isNull(@SuppressWarnings("unused") PNone self) {
6566
public LazyPythonClass getLazyPythonClass() {
6667
return PythonBuiltinClassType.PNone;
6768
}
69+
70+
@ExportMessage
71+
@SuppressWarnings("static-method")
72+
boolean isTrueWithState(@SuppressWarnings("unused") ThreadState state) {
73+
return false;
74+
}
6875
}

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

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.builtins.objects;
4242

4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.AttributeError;
44+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__BOOL__;
4445
import static com.oracle.graal.python.nodes.SpecialMethodNames.__CALL__;
4546
import static com.oracle.graal.python.nodes.SpecialMethodNames.__DELETE__;
4647
import static com.oracle.graal.python.nodes.SpecialMethodNames.__DELITEM__;
@@ -53,6 +54,7 @@
5354
import static com.oracle.graal.python.nodes.SpecialMethodNames.__HASH__;
5455
import static com.oracle.graal.python.nodes.SpecialMethodNames.__INDEX__;
5556
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ITER__;
57+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__;
5658
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEXT__;
5759
import static com.oracle.graal.python.nodes.SpecialMethodNames.__SETITEM__;
5860
import static com.oracle.graal.python.nodes.SpecialMethodNames.__SET__;
@@ -107,6 +109,7 @@
107109
import com.oracle.graal.python.nodes.object.GetClassNode;
108110
import com.oracle.graal.python.nodes.object.GetLazyClassNode;
109111
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
112+
import com.oracle.graal.python.nodes.util.CastToJavaBooleanNode;
110113
import com.oracle.graal.python.nodes.util.CastToJavaIntNode;
111114
import com.oracle.graal.python.nodes.util.CastToJavaLongNode;
112115
import com.oracle.graal.python.runtime.exception.PException;
@@ -377,7 +380,7 @@ private boolean isInBounds(LookupAndCallUnaryDynamicNode callLenNode, PInteropSu
377380
}
378381

379382
private long getArraySizeSafe(LookupAndCallUnaryDynamicNode callLenNode) {
380-
Object lenObj = callLenNode.executeObject(this, SpecialMethodNames.__LEN__);
383+
Object lenObj = callLenNode.executeObject(this, __LEN__);
381384
if (lenObj instanceof Number) {
382385
return ((Number) lenObj).longValue();
383386
} else if (lenObj instanceof PInt) {
@@ -599,7 +602,7 @@ public int lengthWithState(ThreadState state,
599602
@Exclusive @Cached CallNode callNode,
600603
@Exclusive @Cached PRaiseNode raiseNode,
601604
@Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib) {
602-
Object lenFunc = getLenNode.execute(this, SpecialMethodNames.__LEN__);
605+
Object lenFunc = getLenNode.execute(this, __LEN__);
603606
if (hasLen.profile(lenFunc != PNone.NO_VALUE)) {
604607
Object lenResult;
605608
int len;
@@ -635,8 +638,8 @@ public boolean isSequenceType(
635638
@Shared("getItemProfile") @Cached("createBinaryProfile()") ConditionProfile getItemProfile) {
636639
if (isLazyClass.profile(this instanceof LazyPythonClass)) {
637640
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);
640643
}
641644
}
642645
return false;
@@ -694,6 +697,50 @@ public final boolean isCallable(@Exclusive @Cached LookupInheritedAttributeNode.
694697
return PGuards.isCallable(call);
695698
}
696699

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+
697744
@ExportMessage
698745
public final boolean isHashable(@Exclusive @Cached LookupInheritedAttributeNode.Dynamic lookupHashAttributeNode,
699746
@CachedLibrary(limit = "1") PythonObjectLibrary dataModelLibrary) {
@@ -1288,7 +1335,7 @@ Object doSpecialObject(Object primary, Object index,
12881335
@Cached CallNode callGetItemNode,
12891336
@Cached PRaiseNode raiseNode,
12901337
@Cached("createBinaryProfile()") ConditionProfile profile) {
1291-
Object attrGetItem = lookupGetItemNode.execute(primary, SpecialMethodNames.__GETITEM__);
1338+
Object attrGetItem = lookupGetItemNode.execute(primary, __GETITEM__);
12921339
if (profile.profile(attrGetItem == PNone.NO_VALUE)) {
12931340
throw raiseNode.raise(PythonBuiltinClassType.TypeError, "'%p' object is not subscriptable", primary);
12941341
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
33
* Copyright (c) 2014, Regents of the University of California
44
*
55
* All rights reserved.
@@ -75,12 +75,12 @@
7575
import com.oracle.graal.python.builtins.objects.ints.PInt;
7676
import com.oracle.graal.python.builtins.objects.iterator.PForeignArrayIterator;
7777
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory;
78+
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
7879
import com.oracle.graal.python.nodes.PRaiseNode;
7980
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
8081
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
8182
import com.oracle.graal.python.nodes.expression.BinaryArithmetic;
8283
import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
83-
import com.oracle.graal.python.nodes.expression.CastToBooleanNode;
8484
import com.oracle.graal.python.nodes.expression.CastToListExpressionNode.CastToListNode;
8585
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
8686
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
@@ -120,25 +120,10 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
120120
@Builtin(name = __BOOL__, minNumOfPositionalArgs = 1)
121121
@GenerateNodeFactory
122122
abstract static class BoolNode extends PythonUnaryBuiltinNode {
123-
@Specialization
124-
boolean doForeignObject(VirtualFrame frame, Object self,
125-
@CachedLibrary(limit = "3") InteropLibrary lib,
126-
@Cached("createIfTrueNode()") CastToBooleanNode cast) {
127-
try {
128-
if (lib.isBoolean(self)) {
129-
return lib.asBoolean(self);
130-
} else if (lib.fitsInLong(self)) {
131-
return cast.executeBoolean(frame, lib.asLong(self));
132-
} else if (lib.fitsInDouble(self)) {
133-
return cast.executeBoolean(frame, lib.asDouble(self));
134-
} else if (lib.hasArrayElements(self)) {
135-
return cast.executeBoolean(frame, lib.getArraySize(self));
136-
} else {
137-
return !lib.isNull(self);
138-
}
139-
} catch (UnsupportedMessageException e) {
140-
throw raise(AttributeError, "'foreign' object has no attribute '__bool__'");
141-
}
123+
@Specialization(limit = "1")
124+
boolean doForeignObject(Object self,
125+
@CachedLibrary("self") PythonObjectLibrary lib) {
126+
return lib.isTrue(self);
142127
}
143128
}
144129

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/PInt.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ public Object asIndexWithState(@SuppressWarnings("unused") ThreadState threadSta
198198
return this;
199199
}
200200

201+
@ExportMessage
202+
boolean isTrueWithState(@SuppressWarnings("unused") ThreadState threadState) {
203+
return !isZero();
204+
}
205+
201206
@Override
202207
public int hashCode() {
203208
return value.hashCode();

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -62,12 +62,14 @@
6262
import com.oracle.graal.python.builtins.objects.common.IndexNodes.NormalizeIndexNode;
6363
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
6464
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.ListGeneralizationNode;
65+
import com.oracle.graal.python.builtins.objects.function.PArguments;
6566
import com.oracle.graal.python.builtins.objects.ints.PInt;
6667
import com.oracle.graal.python.builtins.objects.iterator.PDoubleSequenceIterator;
6768
import com.oracle.graal.python.builtins.objects.iterator.PIntegerSequenceIterator;
6869
import com.oracle.graal.python.builtins.objects.iterator.PLongSequenceIterator;
6970
import com.oracle.graal.python.builtins.objects.iterator.PSequenceIterator;
7071
import com.oracle.graal.python.builtins.objects.list.ListBuiltinsFactory.ListReverseNodeFactory;
72+
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
7173
import com.oracle.graal.python.builtins.objects.range.PRange;
7274
import com.oracle.graal.python.builtins.objects.str.PString;
7375
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
@@ -80,7 +82,6 @@
8082
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
8183
import com.oracle.graal.python.nodes.control.GetIteratorExpressionNode.GetIteratorNode;
8284
import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
83-
import com.oracle.graal.python.nodes.expression.CastToBooleanNode;
8485
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
8586
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
8687
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
@@ -105,6 +106,7 @@
105106
import com.oracle.truffle.api.dsl.Specialization;
106107
import com.oracle.truffle.api.dsl.TypeSystemReference;
107108
import com.oracle.truffle.api.frame.VirtualFrame;
109+
import com.oracle.truffle.api.library.CachedLibrary;
108110
import com.oracle.truffle.api.profiles.ConditionProfile;
109111

110112
@CoreFunctions(extendClasses = PythonBuiltinClassType.PList)
@@ -478,13 +480,13 @@ PNone remove(VirtualFrame frame, PList list, Object value,
478480
@Cached("createNotNormalized()") SequenceStorageNodes.GetItemNode getItemNode,
479481
@Cached("create()") SequenceStorageNodes.DeleteNode deleteNode,
480482
@Cached("create()") SequenceStorageNodes.LenNode lenNode,
481-
@Cached("createIfTrueNode()") CastToBooleanNode castToBooleanNode,
483+
@CachedLibrary(limit = "getCallSiteInlineCacheMaxDepth()") PythonObjectLibrary lib,
482484
@Cached("create(__EQ__, __EQ__, __EQ__)") BinaryComparisonNode eqNode) {
483485
SequenceStorage listStore = list.getSequenceStorage();
484486
int len = lenNode.execute(listStore);
485487
for (int i = 0; i < len; i++) {
486488
Object object = getItemNode.execute(frame, listStore, i);
487-
if (castToBooleanNode.executeBoolean(frame, eqNode.executeWith(frame, object, value))) {
489+
if (lib.isTrueWithState(eqNode.executeWith(frame, object, value), PArguments.getThreadState(frame))) {
488490
deleteNode.execute(frame, listStore, i);
489491
return PNone.NONE;
490492
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/DefaultPythonBooleanExports.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,9 @@ static LazyPythonClass getLazyPythonClass(@SuppressWarnings("unused") Boolean va
7676
static long hash(Boolean value) {
7777
return value ? 1 : 0;
7878
}
79+
80+
@ExportMessage
81+
static boolean isTrue(Boolean value) {
82+
return value;
83+
}
7984
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/DefaultPythonDoubleExports.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -74,4 +74,9 @@ static long hashDoubleWithDecimals(Double self) {
7474
return self.hashCode();
7575
}
7676
}
77+
78+
@ExportMessage
79+
static boolean isTrue(Double value) {
80+
return value != 0.0;
81+
}
7782
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/DefaultPythonIntegerExports.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,9 @@ static LazyPythonClass getLazyPythonClass(@SuppressWarnings("unused") Integer va
7676
static long hash(Integer value) {
7777
return value;
7878
}
79+
80+
@ExportMessage
81+
static boolean isTrue(Integer value) {
82+
return value != 0;
83+
}
7984
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/DefaultPythonLongExports.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,9 @@ static LazyPythonClass getLazyPythonClass(@SuppressWarnings("unused") Long value
9393
static long hash(Long value) {
9494
return value;
9595
}
96+
97+
@ExportMessage
98+
static boolean isTrue(Long value) {
99+
return value != 0;
100+
}
96101
}

0 commit comments

Comments
 (0)