Skip to content

Commit a7a4bf8

Browse files
committed
[GR-34782] GitHub PR #239: intrinsify all and any builtins
PullRequest: graalpython/2011
2 parents a5fe1bd + 00cd397 commit a7a4bf8

File tree

2 files changed

+221
-16
lines changed

2 files changed

+221
-16
lines changed

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

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import static com.oracle.graal.python.builtins.objects.PNone.NO_VALUE;
3131
import static com.oracle.graal.python.builtins.objects.PNotImplemented.NOT_IMPLEMENTED;
3232
import static com.oracle.graal.python.nodes.BuiltinNames.ABS;
33+
import static com.oracle.graal.python.nodes.BuiltinNames.ALL;
34+
import static com.oracle.graal.python.nodes.BuiltinNames.ANY;
3335
import static com.oracle.graal.python.nodes.BuiltinNames.ASCII;
3436
import static com.oracle.graal.python.nodes.BuiltinNames.BIN;
3537
import static com.oracle.graal.python.nodes.BuiltinNames.BREAKPOINT;
@@ -102,7 +104,9 @@
102104
import com.oracle.graal.python.builtins.objects.code.PCode;
103105
import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage;
104106
import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes;
107+
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
105108
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
109+
import com.oracle.graal.python.builtins.objects.common.PHashingCollection;
106110
import com.oracle.graal.python.builtins.objects.common.SequenceNodes.GetObjectArrayNode;
107111
import com.oracle.graal.python.builtins.objects.common.SequenceNodesFactory.GetObjectArrayNodeGen;
108112
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
@@ -134,6 +138,7 @@
134138
import com.oracle.graal.python.lib.PyObjectGetAttr;
135139
import com.oracle.graal.python.lib.PyObjectGetIter;
136140
import com.oracle.graal.python.lib.PyObjectHashNode;
141+
import com.oracle.graal.python.lib.PyObjectIsTrueNode;
137142
import com.oracle.graal.python.lib.PyObjectLookupAttr;
138143
import com.oracle.graal.python.lib.PyObjectReprAsObjectNode;
139144
import com.oracle.graal.python.lib.PyObjectSizeNode;
@@ -144,6 +149,7 @@
144149
import com.oracle.graal.python.nodes.ErrorMessages;
145150
import com.oracle.graal.python.nodes.GraalPythonTranslationErrorNode;
146151
import com.oracle.graal.python.nodes.PGuards;
152+
import com.oracle.graal.python.nodes.PNodeWithContext;
147153
import com.oracle.graal.python.nodes.PNodeWithRaise;
148154
import com.oracle.graal.python.nodes.PRaiseNode;
149155
import com.oracle.graal.python.nodes.PRootNode;
@@ -204,6 +210,8 @@
204210
import com.oracle.graal.python.runtime.exception.PException;
205211
import com.oracle.graal.python.runtime.exception.PythonErrorType;
206212
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
213+
import com.oracle.graal.python.runtime.sequence.storage.BoolSequenceStorage;
214+
import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage;
207215
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
208216
import com.oracle.graal.python.util.CharsetMapping;
209217
import com.oracle.graal.python.util.PythonUtils;
@@ -232,11 +240,13 @@
232240
import com.oracle.truffle.api.library.CachedLibrary;
233241
import com.oracle.truffle.api.nodes.ExplodeLoop;
234242
import com.oracle.truffle.api.nodes.ExplodeLoop.LoopExplosionKind;
243+
import com.oracle.truffle.api.nodes.LoopNode;
235244
import com.oracle.truffle.api.nodes.Node;
236245
import com.oracle.truffle.api.nodes.RootNode;
237246
import com.oracle.truffle.api.nodes.UnexpectedResultException;
238247
import com.oracle.truffle.api.profiles.BranchProfile;
239248
import com.oracle.truffle.api.profiles.ConditionProfile;
249+
import com.oracle.truffle.api.profiles.LoopConditionProfile;
240250
import com.oracle.truffle.api.source.Source;
241251
import com.oracle.truffle.api.utilities.TriState;
242252

@@ -286,6 +296,217 @@ public Object absObject(VirtualFrame frame, Object object,
286296
}
287297
}
288298

