Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void before() {
Builder newBuilder = Context.newBuilder();
newBuilder.allowExperimentalOptions(true);
newBuilder.allowAllAccess(true);
newBuilder.option("engine.WarnInterpreterOnly", "false");
PythonTests.closeContext();
tester = new DebuggerTester(newBuilder);
}
Expand Down
32 changes: 30 additions & 2 deletions graalpython/com.oracle.graal.python.test/src/tests/test_code.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2018, 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 @@ -284,4 +284,32 @@ def bug93662():
raise ValueError()

check_lines(misshappen)
check_lines(bug93662)
check_lines(bug93662)


def test_code_identity():
import sys
import marshal
import types
import _imp
def foo():
def bar():
return sys._getframe()

return bar

bar = foo()
assert bar.__code__ is foo().__code__
i = foo.__code__.co_consts.index(bar.__code__)
# TODO this is currently broken on the DSL interpreter because the code unit in constants is a separate copy
# assert bar.__code__ is foo.__code__.co_consts[i]
assert bar.__code__ is bar().f_code

foo_copy = types.FunctionType(marshal.loads(marshal.dumps(foo.__code__)), globals=foo.__globals__, closure=foo.__closure__)
bar_copy = foo_copy()
assert foo_copy.__code__ is not foo.__code__
_imp._fix_co_filename(foo_copy.__code__, 'asdf')
assert foo_copy.__code__.co_filename == 'asdf'
assert bar_copy.__code__.co_filename == 'asdf'
assert foo.__code__.co_filename != 'asdf'
assert bar.__code__.co_filename != 'asdf'
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,7 @@ public Object execute(VirtualFrame frame) {
PFrame pFrame = materializeFrameNode.execute(this, false, true, frame);
Object pLocals = getFrameLocalsNode.executeCached(frame, pFrame, true);
PArguments.setSpecialArgument(arguments, pLocals);
PArguments.setCodeObject(arguments, PFactory.createCode(getLanguage(PythonLanguage.class), callTarget));
PArguments.setGlobals(arguments, PArguments.getGlobals(frame));
boolean wasAcquired = gilNode.acquire();
try {
Expand Down Expand Up @@ -1186,6 +1187,10 @@ public RootCallTarget createCachedCallTarget(Function<PythonLanguage, RootNode>
return createCachedCallTargetUnsafe(rootNodeFunction, true, nodeClass1, nodeClass2, type, name);
}

public RootCallTarget createCachedCallTarget(Function<PythonLanguage, RootNode> rootNodeFunction, CodeUnit key) {
return createCachedCallTargetUnsafe(rootNodeFunction, true, key);
}

/**
* Caches call targets for external C functions created by extensions at runtime.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@
import com.oracle.graal.python.builtins.objects.bytes.BytesCommonBuiltins;
import com.oracle.graal.python.builtins.objects.cell.CellBuiltins;
import com.oracle.graal.python.builtins.objects.code.CodeBuiltins;
import com.oracle.graal.python.builtins.objects.code.PCode;
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
import com.oracle.graal.python.builtins.objects.complex.ComplexBuiltins;
import com.oracle.graal.python.builtins.objects.contextvars.ContextBuiltins;
Expand Down Expand Up @@ -1328,7 +1329,8 @@ private void loadFile(TruffleString s, TruffleString prefix, PythonModule mod) {
return getLanguage().parse(getContext(), source, InputType.FILE, false, 0, false, null, EnumSet.noneOf(FutureFeature.class));
};
RootCallTarget callTarget = (RootCallTarget) getLanguage().cacheCode(s, getCode);
CallDispatchers.SimpleIndirectInvokeNode.executeUncached(callTarget, PArguments.withGlobals(mod));
PCode code = PFactory.createCode(language, callTarget);
CallDispatchers.SimpleIndirectInvokeNode.executeUncached(callTarget, PArguments.withGlobals(code, mod));
}

public final PInt getTrue() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,7 @@ static Object eval(VirtualFrame frame, Node inliningTarget, Object source, Objec
throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.CODE_OBJ_NO_FREE_VARIABLES, mode);
}
Object[] args = createArguments.execute(frame, inliningTarget, globals, locals, mode);
PArguments.setCodeObject(args, code);
RootCallTarget callTarget = getCallTarget.execute(inliningTarget, code);
return invoke.execute(frame, inliningTarget, callTarget, args);
}
Expand Down Expand Up @@ -985,10 +986,9 @@ protected abstract Object executeInternal(VirtualFrame frame, Object source, Tru
int featureVersion);

private int inheritFlags(VirtualFrame frame, int flags, ReadFrameNode readCallerFrame) {
PFrame fr = readCallerFrame.getCurrentPythonFrame(frame);
if (fr != null) {
PCode code = PFactory.createCode(PythonLanguage.get(this), fr.getTarget());
flags |= code.getFlags() & PyCF_MASK;
PFrame pyFrame = readCallerFrame.getCurrentPythonFrame(frame);
if (pyFrame != null) {
flags |= pyFrame.getCode().getFlags() & PyCF_MASK;
}
return flags;
}
Expand Down Expand Up @@ -1071,7 +1071,7 @@ Object compile(TruffleString expression, TruffleString filename, TruffleString m
} else {
ct = getContext().getLanguage().cacheCode(filename, createCode);
}
return wrapRootCallTarget((RootCallTarget) ct);
return wrapRootCallTarget((RootCallTarget) ct, filename);
}

@Specialization(limit = "3")
Expand Down Expand Up @@ -1102,7 +1102,7 @@ Object generic(VirtualFrame frame, Object wSource, Object wFilename, TruffleStri
ModTy mod = AstModuleBuiltins.obj2sst(inliningTarget, context, wSource, getParserInputType(mode, flags));
Source source = PythonUtils.createFakeSource(filename);
RootCallTarget rootCallTarget = context.getLanguage(inliningTarget).compileModule(context, mod, source, false, optimize, null, null, flags);
return wrapRootCallTarget(rootCallTarget);
return wrapRootCallTarget(rootCallTarget, filename);
}
TruffleString source = sourceAsString(frame, inliningTarget, wSource, filename, interopLib, acquireLib, bufferLib, switchEncodingNode, raiseNode);
checkSource(source);
Expand All @@ -1112,7 +1112,7 @@ Object generic(VirtualFrame frame, Object wSource, Object wFilename, TruffleStri
}
}

private static PCode wrapRootCallTarget(RootCallTarget rootCallTarget) {
private static PCode wrapRootCallTarget(RootCallTarget rootCallTarget, TruffleString filename) {
RootNode rootNode = rootCallTarget.getRootNode();
if (PythonOptions.ENABLE_BYTECODE_DSL_INTERPRETER) {
if (rootNode instanceof PBytecodeDSLRootNode bytecodeDSLRootNode) {
Expand All @@ -1121,7 +1121,7 @@ private static PCode wrapRootCallTarget(RootCallTarget rootCallTarget) {
} else if (rootNode instanceof PBytecodeRootNode bytecodeRootNode) {
bytecodeRootNode.triggerDeferredDeprecationWarnings();
}
return PFactory.createCode(PythonLanguage.get(null), rootCallTarget);
return PFactory.createCode(PythonLanguage.get(null), rootCallTarget, filename);
}

@TruffleBoundary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,9 @@ private void runFile(PythonContext context, TruffleString inputFilePath) {
}
PythonLanguage language = context.getLanguage();
RootCallTarget callTarget = (RootCallTarget) context.getEnv().parsePublic(source);
PCode code = PFactory.createCode(language, callTarget);
Object[] arguments = PArguments.create();
PArguments.setCodeObject(arguments, code);
PythonModule mainModule = context.getMainModule();
PDict mainDict = GetOrCreateDictNode.executeUncached(mainModule);
PArguments.setGlobals(arguments, mainDict);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@
import com.oracle.graal.python.builtins.objects.module.PythonFrozenModule;
import com.oracle.graal.python.builtins.objects.module.PythonModule;
import com.oracle.graal.python.builtins.objects.object.PythonObject;
import com.oracle.graal.python.builtins.objects.str.PString;
import com.oracle.graal.python.builtins.objects.str.StringNodes;
import com.oracle.graal.python.compiler.CodeUnit;
import com.oracle.graal.python.lib.PyMemoryViewFromObject;
Expand Down Expand Up @@ -625,13 +624,14 @@ public static PythonModule importFrozenModuleObject(Node inliningTarget, PConstr

RootCallTarget callTarget = createCallTarget(core.getContext(), info);
PythonModule module = globals == null ? PFactory.createPythonModule(name) : globals;
PCode code = PFactory.createCode(core.getLanguage(), callTarget);

if (info.isPackage) {
/* Set __path__ to the empty list */
WriteAttributeToPythonObjectNode.getUncached().execute(module, T___PATH__, PFactory.createList(core.getLanguage()));
}

CallDispatchers.SimpleIndirectInvokeNode.executeUncached(callTarget, PArguments.withGlobals(module));
CallDispatchers.SimpleIndirectInvokeNode.executeUncached(callTarget, PArguments.withGlobals(code, module));

Object origName = info.origName == null ? PNone.NONE : info.origName;
WriteAttributeToPythonObjectNode.getUncached().execute(module, T___ORIGNAME__, origName);
Expand Down Expand Up @@ -728,23 +728,20 @@ protected ArgumentClinicProvider getArgumentClinic() {
}
}

