Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .agents/skills/windows/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: windows
description: Windows-specific command guidance. Use when working on Windows and a required CLI tool, especially gdev-cli, is not available directly in PowerShell or cmd.
---

# Windows

On Windows, if `gdev-cli` is not available, it may be available via `wsl bash -l -c gdev-cli`.
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ def build_package(self, name, version):

def add_package_to_index(self, name, version, dist_type):
package = self.build_package(name, version)[dist_type]
shutil.copy(package, self.index_dir)
# extra careful, not using shutil.copy so we get more detailed traceback
# on some flaky windows CI workers
self.assertTrue(package.exists(), f"Built package disappeared: {package}")
destination = self.index_dir / package.name
with open(package, 'rb') as src, open(destination, 'wb') as dst:
shutil.copyfileobj(src, dst)

def run_venv_pip_install(self, package, extra_env=None, assert_stderr_matches=None):
env = self.pip_env.copy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
import com.oracle.graal.python.builtins.PythonBuiltins;
import com.oracle.graal.python.builtins.objects.PNone;
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
import com.oracle.graal.python.builtins.objects.common.EconomicMapStorage;
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
import com.oracle.graal.python.builtins.objects.dict.PDict;
Expand Down Expand Up @@ -355,8 +356,8 @@ private static MatcherType getMatcherType(Node inliningTarget, Object value) {
if (isExceptionTypeUncached(value)) {
return MatcherType.BY_TYPE;
}
if (value instanceof PTuple tuple && PyTupleCheckExactNode.executeUncached(tuple)) {
SequenceStorage storage = tuple.getSequenceStorage();
SequenceStorage storage = getExactTupleStorage(value);
if (storage != null) {
for (int i = 0; i < storage.length(); i++) {
Object elem = SequenceStorageNodes.GetItemScalarNode.executeUncached(storage, i);
if (!isExceptionTypeUncached(elem)) {
Expand All @@ -368,6 +369,16 @@ private static MatcherType getMatcherType(Node inliningTarget, Object value) {
throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.EXPECTED_A_FUNCTION_EXCEPTION_TYPE_OR_TUPLE_OF_EXCEPTION_TYPES);
}

private static SequenceStorage getExactTupleStorage(Object value) {
if (value instanceof PTuple tuple && PyTupleCheckExactNode.executeUncached(tuple)) {
return tuple.getSequenceStorage();
}
if (value instanceof PythonAbstractNativeObject nativeTuple && PyTupleCheckExactNode.executeUncached(nativeTuple)) {
return TupleNodes.GetNativeTupleStorage.getUncached().execute(nativeTuple);
}
return null;
}

private static boolean isExceptionTypeUncached(Object value) {
return TypeNodes.IsTypeNode.executeUncached(value) && BuiltinClassProfiles.IsBuiltinClassProfile.profileClassSlowPath(value, PythonBuiltinClassType.PBaseException);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
import com.oracle.graal.python.builtins.objects.PNone;
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
import com.oracle.graal.python.lib.PyExceptionInstanceCheckNode;
import com.oracle.graal.python.lib.PyObjectIsInstanceNode;
import com.oracle.graal.python.lib.PyTupleCheckNode;
import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.PGuards;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.builtins.TupleNodes.GetTupleStorage;
import com.oracle.graal.python.nodes.call.CallNode;
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
import com.oracle.graal.python.runtime.object.PFactory;
Expand Down Expand Up @@ -96,11 +97,12 @@ static Object doException(@SuppressWarnings("unused") PBaseException exc, @Suppr
throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.INSTANCE_EX_MAY_NOT_HAVE_SEP_VALUE);
}

@Specialization(guards = {"isTypeNode.execute(inliningTarget, type)", "!isPNone(value)", "!isPTuple(value)"}, limit = "1")
@Specialization(guards = {"isTypeNode.execute(inliningTarget, type)", "!isPNone(value)", "!tupleCheck.execute(inliningTarget, value)"}, limit = "1")
static Object doExceptionOrCreate(VirtualFrame frame, Object type, Object value,
@Bind Node inliningTarget,
@SuppressWarnings("unused") @Exclusive @Cached IsTypeNode isTypeNode,
@Exclusive @Cached PyExceptionInstanceCheckNode check,
@SuppressWarnings("unused") @Exclusive @Cached PyTupleCheckNode tupleCheck,
@Cached PyObjectIsInstanceNode isInstanceNode,
@Cached InlinedConditionProfile isInstanceProfile,
@Shared @Cached IsSubtypeNode isSubtypeNode,
Expand Down Expand Up @@ -136,17 +138,19 @@ static Object doCreate(VirtualFrame frame, Object type, @SuppressWarnings("unuse
}
}

@Specialization(guards = "isTypeNode.execute(inliningTarget, type)", limit = "1")
static Object doCreateTuple(VirtualFrame frame, Object type, PTuple value,
@Specialization(guards = {"isTypeNode.execute(inliningTarget, type)", "tupleCheck.execute(inliningTarget, value)"}, limit = "1")
static Object doCreateTuple(VirtualFrame frame, Object type, Object value,
@Bind Node inliningTarget,
@SuppressWarnings("unused") @Exclusive @Cached IsTypeNode isTypeNode,
@Exclusive @Cached PyExceptionInstanceCheckNode check,
@Cached SequenceNodes.GetObjectArrayNode getObjectArrayNode,
@SuppressWarnings("unused") @Exclusive @Cached PyTupleCheckNode tupleCheck,
@Exclusive @Cached GetTupleStorage getTupleStorage,
@Exclusive @Cached SequenceStorageNodes.ToArrayNode toArrayNode,
@Shared @Cached IsSubtypeNode isSubtypeNode,
@Exclusive @Cached PRaiseNode raiseNode,
@Shared("callCtor") @Cached CallNode callConstructor) {
checkExceptionClass(inliningTarget, type, isSubtypeNode, raiseNode);
Object[] args = getObjectArrayNode.execute(inliningTarget, value);
Object[] args = toArrayNode.execute(inliningTarget, getTupleStorage.execute(inliningTarget, value));
Object instance = callConstructor.execute(frame, type, args);
if (check.execute(inliningTarget, instance)) {
return instance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,10 @@ public static PyObjectIsInstanceNode getUncached() {
return PyObjectIsInstanceNodeGen.getUncached();
}

@Specialization(guards = "!isPTuple(cls)", insertBefore = "doTupleConstantLen")
@Specialization(guards = "!tupleCheck.execute(inliningTarget, cls)", insertBefore = "doRecursiveWithNode", limit = "1")
static boolean isInstance(VirtualFrame frame, Object instance, Object cls, @SuppressWarnings("unused") int depth,
@Bind Node inliningTarget,
@SuppressWarnings("unused") @Cached PyTupleCheckNode tupleCheck,
@Cached GetClassNode getClsClassNode,
@Cached IsBuiltinClassExactProfile classProfile,
@Cached GetClassNode getInstanceClassNode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,10 @@ public static PyObjectIsSubclassNode getUncached() {
return PyObjectIsSubclassNodeGen.getUncached();
}

@Specialization(guards = "!isPTuple(cls)", insertBefore = "doTupleConstantLen")
@Specialization(guards = "!tupleCheck.execute(inliningTarget, cls)", insertBefore = "doRecursiveWithNode", limit = "1")
static boolean isSubclass(VirtualFrame frame, Object derived, Object cls, @SuppressWarnings("unused") int depth,
@Bind Node inliningTarget,
@SuppressWarnings("unused") @Cached PyTupleCheckNode tupleCheck,
@Cached GetClassNode getClsClassNode,
@Cached IsBuiltinClassExactProfile classProfile,
@Cached LookupSpecialMethodNode.Dynamic subclassCheckLookup,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,16 @@
package com.oracle.graal.python.lib;

import com.oracle.graal.python.PythonLanguage;
import com.oracle.graal.python.builtins.objects.common.SequenceNodes.GetObjectArrayNode;
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
import com.oracle.graal.python.nodes.PGuards;
import com.oracle.graal.python.nodes.PNodeWithContext;
import com.oracle.graal.python.nodes.builtins.TupleNodes;
import com.oracle.graal.python.runtime.ExecutionContext.BoundaryCallContext;
import com.oracle.graal.python.runtime.IndirectCallData.BoundaryCallData;
import com.oracle.graal.python.runtime.PythonOptions;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Cached.Shared;
import com.oracle.truffle.api.dsl.GenerateCached;
import com.oracle.truffle.api.dsl.GenerateInline;
import com.oracle.truffle.api.dsl.Idempotent;
Expand All @@ -60,8 +59,6 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.ExplodeLoop.LoopExplosionKind;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.UnadoptableNode;

Expand All @@ -74,8 +71,6 @@
@GenerateCached(false)
@SuppressWarnings("truffle-neverdefault")
abstract class PyObjectRecursiveBinaryCheckNode extends PNodeWithContext {
static final int MAX_EXPLODE_LOOP = 16; // is also shifted to the left by recursion depth

public final boolean execute(Frame frame, Object arg, Object classinfo) {
return executeInternal(frame, arg, classinfo, 0);
}
Expand All @@ -87,78 +82,64 @@ public final boolean execute(Frame frame, Object arg, Object classinfo) {

abstract PyObjectRecursiveBinaryCheckNode getUncachedRecursive();

@Idempotent
protected static int getMaxExplodeLoop(int depth) {
return MAX_EXPLODE_LOOP >> depth;
}

@Specialization(guards = {"depth < getNodeRecursionLimit(language)", "getLength(clsTuple) == cachedLen", "cachedLen < getMaxExplodeLoop(depth)"}, //
limit = "getVariableArgumentInlineCacheLimit()", excludeForUncached = true)
@ExplodeLoop(kind = LoopExplosionKind.FULL_UNROLL_UNTIL_RETURN)
static boolean doTupleConstantLen(VirtualFrame frame, Object arg, PTuple clsTuple, int depth,
@Specialization(guards = {"depth < getNodeRecursionLimit(language)", "tupleCheck.execute(inliningTarget, clsTuple)"}, limit = "1", excludeForUncached = true)
static boolean doRecursiveWithNode(VirtualFrame frame, Object arg, Object clsTuple, int depth,
@Bind Node inliningTarget,
@SuppressWarnings("unused") @Bind PythonLanguage language,
@Cached("getLength(clsTuple)") int cachedLen,
@Shared @Cached GetObjectArrayNode getObjectArrayNode,
@Shared @Cached("createRecursive()") PyObjectRecursiveBinaryCheckNode recursiveNode) {
Object[] array = getObjectArrayNode.execute(inliningTarget, clsTuple);
int newDepth = depth + 1;
for (int i = 0; i < cachedLen; i++) {
Object cls = array[i];
if (recursiveNode.executeInternal(frame, arg, cls, newDepth)) {
return true;
}
}
return false;
}

@Specialization(guards = "depth < getNodeRecursionLimit(language)", replaces = "doTupleConstantLen", excludeForUncached = true)
static boolean doRecursiveWithNode(VirtualFrame frame, Object arg, PTuple clsTuple, int depth,
@Bind Node inliningTarget,
@SuppressWarnings("unused") @Bind PythonLanguage language,
@Shared @Cached GetObjectArrayNode getObjectArrayNode,
@Shared @Cached("createRecursive()") PyObjectRecursiveBinaryCheckNode recursiveNode) {
return loopRecursive(frame, arg, clsTuple, inliningTarget, getObjectArrayNode, recursiveNode, depth + 1);
@SuppressWarnings("unused") @Cached PyTupleCheckNode tupleCheck,
@Cached TupleNodes.GetTupleStorage getTupleStorage,
@Cached SequenceStorageNodes.ToArrayNode toArrayNode,
@Cached("createRecursive()") PyObjectRecursiveBinaryCheckNode recursiveNode) {
return loopRecursive(frame, arg, clsTuple, inliningTarget, getTupleStorage, toArrayNode, recursiveNode, depth + 1);
}

@Specialization(guards = {"depth >= getNodeRecursionLimit(language)"}, excludeForUncached = true)
boolean doRecursiveTransition(VirtualFrame frame, Object arg, PTuple clsTuple, @SuppressWarnings("unused") int depth,
@SuppressWarnings("truffle-static-method")
@Specialization(guards = {"depth >= getNodeRecursionLimit(language)", "tupleCheck.execute(inliningTarget, clsTuple)"}, limit = "1", excludeForUncached = true)
boolean doRecursiveTransition(VirtualFrame frame, Object arg, Object clsTuple, @SuppressWarnings("unused") int depth,
@Bind Node inliningTarget,
@SuppressWarnings("unused") @Bind PythonLanguage language,
@Cached("createFor($node)") BoundaryCallData boundaryCallData,
@Shared @Cached GetObjectArrayNode getObjectArrayNode) {
@SuppressWarnings("unused") @Cached PyTupleCheckNode tupleCheck,
@Cached TupleNodes.GetTupleStorage getTupleStorage,
@Cached SequenceStorageNodes.ToArrayNode toArrayNode) {
Object state = BoundaryCallContext.enter(frame, boundaryCallData);
try {
// Note: we need actual recursion to trigger the stack overflow error like CPython.
return callRecursiveWithNodeTruffleBoundary(inliningTarget, arg, clsTuple, getObjectArrayNode);
return callRecursiveWithNodeTruffleBoundary(inliningTarget, arg, clsTuple, getTupleStorage, toArrayNode);
} finally {
BoundaryCallContext.exit(frame, boundaryCallData, state);
}
}

@Specialization
boolean doRecursiveUncached(VirtualFrame frame, Object arg, PTuple clsTuple, @SuppressWarnings("unused") int depth) {
@SuppressWarnings("truffle-static-method")
@Specialization(guards = "tupleCheck.execute(inliningTarget, clsTuple)", limit = "1")
boolean doRecursiveUncached(VirtualFrame frame, Object arg, Object clsTuple, @SuppressWarnings("unused") int depth,
@Bind Node inliningTarget,
@SuppressWarnings("unused") @Cached PyTupleCheckNode tupleCheck,
@Cached TupleNodes.GetTupleStorage getTupleStorage,
@Cached SequenceStorageNodes.ToArrayNode toArrayNode) {
assert this instanceof UnadoptableNode;
return loopRecursive(frame, arg, clsTuple, null, GetObjectArrayNode.getUncached(), this, -1);
return loopRecursive(frame, arg, clsTuple, inliningTarget, getTupleStorage, toArrayNode, this, -1);
}

@TruffleBoundary
private boolean callRecursiveWithNodeTruffleBoundary(Node inliningTarget, Object arg, PTuple clsTuple, GetObjectArrayNode getObjectArrayNode) {
return loopRecursive(null, arg, clsTuple, inliningTarget, getObjectArrayNode, getUncachedRecursive(), -1);
private boolean callRecursiveWithNodeTruffleBoundary(Node inliningTarget, Object arg, Object clsTuple, TupleNodes.GetTupleStorage getTupleStorage,
SequenceStorageNodes.ToArrayNode toArrayNode) {
return loopRecursive(null, arg, clsTuple, inliningTarget, getTupleStorage, toArrayNode, getUncachedRecursive(), -1);
}

private static boolean loopRecursive(VirtualFrame frame, Object arg, PTuple clsTuple, Node inliningTarget, GetObjectArrayNode getObjectArrayNode, PyObjectRecursiveBinaryCheckNode node,
int depth) {
for (Object cls : getObjectArrayNode.execute(inliningTarget, clsTuple)) {
private static boolean loopRecursive(VirtualFrame frame, Object arg, Object clsTuple, Node inliningTarget, TupleNodes.GetTupleStorage getTupleStorage,
SequenceStorageNodes.ToArrayNode toArrayNode, PyObjectRecursiveBinaryCheckNode node, int depth) {
for (Object cls : getTupleArray(inliningTarget, clsTuple, getTupleStorage, toArrayNode)) {
if (node.executeInternal(frame, arg, cls, depth)) {
return true;
}
}
return false;
}

protected static int getLength(PTuple t) {
return t.getSequenceStorage().length();
private static Object[] getTupleArray(Node inliningTarget, Object clsTuple, TupleNodes.GetTupleStorage getTupleStorage, SequenceStorageNodes.ToArrayNode toArrayNode) {
return toArrayNode.execute(inliningTarget, getTupleStorage.execute(inliningTarget, clsTuple));
}

@Idempotent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -40,9 +40,13 @@
*/
package com.oracle.graal.python.lib;

import com.oracle.graal.python.builtins.PythonBuiltinClassType;
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
import com.oracle.graal.python.nodes.PGuards;
import com.oracle.graal.python.nodes.PNodeWithContext;
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectExactProfile;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.GenerateCached;
import com.oracle.truffle.api.dsl.GenerateInline;
Expand Down Expand Up @@ -70,6 +74,12 @@ static boolean doBuiltinTuple(@SuppressWarnings("unused") PTuple tuple) {
return true;
}

@Specialization
static boolean doNativeTuple(PythonAbstractNativeObject tuple,
@Cached(inline = false) IsBuiltinObjectExactProfile check) {
return check.profileObject(check, tuple, PythonBuiltinClassType.PTuple);
}

@Fallback
static boolean doOther(@SuppressWarnings("unused") Object object) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ SequenceStorage getNative(PythonAbstractNativeObject tuple,
public abstract static class GetNativeTupleStorage extends Node {
public abstract NativeObjectSequenceStorage execute(PythonAbstractNativeObject tuple);

public static GetNativeTupleStorage getUncached() {
return TupleNodesFactory.GetNativeTupleStorageNodeGen.getUncached();
}

@Specialization
NativeObjectSequenceStorage getNative(PythonAbstractNativeObject tuple) {
assert PyTupleCheckNode.executeUncached(tuple);
Expand Down
Loading
Loading