299+
/**
300+
* Common class for all() and any() operations, as their logic and behaviors are very similar.
301+
*/
302+
abstract static class AllOrAnyNode extends PNodeWithContext {
303+
enum NodeType {
304+
ALL,
305+
ANY
306+
}
307+
308+
@Child private PyObjectIsTrueNode isTrueNode = PyObjectIsTrueNode.create();
309+
310+
private final LoopConditionProfile loopConditionProfile = LoopConditionProfile.create();
311+
312+
abstract boolean execute(Frame frame, Object storageObj, NodeType nodeType);
313+
314+
@Specialization
315+
boolean doBoolSequence(VirtualFrame frame,
316+
BoolSequenceStorage sequenceStorage,
317+
NodeType nodeType) {
318+
boolean[] internalArray = sequenceStorage.getInternalBoolArray();
319+
int seqLength = sequenceStorage.length();
320+
321+
loopConditionProfile.profileCounted(seqLength);
322+
for (int i = 0; loopConditionProfile.inject(i < seqLength); i++) {
323+
if (nodeType == NodeType.ALL && !isTrueNode.execute(frame, internalArray[i])) {
324+
return false;
325+
} else if (nodeType == NodeType.ANY && isTrueNode.execute(frame, internalArray[i])) {
326+
return true;
327+
}
328+
}
329+
330+
return nodeType == NodeType.ALL;
331+
}
332+
333+
@Specialization
334+
boolean doIntSequence(VirtualFrame frame,
335+
IntSequenceStorage sequenceStorage,
336+
NodeType nodeType) {
337+
int[] internalArray = sequenceStorage.getInternalIntArray();
338+
int seqLength = sequenceStorage.length();
339+
340+
loopConditionProfile.profileCounted(seqLength);
341+
for (int i = 0; loopConditionProfile.inject(i < seqLength); i++) {
342+
if (nodeType == NodeType.ALL && !isTrueNode.execute(frame, internalArray[i])) {
343+
return false;
344+
} else if (nodeType == NodeType.ANY && isTrueNode.execute(frame, internalArray[i])) {
345+
return true;
346+
}
347+
}
348+
349+
return nodeType == NodeType.ALL;
350+
}
351+
352+
@Specialization
353+
boolean doGenericSequence(VirtualFrame frame,
354+
SequenceStorage sequenceStorage,
355+
NodeType nodeType,
356+
@Cached SequenceStorageNodes.LenNode lenNode) {
357+
Object[] internalArray = sequenceStorage.getInternalArray();
358+
int seqLength = lenNode.execute(sequenceStorage);
359+
360+
loopConditionProfile.profileCounted(seqLength);
361+
for (int i = 0; loopConditionProfile.inject(i < seqLength); i++) {
362+
if (nodeType == NodeType.ALL && !isTrueNode.execute(frame, internalArray[i])) {
363+
return false;
364+
} else if (nodeType == NodeType.ANY && isTrueNode.execute(frame, internalArray[i])) {
365+
return true;
366+
}
367+
}
368+
369+
return nodeType == NodeType.ALL;
370+
}
371+
372+
@Specialization(limit = "3")
373+
protected boolean doHashStorage(VirtualFrame frame,
374+
HashingStorage hashingStorage,
375+
NodeType nodeType,
376+
@CachedLibrary("hashingStorage") HashingStorageLibrary hlib) {
377+
HashingStorageLibrary.HashingStorageIterator<Object> keysIter = hlib.keys(hashingStorage).iterator();
378+
int seqLength = hlib.length(hashingStorage);
379+
380+
loopConditionProfile.profileCounted(seqLength);
381+
for (int i = 0; loopConditionProfile.inject(i < seqLength); i++) {
382+
Object key = keysIter.next();
383+
if (nodeType == NodeType.ALL) {
384+
if (!isTrueNode.execute(frame, key)) {
385+
return false;
386+
}
387+
} else if (nodeType == NodeType.ANY && isTrueNode.execute(frame, key)) {
388+
return true;
389+
}
390+
}
391+
392+
return nodeType == NodeType.ALL;
393+
}
394+
}
395+
396+
@Builtin(name = ALL, minNumOfPositionalArgs = 1)
397+
@GenerateNodeFactory
398+
public abstract static class AllNode extends PythonUnaryBuiltinNode {
399+
400+
@Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1")
401+
static boolean doList(VirtualFrame frame,
402+
PList object,
403+
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode,
404+
@Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) {
405+
return allOrAnyNode.execute(frame, object.getSequenceStorage(), AllOrAnyNode.NodeType.ALL);
406+
}
407+
408+
@Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1")
409+
static boolean doTuple(VirtualFrame frame,
410+
PTuple object,
411+
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode,
412+
@Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) {
413+
return allOrAnyNode.execute(frame, object.getSequenceStorage(), AllOrAnyNode.NodeType.ALL);
414+
}
415+
416+
@Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1")
417+
static boolean doHashColl(VirtualFrame frame,
418+
PHashingCollection object,
419+
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode,
420+
@Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) {
421+
return allOrAnyNode.execute(frame, object.getDictStorage(), AllOrAnyNode.NodeType.ALL);
422+
}
423+
424+
@Specialization
425+
boolean doObject(VirtualFrame frame,
426+
Object object,
427+
@Cached PyObjectGetIter getIter,
428+
@Cached GetNextNode nextNode,
429+
@Cached IsBuiltinClassProfile errorProfile,
430+
@Cached PyObjectIsTrueNode isTrueNode) {
431+
Object iterator = getIter.execute(frame, object);
432+
int nbrIter = 0;
433+
434+
while (true) {
435+
try {
436+
Object next = nextNode.execute(frame, iterator);
437+
nbrIter++;
438+
if (!isTrueNode.execute(frame, next)) {
439+
return false;
440+
}
441+
} catch (PException e) {
442+
e.expectStopIteration(errorProfile);
443+
break;
444+
} finally {
445+
LoopNode.reportLoopCount(this, nbrIter);
446+
}
447+
}
448+
449+
return true;
450+
}
451+
}
452+
453+
@Builtin(name = ANY, minNumOfPositionalArgs = 1)
454+
@GenerateNodeFactory
455+
public abstract static class AnyNode extends PythonUnaryBuiltinNode {
456+
457+
@Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1")
458+
static boolean doList(VirtualFrame frame,
459+
PList object,
460+
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode,
461+
@Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) {
462+
return allOrAnyNode.execute(frame, object.getSequenceStorage(), AllOrAnyNode.NodeType.ANY);
463+
}
464+
465+
@Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1")
466+
static boolean doTuple(VirtualFrame frame,
467+
PTuple object,
468+
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode,
469+
@Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) {
470+
return allOrAnyNode.execute(frame, object.getSequenceStorage(), AllOrAnyNode.NodeType.ANY);
471+
}
472+
473+
@Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1")
474+
static boolean doHashColl(VirtualFrame frame,
475+
PHashingCollection object,
476+
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode,
477+
@Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) {
478+
return allOrAnyNode.execute(frame, object.getDictStorage(), AllOrAnyNode.NodeType.ANY);
479+
}
480+
481+
@Specialization
482+
boolean doObject(VirtualFrame frame,
483+
Object object,
484+
@Cached PyObjectGetIter getIter,
485+
@Cached GetNextNode nextNode,
486+
@Cached IsBuiltinClassProfile errorProfile,
487+
@Cached PyObjectIsTrueNode isTrueNode) {
488+
Object iterator = getIter.execute(frame, object);
489+
int nbrIter = 0;
490+
491+
while (true) {
492+
try {
493+
Object next = nextNode.execute(frame, iterator);
494+
nbrIter++;
495+
if (isTrueNode.execute(frame, next)) {
496+
return true;
497+
}
498+
} catch (PException e) {
499+
e.expectStopIteration(errorProfile);
500+
break;
501+
} finally {
502+
LoopNode.reportLoopCount(this, nbrIter);
503+
}
504+
}
505+
506+
return false;
507+
}
508+
}
509+
289510
// bin(object)
290511
@Builtin(name = BIN, minNumOfPositionalArgs = 1)
291512
@TypeSystemReference(PythonArithmeticTypes.class)

graalpython/lib-graalpython/functions.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,6 @@ def hasattr(obj, key):
4343
return getattr(obj, key, default) is not default
4444

4545

46-
@__graalpython__.builtin
47-
def any(iterable):
48-
for i in iterable:
49-
if i:
50-
return True
51-
return False
52-
53-
54-
@__graalpython__.builtin
55-
def all(iterable):
56-
for i in iterable:
57-
if not i:
58-
return False
59-
return True
60-
61-
6246
from sys import _getframe as __getframe__
6347

6448

0 commit comments

Comments
 (0)