@Builtin(name = "_fix_co_filename", minNumOfPositionalArgs = 2)
@Builtin(name = "_fix_co_filename", minNumOfPositionalArgs = 2, numOfPositionalOnlyArgs = 2, parameterNames = {"code", "path"})
@GenerateNodeFactory
public abstract static class FixCoFilename extends PythonBinaryBuiltinNode {
@ArgumentClinic(name = "path", conversion = ClinicConversion.TString)
public abstract static class FixCoFilename extends PythonBinaryClinicBuiltinNode {
@Specialization
@TruffleBoundary
public Object run(PCode code, PString path,
@Bind Node inliningTarget,
@Cached CastToTruffleStringNode castToStringNode) {
code.setFilename(castToStringNode.execute(inliningTarget, path));
public Object run(PCode code, TruffleString path) {
code.fixCoFilename(path);
return PNone.NONE;
}

@Specialization
@TruffleBoundary
public Object run(PCode code, TruffleString path) {
code.setFilename(path);
return PNone.NONE;
@Override
protected ArgumentClinicProvider getArgumentClinic() {
return ImpModuleBuiltinsClinicProviders.FixCoFilenameClinicProviderGen.INSTANCE;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.StringLiterals;
import com.oracle.graal.python.nodes.bytecode_dsl.BytecodeDSLCodeUnit;
import com.oracle.graal.python.nodes.bytecode_dsl.BytecodeDSLCodeUnitAndRoot;
import com.oracle.graal.python.nodes.bytecode_dsl.PBytecodeDSLRootNode;
import com.oracle.graal.python.nodes.bytecode_dsl.PBytecodeDSLRootNodeGen;
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
Expand Down Expand Up @@ -347,7 +346,6 @@ public static final class Marshal {
private static final char TYPE_ARRAY = ']';
// These are constants that show up in the Bytecode DSL interpreter.
private static final char TYPE_GRAALPYTHON_DSL_CODE_UNIT = 'D';
private static final char TYPE_GRAALPYTHON_DSL_CODE_UNIT_AND_ROOT = 'K';
private static final char TYPE_DSL_SOURCE = '$';
private static final char TYPE_DSL_EMPTY_KEYWORDS = 'k';

Expand Down Expand Up @@ -804,16 +802,6 @@ private void writeObject(Object v) throws IOException {
} else if (v instanceof BigInteger) {
writeByte(TYPE_BIG_INTEGER);
writeBigInteger((BigInteger) v);
} else if (v instanceof BytecodeDSLCodeUnitAndRoot unitAndRoot) {
// BytecodeDSLCodeUnit data should be deserialized to BytecodeDSLCodeUnit if we are
// deserializing a constant in the constants array of BytecodeDSLCodeUnit, otherwise
// if we are deserializing a constant operand of MakeFunction operation, we should
// deserialize it to BytecodeDSLCodeUnitAndRoot.
// In the deserializer we would have to pass down some context to know whether to
// deserialize to one or the other. Instead, we write this extra byte that allows us
// to distinguish this locally during deserialization.
writeByte(TYPE_GRAALPYTHON_DSL_CODE_UNIT_AND_ROOT);
writeReferenceOrComplexObject(unitAndRoot.getCodeUnit());
} else {
writeReferenceOrComplexObject(v);
}
Expand Down Expand Up @@ -1187,13 +1175,6 @@ private Object readObject(int type, AddRefAndReturn addRef) throws NumberFormatE
return addRef.run(readBytecodeCodeUnit());
case TYPE_GRAALPYTHON_DSL_CODE_UNIT:
return addRef.run(readBytecodeDSLCodeUnit());
case TYPE_GRAALPYTHON_DSL_CODE_UNIT_AND_ROOT:
Object co = readObject();
if (co instanceof BytecodeDSLCodeUnit dslUnit) {
return new BytecodeDSLCodeUnitAndRoot(dslUnit);
} else {
throw new MarshalError(ValueError, ErrorMessages.BAD_MARSHAL_DATA);
}
case TYPE_DSL_SOURCE:
return getSource();
case TYPE_DSL_EMPTY_KEYWORDS:
Expand Down Expand Up @@ -1571,14 +1552,12 @@ private PCode readCode() {
return PythonLanguage.callTargetFromBytecode(context, subSource, code);
};
CallTarget callTarget;
if (context.getLanguage().isSingleContext() || cacheKey == 0) {
if (getLanguage().isSingleContext() || cacheKey == 0) {
callTarget = supplier.get();
} else {
// get a new ID every time we deserialize the same filename in the same context
long fullCacheKey = cacheKey + context.getDeserializationId(fileName);
callTarget = context.getLanguage().cacheCode(new PythonLanguage.CodeCacheKey(fileName, fullCacheKey), supplier);
callTarget = getLanguage().cacheCode(new PythonLanguage.CodeCacheKey(fileName, cacheKey), supplier);
}
return PFactory.createCode(context.getLanguage(), (RootCallTarget) callTarget, flags, firstLineNo, lnoTab, fileName);
return PFactory.createCode(getLanguage(), (RootCallTarget) callTarget, flags, firstLineNo, lnoTab, fileName);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import static com.oracle.graal.python.nodes.ErrorMessages.INTEROP_TYPE_ALREADY_REGISTERED;
import static com.oracle.graal.python.nodes.ErrorMessages.INTEROP_TYPE_NOT_MERGABLE;
import static com.oracle.graal.python.nodes.ErrorMessages.S_ARG_MUST_BE_S_NOT_P;
import static com.oracle.graal.python.nodes.ErrorMessages.S_CANNOT_HAVE_S;
import static com.oracle.graal.python.nodes.ErrorMessages.S_DOES_NOT_TAKE_VARARGS;
import static com.oracle.graal.python.nodes.ErrorMessages.S_TAKES_EXACTLY_D_ARGS;
import static com.oracle.graal.python.nodes.ErrorMessages.S_TAKES_NO_KEYWORD_ARGS;
Expand Down Expand Up @@ -706,10 +705,6 @@ void handleArg(Object value, InteropBehaviorMethod method, InteropBehavior inter
// validate the function
if (function.getKwDefaults().length != 0) {
throw raiseNode.raise(this, ValueError, S_TAKES_NO_KEYWORD_ARGS, method.name);
} else if (function.getCode().getCellVars().length != 0) {
throw raiseNode.raise(this, ValueError, S_CANNOT_HAVE_S, method.name, "cell vars");
} else if (function.getCode().getFreeVars().length != 0) {
throw raiseNode.raise(this, ValueError, S_CANNOT_HAVE_S, method.name, "free vars");
} else {
// check signature
if (method.takesVarArgs != signature.takesVarArgs()) {
Expand Down
Loading
Loading