From 6d0b245740c869910a9827316632dfa98a1fe61b Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 25 Jan 2019 21:52:03 +0100 Subject: [PATCH 001/202] Fake inode IDs for files. --- .../builtins/modules/PosixModuleBuiltins.java | 10 +++++++++- .../graal/python/runtime/PosixResources.java | 19 ++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index 147e129955..1f37f5be8c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -513,9 +513,17 @@ Object stat(String path, boolean followSymlinks) { } catch (IOException e) { size = 0; } + TruffleFile canonical; + try { + canonical = f.getCanonicalFile(); + } catch (IOException e) { + // best effort + canonical = f.getAbsoluteFile(); + } + int inode = getContext().getResources().getInodeId(canonical.getPath()); return factory().createTuple(new Object[]{ mode, - 0, // ino + inode, // ino 0, // dev 0, // nlink uid, diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java index 6bfe23559b..3c7bc91eda 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -47,6 +47,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; @@ -65,6 +67,8 @@ public class PosixResources { private final List files; private final List filePaths; private final List children; + private final Map inodes; + private int inodeCnt = 0; public PosixResources() { files = Collections.synchronizedList(new ArrayList<>()); @@ -82,6 +86,7 @@ public PosixResources() { files.add(null); files.add(null); files.add(null); + inodes = new ConcurrentHashMap<>(); } @TruffleBoundary(allowInlining = true) @@ -198,4 +203,16 @@ public int waitpid(int pid) throws ArrayIndexOutOfBoundsException, InterruptedEx children.set(pid, null); return exitStatus; } + + @TruffleBoundary(allowInlining = true) + public int getInodeId(String canonical) { + int inodeId; + if (!inodes.containsKey(canonical)) { + inodeId = inodeCnt++; + inodes.put(canonical, inodeId); + } else { + inodeId = inodes.get(canonical); + } + return inodeId; + } } From d1866c4064df9fbb7f60792765345a33f5a122bc Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Sat, 26 Jan 2019 08:39:00 +0100 Subject: [PATCH 002/202] Synchronize inode ID generation. --- .../graal/python/runtime/PosixResources.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java index 3c7bc91eda..42371deffb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java @@ -46,9 +46,9 @@ import java.nio.channels.Pipe; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; @@ -86,7 +86,7 @@ public PosixResources() { files.add(null); files.add(null); files.add(null); - inodes = new ConcurrentHashMap<>(); + inodes = new HashMap<>(); } @TruffleBoundary(allowInlining = true) @@ -206,13 +206,15 @@ public int waitpid(int pid) throws ArrayIndexOutOfBoundsException, InterruptedEx @TruffleBoundary(allowInlining = true) public int getInodeId(String canonical) { - int inodeId; - if (!inodes.containsKey(canonical)) { - inodeId = inodeCnt++; - inodes.put(canonical, inodeId); - } else { - inodeId = inodes.get(canonical); + synchronized (inodes) { + int inodeId; + if (!inodes.containsKey(canonical)) { + inodeId = inodeCnt++; + inodes.put(canonical, inodeId); + } else { + inodeId = inodes.get(canonical); + } + return inodeId; } - return inodeId; } } From ea151f01d9efcd1c74823834862f27418a2395e5 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 23 Jan 2019 16:09:55 +0100 Subject: [PATCH 003/202] poll the weakreference queue when we for a GC --- .../src/tests/test_weakref.py | 54 ++++++++++++++ .../builtins/modules/GcModuleBuiltins.java | 24 ++++++- .../modules/WeakRefModuleBuiltins.java | 5 +- .../objects/referencetype/PReferenceType.java | 71 +++++++++---------- .../graal/python/runtime/PythonContext.java | 12 ++++ .../runtime/object/PythonObjectFactory.java | 8 +-- 6 files changed, 126 insertions(+), 48 deletions(-) create mode 100644 graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py b/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py new file mode 100644 index 0000000000..1b63ce356e --- /dev/null +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py @@ -0,0 +1,54 @@ +# Copyright (c) 2018, 2019, 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 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +def test_weakref_finalizer(): + import gc, weakref + class A(): pass + for i in range(2): + w = weakref.ref(A(), cleanup) + gc.collect() + assert not w() + assert cleaned_up + + +cleaned_up = False +def cleanup(_=None): + global cleaned_up + cleaned_up = True diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java index 5e18bd4b6f..a5e4ffe4e2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -27,6 +27,7 @@ import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; +import java.lang.ref.Reference; import java.util.List; import com.oracle.graal.python.builtins.Builtin; @@ -34,12 +35,16 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; +import com.oracle.graal.python.builtins.objects.referencetype.PReferenceType; import com.oracle.graal.python.builtins.objects.tuple.PTuple; +import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; @CoreFunctions(defineModule = "gc") public final class GcModuleBuiltins extends PythonBuiltins { @@ -53,10 +58,23 @@ protected List r; + while ((r = getContext().pollWeakReferenceQueue()) != null) { + cnt++; + if (r instanceof PReferenceType.WeakRefStorage) { + ((PReferenceType.WeakRefStorage) r).runCallback(frame, callNode); + } + } + return cnt; + } + @TruffleBoundary - int collect() { + private static void doGc() { System.gc(); - return 0; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java index a04f8ec56a..ba94ad5f42 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -59,6 +59,7 @@ import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.TruffleObject; @SuppressWarnings("unused") @CoreFunctions(defineModule = "_weakref") @@ -78,7 +79,7 @@ public PReferenceType refType(PythonClass cls, PythonObject pythonObject, PNone } @Specialization - public PReferenceType refType(PythonClass cls, PythonObject pythonObject, PFunction callback) { + public PReferenceType refType(PythonClass cls, PythonObject pythonObject, TruffleObject callback) { return factory().createReferenceType(cls, pythonObject, callback); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/PReferenceType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/PReferenceType.java index 8a8b7480ed..8dcc0ad089 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/PReferenceType.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/PReferenceType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -40,50 +40,46 @@ */ package com.oracle.graal.python.builtins.objects.referencetype; +import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import com.oracle.graal.python.builtins.objects.PNone; -import com.oracle.graal.python.builtins.objects.PythonAbstractObject; -import com.oracle.graal.python.builtins.objects.function.PArguments; -import com.oracle.graal.python.builtins.objects.function.PFunction; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; -import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.truffle.api.CallTarget; +import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.TruffleObject; public class PReferenceType extends PythonBuiltinObject { - private class WeakRefStorage extends WeakReference { - private final CallTarget callback; + public static class WeakRefStorage extends WeakReference { + private final TruffleObject callback; private final PReferenceType ref; - private final PythonObject globals; - public WeakRefStorage(PReferenceType ref, PythonObject referent, PFunction callback) { - super(referent); - if (callback != null) { - this.callback = callback.getCallTarget(); - this.globals = callback.getGlobals(); - } else { - this.callback = null; - this.globals = null; - } + public WeakRefStorage(PReferenceType ref, Object referent, TruffleObject callback, ReferenceQueue referenceQueue) { + super(referent, referenceQueue); + this.callback = callback; this.ref = ref; } - @Override - protected void finalize() throws Throwable { - super.finalize(); + /** + * Run the callback (if any). + * + * @param callNode - must be inserted into the AST by the caller unless run on the slow path + */ + public void runCallback(VirtualFrame frame, CallNode callNode) { if (callback != null) { - // TODO: Exceptions raised by the callback will be noted on the - // standard error output, but cannot be propagated; they are - // handled in exactly the same way as exceptions raised TODO: - // from an object’s __del__() method. - // TODO: check: the referent must no longer be available at this - // point - Object[] arguments = PArguments.create(1); - PArguments.setArgument(arguments, 0, this.ref); - PArguments.setGlobals(arguments, globals); - callback.call(arguments); + try { + // TODO: check: the referent must no longer be available at this + // point + callNode.execute(frame, callback, ref); + } catch (RuntimeException e) { + // TODO: Exceptions raised by the callback will be noted on the + // standard error output, but cannot be propagated; they are + // handled in exactly the same way as exceptions raised + // from an object’s __del__() method. + e.printStackTrace(); + } } } } @@ -92,9 +88,9 @@ protected void finalize() throws Throwable { private int hash = -1; @TruffleBoundary - public PReferenceType(LazyPythonClass cls, PythonObject pythonObject, PFunction callback) { + public PReferenceType(LazyPythonClass cls, Object pythonObject, TruffleObject callback, ReferenceQueue referenceQueue) { super(cls); - this.store = new WeakRefStorage(this, pythonObject, callback); + this.store = new WeakRefStorage(this, pythonObject, callback, referenceQueue); } public Object getCallback() { @@ -105,12 +101,12 @@ public Object getCallback() { } @TruffleBoundary - public PythonObject getObject() { + public Object getObject() { return this.store.get(); } - public PythonAbstractObject getPyObject() { - PythonObject object = getObject(); + public Object getPyObject() { + Object object = getObject(); return (object == null) ? PNone.NONE : object; } @@ -118,12 +114,13 @@ public int getWeakRefCount() { return (this.getObject() == null) ? 0 : 1; } + @TruffleBoundary public int getHash() { if (this.hash != -1) { return this.hash; } - PythonObject object = getObject(); + Object object = getObject(); if (object != null) { this.hash = object.hashCode(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index ad82c122b3..526348faad 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -33,6 +33,8 @@ import java.io.InputStream; import java.io.OutputStream; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; import java.util.HashMap; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; @@ -63,6 +65,7 @@ public final class PythonContext { private final HashMap atExitHooks = new HashMap<>(); private final AtomicLong globalId = new AtomicLong(Integer.MAX_VALUE * 2L + 4L); private final ThreadGroup threadGroup = new ThreadGroup(GRAALPYTHON_THREADS); + private final ReferenceQueue weakRefQueue = new ReferenceQueue<>(); // if set to 0 the VM will set it to whatever it likes private final AtomicLong pythonThreadStackSize = new AtomicLong(0); @@ -321,4 +324,13 @@ public boolean isExecutableAccessAllowed() { public PosixResources getResources() { return resources; } + + public ReferenceQueue getWeakReferenceQueue() { + return weakRefQueue; + } + + @TruffleBoundary + public Reference pollWeakReferenceQueue() { + return weakRefQueue.poll(); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index 9e75447ecc..fa09288736 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -557,12 +557,8 @@ public PMappingproxy createMappingproxy(LazyPythonClass cls, HashingStorage stor return trace(new PMappingproxy(cls, storage)); } - public PReferenceType createReferenceType(LazyPythonClass cls, PythonObject object, PFunction callback) { - return trace(new PReferenceType(cls, object, callback)); - } - - public PReferenceType createReferenceType(PythonObject object, PFunction callback) { - return createReferenceType(PythonBuiltinClassType.PReferenceType, object, callback); + public PReferenceType createReferenceType(LazyPythonClass cls, Object object, TruffleObject callback) { + return trace(new PReferenceType(cls, object, callback, getContextRef().get().getWeakReferenceQueue())); } /* From 40d5d047a58ae274dcf70ddcd8c26ef217e38a6a Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 23 Jan 2019 17:59:39 +0100 Subject: [PATCH 004/202] schedule a task to periodically trigger collections --- .../src/tests/test_weakref.py | 3 +- .../builtins/modules/GcModuleBuiltins.java | 9 ++--- .../nodes/function/FunctionRootNode.java | 16 ++++++++- .../graal/python/runtime/PythonContext.java | 36 ++++++++++++++++++- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py b/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py index 1b63ce356e..652f1b49ac 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py @@ -43,7 +43,8 @@ def test_weakref_finalizer(): class A(): pass for i in range(2): w = weakref.ref(A(), cleanup) - gc.collect() + while not cleaned_up: + gc.collect() assert not w() assert cleaned_up diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java index a5e4ffe4e2..44e6240ec8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java @@ -27,7 +27,6 @@ import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; -import java.lang.ref.Reference; import java.util.List; import com.oracle.graal.python.builtins.Builtin; @@ -35,7 +34,6 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; -import com.oracle.graal.python.builtins.objects.referencetype.PReferenceType; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; @@ -62,12 +60,9 @@ int collect(VirtualFrame frame, @Cached("create()") CallNode callNode) { doGc(); int cnt = 0; - Reference r; - while ((r = getContext().pollWeakReferenceQueue()) != null) { + // collect all weak references now + while (getContext().collectWeakReferences(frame, callNode)) { cnt++; - if (r instanceof PReferenceType.WeakRefStorage) { - ((PReferenceType.WeakRefStorage) r).runCallback(frame, callNode); - } } return cnt; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java index 8c57cf8d21..6a29188c16 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java @@ -29,10 +29,14 @@ import com.oracle.graal.python.builtins.objects.cell.PCell; import com.oracle.graal.python.builtins.objects.function.PArguments; import com.oracle.graal.python.nodes.PClosureFunctionRootNode; +import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.graal.python.nodes.cell.CellSupplier; import com.oracle.graal.python.nodes.expression.ExpressionNode; import com.oracle.graal.python.parser.ExecutionCellSlots; +import com.oracle.graal.python.runtime.PythonContext; import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; @@ -47,7 +51,7 @@ * RootNode of a Python Function body. It is invoked by a CallTarget. */ public class FunctionRootNode extends PClosureFunctionRootNode implements CellSupplier { - + private final ContextReference contextRef; private final PCell[] cells; private final ExecutionCellSlots executionCellSlots; private final String functionName; @@ -57,11 +61,13 @@ public class FunctionRootNode extends PClosureFunctionRootNode implements CellSu private boolean isRewritten = false; @Child private ExpressionNode body; + @Child private CallNode callNode; private ExpressionNode uninitializedBody; public FunctionRootNode(PythonLanguage language, SourceSection sourceSection, String functionName, boolean isGenerator, FrameDescriptor frameDescriptor, ExpressionNode body, ExecutionCellSlots executionCellSlots) { super(language, frameDescriptor, executionCellSlots); + this.contextRef = language.getContextReference(); this.executionCellSlots = executionCellSlots; this.cells = new PCell[this.cellVarSlots.length]; @@ -138,6 +144,14 @@ private void initClosureAndCellVars(VirtualFrame frame) { @Override public Object execute(VirtualFrame frame) { + PythonContext pythonContext = contextRef.get(); + if (pythonContext.shouldTriggerCollection()) { + if (callNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + callNode = insert(CallNode.create()); + } + pythonContext.collectWeakReferences(frame, callNode); + } initClosureAndCellVars(frame); return body.execute(frame); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 526348faad..4a9a6adafc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -36,6 +36,9 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.util.HashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; @@ -47,6 +50,8 @@ import com.oracle.graal.python.builtins.objects.common.HashingStorage; import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.module.PythonModule; +import com.oracle.graal.python.builtins.objects.referencetype.PReferenceType; +import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CallTarget; @@ -56,6 +61,7 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; +import com.oracle.truffle.api.frame.VirtualFrame; public final class PythonContext { @@ -67,6 +73,10 @@ public final class PythonContext { private final ThreadGroup threadGroup = new ThreadGroup(GRAALPYTHON_THREADS); private final ReferenceQueue weakRefQueue = new ReferenceQueue<>(); + private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + private volatile boolean triggerCollection = false; + private static final int COLLECTIONS_N_MILLISECONDS = 5; + // if set to 0 the VM will set it to whatever it likes private final AtomicLong pythonThreadStackSize = new AtomicLong(0); private final Assumption nativeObjectsAllManagedAssumption = Truffle.getRuntime().createAssumption("all C API objects are managed"); @@ -248,6 +258,11 @@ private void setupRuntimeInformation() { mainModule.setDict(core.factory().createDictFixedStorage(mainModule)); sysModules.setItem(__MAIN__, mainModule); OpaqueBytes.initializeForNewContext(this); + executor.scheduleWithFixedDelay(new Runnable() { + public void run() { + triggerCollection = true; + } + }, COLLECTIONS_N_MILLISECONDS, COLLECTIONS_N_MILLISECONDS, TimeUnit.MILLISECONDS); currentException = null; isInitialized = true; } @@ -330,7 +345,26 @@ public ReferenceQueue getWeakReferenceQueue() { } @TruffleBoundary - public Reference pollWeakReferenceQueue() { + private Reference pollWeakReferenceQueue() { return weakRefQueue.poll(); } + + public boolean shouldTriggerCollection() { + if (triggerCollection) { + triggerCollection = false; + return true; + } else { + return false; + } + } + + public boolean collectWeakReferences(VirtualFrame frame, CallNode callNode) { + Reference r = pollWeakReferenceQueue(); + if (r instanceof PReferenceType.WeakRefStorage) { + ((PReferenceType.WeakRefStorage) r).runCallback(frame, callNode); + return true; + } else { + return false; + } + } } From 03ebdf28f32339241e4b5e53527a1a2d23934a25 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 11:11:50 +0100 Subject: [PATCH 005/202] move postInitialization code to appropriate places in builtin modules --- .../graal/python/builtins/Python3Core.java | 86 +------------------ .../graal/python/builtins/PythonBuiltins.java | 13 ++- .../builtins/modules/BuiltinFunctions.java | 10 +++ .../builtins/modules/SysModuleBuiltins.java | 85 ++++++++++++++++++ .../graal/python/runtime/PythonContext.java | 16 ++-- .../graal/python/runtime/PythonCore.java | 6 -- 6 files changed, 117 insertions(+), 99 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java index a8dbafb35a..7d368bcc6c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java @@ -124,7 +124,6 @@ import com.oracle.graal.python.builtins.objects.iterator.PZipBuiltins; import com.oracle.graal.python.builtins.objects.iterator.SentinelIteratorBuiltins; import com.oracle.graal.python.builtins.objects.list.ListBuiltins; -import com.oracle.graal.python.builtins.objects.list.PList; import com.oracle.graal.python.builtins.objects.mappingproxy.MappingproxyBuiltins; import com.oracle.graal.python.builtins.objects.memoryview.BufferBuiltins; import com.oracle.graal.python.builtins.objects.memoryview.MemoryviewBuiltins; @@ -398,7 +397,6 @@ public boolean isInitialized() { public void initialize(PythonContext context) { singletonContext = context; initializeJavaCore(); - initializeSysModule(); initializePythonCore(); initialized = true; } @@ -425,6 +423,10 @@ public void postInitialize() { if (!TruffleOptions.AOT || ImageInfo.inImageRuntimeCode()) { initialized = false; + for (PythonBuiltins builtin : builtins) { + builtin.postInitialize(this); + } + loadFile(__BUILTINS_PATCHES__, PythonCore.getCoreHomeOrFail()); PythonModule os = lookupBuiltinModule("posix"); @@ -435,86 +437,6 @@ public void postInitialize() { } } - public PythonModule initializeSysModule() { - PythonModule sys = builtinModules.get("sys"); - PythonContext context = getContext(); - String[] args = context.getEnv().getApplicationArguments(); - sys.setAttribute("argv", factory().createList(Arrays.copyOf(args, args.length, Object[].class))); - String prefix = PythonCore.getSysPrefix(context.getEnv()); - for (String name : SysModuleBuiltins.SYS_PREFIX_ATTRIBUTES) { - sys.setAttribute(name, prefix); - } - - sys.setAttribute("executable", PythonOptions.getOption(context, PythonOptions.Executable)); - sys.setAttribute("graal_python_home", context.getLanguage().getHome()); - sys.setAttribute("graal_python_core_home", PythonOptions.getOption(context, PythonOptions.CoreHome)); - sys.setAttribute("graal_python_stdlib_home", PythonOptions.getOption(context, PythonOptions.StdLibHome)); - sys.setAttribute("graal_python_opaque_filesystem", PythonOptions.getOption(context, PythonOptions.OpaqueFilesystem)); - sys.setAttribute("graal_python_opaque_filesystem_prefix", PythonOptions.getOption(context, PythonOptions.OpaqueFilesystemPrefixes)); - sys.setAttribute("__flags__", factory().createTuple(new Object[]{ - false, // bytes_warning - !PythonOptions.getFlag(context, PythonOptions.PythonOptimizeFlag), // debug - true, // dont_write_bytecode - false, // hash_randomization - PythonOptions.getFlag(context, PythonOptions.IgnoreEnvironmentFlag), // ignore_environment - PythonOptions.getFlag(context, PythonOptions.InspectFlag), // inspect - PythonOptions.getFlag(context, PythonOptions.TerminalIsInteractive), // interactive - !context.isExecutableAccessAllowed(), // isolated - PythonOptions.getFlag(context, PythonOptions.NoSiteFlag), // no_site - PythonOptions.getFlag(context, PythonOptions.NoUserSiteFlag), // no_user_site - PythonOptions.getFlag(context, PythonOptions.PythonOptimizeFlag), // optimize - PythonOptions.getFlag(context, PythonOptions.QuietFlag), // quiet - PythonOptions.getFlag(context, PythonOptions.VerboseFlag), // verbose - })); - - initializeSysPath(sys, args); - - return sys; - } - - private void initializeSysPath(PythonModule sys, String[] args) { - Env env = getContext().getEnv(); - String option = PythonOptions.getOption(getContext(), PythonOptions.PythonPath); - Object[] path; - int pathIdx = 0; - if (option.length() > 0) { - String[] split = option.split(PythonCore.PATH_SEPARATOR); - path = new Object[split.length + 3]; - System.arraycopy(split, 0, path, 0, split.length); - pathIdx = split.length; - } else { - path = new Object[3]; - } - path[pathIdx] = getScriptPath(env, args); - path[pathIdx + 1] = PythonCore.getStdlibHome(env); - path[pathIdx + 2] = PythonCore.getCoreHome(env) + PythonCore.FILE_SEPARATOR + "modules"; - PList sysPaths = factory().createList(path); - sys.setAttribute("path", sysPaths); - } - - private static String getScriptPath(Env env, String[] args) { - String scriptPath; - if (args.length > 0) { - String argv0 = args[0]; - if (argv0 != null && !argv0.startsWith("-") && !argv0.isEmpty()) { - TruffleFile scriptFile = env.getTruffleFile(argv0); - try { - scriptPath = scriptFile.getAbsoluteFile().getParent().getPath(); - } catch (SecurityException e) { - scriptPath = scriptFile.getParent().getPath(); - } - if (scriptPath == null) { - scriptPath = "."; - } - } else { - scriptPath = ""; - } - } else { - scriptPath = ""; - } - return scriptPath; - } - @TruffleBoundary public PythonModule lookupBuiltinModule(String name) { return builtinModules.get(name); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java index 2f9b9eb36f..23ef7a6c83 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java @@ -54,6 +54,10 @@ public abstract class PythonBuiltins { protected abstract List> getNodeFactories(); + /** + * Initialize everything that is truly independent of commandline arguments and that can be + * initialized and frozen into an SVM image. + */ public void initialize(PythonCore core) { if (builtinFunctions.size() > 0) { return; @@ -101,6 +105,14 @@ public void initialize(PythonCore core) { }); } + /** + * Run any actions that can only be run in the post-initialization step, that is, if we're + * actually going to start running rather than just pre-initializing. + */ + public void postInitialize(@SuppressWarnings("unused") PythonCore core) { + // nothing to do by default + } + private void initializeEachFactoryWith(BiConsumer, Builtin> func) { List> factories = getNodeFactories(); assert factories != null : "No factories found. Override getFactories() to resolve this."; @@ -150,5 +162,4 @@ protected Map> getB protected Map getBuiltinConstants() { return builtinConstants; } - } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 70f382d36a..3be2c688aa 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -57,6 +57,7 @@ import static com.oracle.graal.python.nodes.BuiltinNames.SUM; import static com.oracle.graal.python.nodes.BuiltinNames.__BREAKPOINT__; import static com.oracle.graal.python.nodes.BuiltinNames.__BUILTIN__; +import static com.oracle.graal.python.nodes.BuiltinNames.__DEBUG__; import static com.oracle.graal.python.nodes.BuiltinNames.__DUMP_TRUFFLE_AST__; import static com.oracle.graal.python.nodes.HiddenAttributes.ID_KEY; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__; @@ -158,6 +159,8 @@ import com.oracle.graal.python.nodes.util.CastToIntegerFromIndexNode; import com.oracle.graal.python.nodes.util.CastToStringNode; import com.oracle.graal.python.runtime.PythonContext; +import com.oracle.graal.python.runtime.PythonCore; +import com.oracle.graal.python.runtime.PythonOptions; import com.oracle.graal.python.runtime.PythonParser.ParserMode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.exception.PythonErrorType; @@ -196,6 +199,13 @@ protected List 0) { + String[] split = option.split(PythonCore.PATH_SEPARATOR); + path = new Object[split.length + 3]; + System.arraycopy(split, 0, path, 0, split.length); + pathIdx = split.length; + } else { + path = new Object[3]; + } + path[pathIdx] = getScriptPath(env, args); + path[pathIdx + 1] = PythonCore.getStdlibHome(env); + path[pathIdx + 2] = PythonCore.getCoreHome(env) + PythonCore.FILE_SEPARATOR + "modules"; + PList sysPaths = core.factory().createList(path); + sys.setAttribute("path", sysPaths); + } + + private static String getScriptPath(Env env, String[] args) { + String scriptPath; + if (args.length > 0) { + String argv0 = args[0]; + if (argv0 != null && !argv0.startsWith("-") && !argv0.isEmpty()) { + TruffleFile scriptFile = env.getTruffleFile(argv0); + try { + scriptPath = scriptFile.getAbsoluteFile().getParent().getPath(); + } catch (SecurityException e) { + scriptPath = scriptFile.getParent().getPath(); + } + if (scriptPath == null) { + scriptPath = "."; + } + } else { + scriptPath = ""; + } + } else { + scriptPath = ""; + } + return scriptPath; } static String getPythonArch() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 4a9a6adafc..b285935a0a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -247,22 +247,18 @@ public void patch(Env newEnv) { } private void setupRuntimeInformation() { - PythonModule sysModule = core.initializeSysModule(); - sysModules = (PDict) sysModule.getAttribute("modules"); - - builtinsModule = (PythonModule) sysModules.getItem("builtins"); - builtinsModule.setAttribute(__DEBUG__, !PythonOptions.getOption(core.getContext(), PythonOptions.PythonOptimizeFlag)); + builtinsModule = core.lookupBuiltinModule("builtins"); mainModule = core.factory().createPythonModule(__MAIN__); mainModule.setAttribute(__BUILTINS__, builtinsModule); mainModule.setDict(core.factory().createDictFixedStorage(mainModule)); + + PythonModule sysModule = core.lookupBuiltinModule("sys"); + sysModules = (PDict) sysModule.getAttribute("modules"); sysModules.setItem(__MAIN__, mainModule); + OpaqueBytes.initializeForNewContext(this); - executor.scheduleWithFixedDelay(new Runnable() { - public void run() { - triggerCollection = true; - } - }, COLLECTIONS_N_MILLISECONDS, COLLECTIONS_N_MILLISECONDS, TimeUnit.MILLISECONDS); + currentException = null; isInitialized = true; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java index 2722d5489a..3af3fc7128 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java @@ -57,12 +57,6 @@ public interface PythonCore extends ParserErrorCallback { */ public void initialize(PythonContext pythonContext); - /** - * Initialize the runtime information in the sys module, capturing command line arguments, - * executable paths and so on. - */ - public PythonModule initializeSysModule(); - /** * Run post-initialization code that needs a fully working Python environment. This will be run * eagerly when the context is initialized on the JVM or a new context is created on SVM, but is From 4e4867196c71f2fdb83180533f199d166222a4e4 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 11:12:21 +0100 Subject: [PATCH 006/202] introduce a per-context AsyncHandler for asynchronous actions and use it for weakreference queueing --- .../builtins/modules/GcModuleBuiltins.java | 15 +-- .../modules/WeakRefModuleBuiltins.java | 71 ++++++++++- .../objects/referencetype/PReferenceType.java | 38 ++---- .../nodes/function/FunctionRootNode.java | 10 +- .../graal/python/runtime/AsyncHandler.java | 115 ++++++++++++++++++ .../graal/python/runtime/PythonContext.java | 51 ++------ .../runtime/object/PythonObjectFactory.java | 5 +- 7 files changed, 214 insertions(+), 91 deletions(-) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java index 44e6240ec8..d229535217 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java @@ -35,14 +35,11 @@ import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.frame.VirtualFrame; @CoreFunctions(defineModule = "gc") public final class GcModuleBuiltins extends PythonBuiltins { @@ -56,15 +53,11 @@ protected List weakRefQueue = new ReferenceQueue<>(); + @Override protected List> getNodeFactories() { return WeakRefModuleBuiltinsFactory.getFactories(); } + private static class WeakrefCallbackAction implements AsyncHandler.AsyncAction { + private final WeakRefStorage reference; + + public WeakrefCallbackAction(PReferenceType.WeakRefStorage reference) { + this.reference = reference; + } + + public Object callable() { + return reference.getCallback(); + } + + public Object[] arguments() { + return new Object[]{reference.getRef()}; + } + } + + @Override + public void postInitialize(PythonCore core) { + super.postInitialize(core); + PythonModule weakrefModule = core.lookupBuiltinModule("_weakref"); + weakrefModule.setAttribute(weakRefQueueKey, weakRefQueue); + core.lookupType(PythonBuiltinClassType.PReferenceType).setAttribute(weakRefQueueKey, weakRefQueue); + + core.getContext().registerAsyncAction(() -> { + Reference reference = null; + try { + reference = weakRefQueue.remove(); + } catch (InterruptedException e) { + } + if (reference instanceof PReferenceType.WeakRefStorage) { + return new WeakrefCallbackAction((PReferenceType.WeakRefStorage) reference); + } else { + return null; + } + }); + } + // ReferenceType constructor @Builtin(name = "ReferenceType", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3, constructsClass = PythonBuiltinClassType.PReferenceType) @GenerateNodeFactory public abstract static class ReferenceTypeNode extends PythonBuiltinNode { + @Child ReadAttributeFromObjectNode readQueue = ReadAttributeFromObjectNode.create(); + @Specialization public PReferenceType refType(PythonClass cls, PythonObject pythonObject, PNone none) { - return factory().createReferenceType(cls, pythonObject, null); + return factory().createReferenceType(cls, pythonObject, null, getWeakReferenceQueue()); } @Specialization - public PReferenceType refType(PythonClass cls, PythonObject pythonObject, TruffleObject callback) { - return factory().createReferenceType(cls, pythonObject, callback); + public PReferenceType refType(PythonClass cls, PythonObject pythonObject, Object callback) { + return factory().createReferenceType(cls, pythonObject, callback, getWeakReferenceQueue()); + } + + private ReferenceQueue getWeakReferenceQueue() { + Object queueObject = readQueue.execute(getCore().lookupType(PythonBuiltinClassType.PReferenceType), weakRefQueueKey); + if (queueObject instanceof ReferenceQueue) { + @SuppressWarnings("unchecked") + ReferenceQueue queue = (ReferenceQueue) queueObject; + return queue; + } else { + throw new IllegalStateException("the weak reference queue was modified!"); + } } @Fallback diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/PReferenceType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/PReferenceType.java index 8dcc0ad089..2fd60636e4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/PReferenceType.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/referencetype/PReferenceType.java @@ -46,41 +46,25 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.interop.TruffleObject; public class PReferenceType extends PythonBuiltinObject { public static class WeakRefStorage extends WeakReference { - private final TruffleObject callback; + private final Object callback; private final PReferenceType ref; - public WeakRefStorage(PReferenceType ref, Object referent, TruffleObject callback, ReferenceQueue referenceQueue) { - super(referent, referenceQueue); + public WeakRefStorage(PReferenceType ref, Object referent, Object callback, ReferenceQueue queue) { + super(referent, queue); this.callback = callback; this.ref = ref; } - /** - * Run the callback (if any). - * - * @param callNode - must be inserted into the AST by the caller unless run on the slow path - */ - public void runCallback(VirtualFrame frame, CallNode callNode) { - if (callback != null) { - try { - // TODO: check: the referent must no longer be available at this - // point - callNode.execute(frame, callback, ref); - } catch (RuntimeException e) { - // TODO: Exceptions raised by the callback will be noted on the - // standard error output, but cannot be propagated; they are - // handled in exactly the same way as exceptions raised - // from an object’s __del__() method. - e.printStackTrace(); - } - } + public Object getCallback() { + return callback; + } + + public PReferenceType getRef() { + return ref; } } @@ -88,9 +72,9 @@ public void runCallback(VirtualFrame frame, CallNode callNode) { private int hash = -1; @TruffleBoundary - public PReferenceType(LazyPythonClass cls, Object pythonObject, TruffleObject callback, ReferenceQueue referenceQueue) { + public PReferenceType(LazyPythonClass cls, Object pythonObject, Object callback, ReferenceQueue queue) { super(cls); - this.store = new WeakRefStorage(this, pythonObject, callback, referenceQueue); + this.store = new WeakRefStorage(this, pythonObject, callback, queue); } public Object getCallback() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java index 6a29188c16..9565304e87 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java @@ -35,7 +35,6 @@ import com.oracle.graal.python.parser.ExecutionCellSlots; import com.oracle.graal.python.runtime.PythonContext; import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; @@ -144,14 +143,7 @@ private void initClosureAndCellVars(VirtualFrame frame) { @Override public Object execute(VirtualFrame frame) { - PythonContext pythonContext = contextRef.get(); - if (pythonContext.shouldTriggerCollection()) { - if (callNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - callNode = insert(CallNode.create()); - } - pythonContext.collectWeakReferences(frame, callNode); - } + contextRef.get().triggerAsyncActions(); initClosureAndCellVars(frame); return body.execute(frame); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java new file mode 100644 index 0000000000..9a8fcda77c --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -0,0 +1,115 @@ +package com.oracle.graal.python.runtime; + +import java.util.Arrays; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; + +import com.oracle.graal.python.PythonLanguage; +import com.oracle.graal.python.builtins.objects.frame.PFrame; +import com.oracle.graal.python.nodes.call.CallNode; +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node.Child; +import com.oracle.truffle.api.nodes.RootNode; + +/** + * A handler for asynchronous actions events that need to be handled on a main thread of execution, + * including signals and finalization. + */ +public class AsyncHandler { + /** + * An action to be run triggered by an asynchronous event. + */ + public interface AsyncAction { + /** + * The object to call via a standard Python call + */ + public Object callable(); + + /** + * The arguments to pass to the call + */ + public Object[] arguments(); + + /** + * If the arguments include an element for the currently executing frame upon which this + * async action is triggered, this method should return something >= 0. The array returned + * by {@link #arguments()} should have a space for the frame already. + */ + default int frameIndex() { + return -1; + } + } + + private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + private ConcurrentLinkedQueue scheduledActions = new ConcurrentLinkedQueue<>(); + private AtomicBoolean hasScheduledAction = new AtomicBoolean(false); + private static final int ASYNC_ACTION_DELAY = 3; + + private class AsyncRunnable implements Runnable { + private final Supplier actionSupplier; + + public AsyncRunnable(Supplier actionSupplier) { + this.actionSupplier = actionSupplier; + } + + public void run() { + AsyncAction asyncAction = actionSupplier.get(); + if (asyncAction != null) { + scheduledActions.add(asyncAction); + hasScheduledAction.set(true); + } + } + } + + private static class CallRootNode extends RootNode { + @Child CallNode callNode = CallNode.create(); + + protected CallRootNode(TruffleLanguage language) { + super(language); + } + + @Override + public Object execute(VirtualFrame frame) { + Object[] frameArguments = frame.getArguments(); + Object callable = frameArguments[0]; + Object arguments = Arrays.copyOfRange(frameArguments, 1, frameArguments.length); + return callNode.execute(frame, callable, arguments); + } + } + + private final CallTarget callTarget; + @Child CallNode callNode = CallNode.create(); + + AsyncHandler(PythonLanguage language) { + callTarget = Truffle.getRuntime().createCallTarget(new CallRootNode(language)); + } + + void registerAction(Supplier actionSupplier) { + executorService.scheduleWithFixedDelay(new AsyncRunnable(actionSupplier), ASYNC_ACTION_DELAY, ASYNC_ACTION_DELAY, TimeUnit.MILLISECONDS); + } + + void triggerAsyncActions(PFrame pFrame) { + if (hasScheduledAction.getAndSet(false)) { + CompilerDirectives.transferToInterpreter(); + // TODO: (tfel) - for now all async actions are slow path + for (AsyncAction action : scheduledActions) { + Object[] arguments = action.arguments(); + Object[] args = new Object[arguments.length + 1]; + System.arraycopy(arguments, 0, args, 1, arguments.length); + args[0] = action.callable(); + if (action.frameIndex() >= 0) { + args[action.frameIndex() + 1] = pFrame; + } + callTarget.call(args); + } + } + } +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index b285935a0a..89264920ad 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -27,20 +27,15 @@ import static com.oracle.graal.python.builtins.objects.thread.PThread.GRAALPYTHON_THREADS; import static com.oracle.graal.python.nodes.BuiltinNames.__BUILTINS__; -import static com.oracle.graal.python.nodes.BuiltinNames.__DEBUG__; import static com.oracle.graal.python.nodes.BuiltinNames.__MAIN__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__FILE__; import java.io.InputStream; import java.io.OutputStream; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; import java.util.HashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Supplier; import org.graalvm.options.OptionValues; @@ -50,8 +45,7 @@ import com.oracle.graal.python.builtins.objects.common.HashingStorage; import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.module.PythonModule; -import com.oracle.graal.python.builtins.objects.referencetype.PReferenceType; -import com.oracle.graal.python.nodes.call.CallNode; +import com.oracle.graal.python.runtime.AsyncHandler.AsyncAction; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CallTarget; @@ -61,7 +55,6 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; -import com.oracle.truffle.api.frame.VirtualFrame; public final class PythonContext { @@ -71,11 +64,6 @@ public final class PythonContext { private final HashMap atExitHooks = new HashMap<>(); private final AtomicLong globalId = new AtomicLong(Integer.MAX_VALUE * 2L + 4L); private final ThreadGroup threadGroup = new ThreadGroup(GRAALPYTHON_THREADS); - private final ReferenceQueue weakRefQueue = new ReferenceQueue<>(); - - private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); - private volatile boolean triggerCollection = false; - private static final int COLLECTIONS_N_MILLISECONDS = 5; // if set to 0 the VM will set it to whatever it likes private final AtomicLong pythonThreadStackSize = new AtomicLong(0); @@ -106,13 +94,17 @@ public final class PythonContext { /** The thread-local state object. */ private ThreadLocal customThreadState; + + // The context-local resources private final PosixResources resources; + private final AsyncHandler handler; public PythonContext(PythonLanguage language, TruffleLanguage.Env env, PythonCore core) { this.language = language; this.core = core; this.env = env; this.resources = new PosixResources(); + this.handler = new AsyncHandler(language); if (env == null) { this.in = System.in; this.out = System.out; @@ -336,31 +328,14 @@ public PosixResources getResources() { return resources; } - public ReferenceQueue getWeakReferenceQueue() { - return weakRefQueue; - } - - @TruffleBoundary - private Reference pollWeakReferenceQueue() { - return weakRefQueue.poll(); - } - - public boolean shouldTriggerCollection() { - if (triggerCollection) { - triggerCollection = false; - return true; - } else { - return false; - } + /** + * Trigger any pending asynchronous actions + */ + public void triggerAsyncActions() { + handler.triggerAsyncActions(); } - public boolean collectWeakReferences(VirtualFrame frame, CallNode callNode) { - Reference r = pollWeakReferenceQueue(); - if (r instanceof PReferenceType.WeakRefStorage) { - ((PReferenceType.WeakRefStorage) r).runCallback(frame, callNode); - return true; - } else { - return false; - } + public void registerAsyncAction(Supplier actionSupplier) { + handler.registerAction(actionSupplier); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index fa09288736..9bd709bab7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -25,6 +25,7 @@ */ package com.oracle.graal.python.runtime.object; +import java.lang.ref.ReferenceQueue; import java.math.BigInteger; import java.nio.file.DirectoryStream; import java.util.Map; @@ -557,8 +558,8 @@ public PMappingproxy createMappingproxy(LazyPythonClass cls, HashingStorage stor return trace(new PMappingproxy(cls, storage)); } - public PReferenceType createReferenceType(LazyPythonClass cls, Object object, TruffleObject callback) { - return trace(new PReferenceType(cls, object, callback, getContextRef().get().getWeakReferenceQueue())); + public PReferenceType createReferenceType(LazyPythonClass cls, Object object, Object callback, ReferenceQueue queue) { + return trace(new PReferenceType(cls, object, callback, queue)); } /* From a98f13d815a5e634b18aba10313064bd547918e1 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 12:17:32 +0100 Subject: [PATCH 007/202] update signal module to use the async handler to schedule signal delivery --- .../builtins/modules/GcModuleBuiltins.java | 5 +- .../modules/SignalModuleBuiltins.java | 104 ++++++++++++------ .../nodes/function/FunctionRootNode.java | 2 +- .../graal/python/runtime/PythonContext.java | 5 +- 4 files changed, 79 insertions(+), 37 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java index d229535217..14886bf518 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java @@ -40,6 +40,7 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; @CoreFunctions(defineModule = "gc") public final class GcModuleBuiltins extends PythonBuiltins { @@ -53,10 +54,10 @@ protected List signalHandlers = new Hashtable<>(); + private final static HiddenKey signalQueueKey = new HiddenKey("signalQueue"); + private final ConcurrentLinkedDeque signalQueue = new ConcurrentLinkedDeque<>(); + @Override protected List> getNodeFactories() { return SignalModuleBuiltinsFactory.getFactories(); @@ -90,6 +96,40 @@ public void initialize(PythonCore core) { } } + @Override + public void postInitialize(PythonCore core) { + super.postInitialize(core); + + PythonModule signalModule = core.lookupBuiltinModule("_signal"); + signalModule.setAttribute(signalQueueKey, signalQueue); + + core.getContext().registerAsyncAction(() -> { + return signalQueue.poll(); + }); + } + + private static class SignalTriggerAction implements AsyncHandler.AsyncAction { + private final Object callable; + private final int signum; + + SignalTriggerAction(Object callable, int signum) { + this.callable = callable; + this.signum = signum; + } + + public Object callable() { + return callable; + } + + public Object[] arguments() { + return new Object[]{signum, null}; + } + + public int frameIndex() { + return 1; + } + } + @Builtin(name = "alarm", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) @@ -146,14 +186,23 @@ Object defaultIntHandler(@SuppressWarnings("unused") Object[] args) { } } - @Builtin(name = "signal", fixedNumOfPositionalArgs = 2) + @Builtin(name = "signal", fixedNumOfPositionalArgs = 3, declaresExplicitSelf = true) @GenerateNodeFactory - abstract static class SignalNode extends PythonBinaryBuiltinNode { + abstract static class SignalNode extends PythonTernaryBuiltinNode { @Child CreateArgumentsNode createArgs = CreateArgumentsNode.create(); + private int getSignum(long signum) { + try { + return toIntExact(signum); + } catch (ArithmeticException ae) { + throw raise(PythonBuiltinClassType.OverflowError, "Python int too large to convert to C int"); + } + } + @Specialization @TruffleBoundary - Object signal(int signum, int id) { + Object signal(@SuppressWarnings("unused") PythonModule self, long signalNumber, int id) { + int signum = getSignum(signalNumber); Object retval; try { retval = Signals.setSignalHandler(signum, id); @@ -171,11 +220,17 @@ Object signal(int signum, int id) { return retval; } - private Object installSignalHandler(int signum, Object handler, RootCallTarget callTarget, Object[] arguments) { + @Specialization + @TruffleBoundary + Object signal(PythonModule self, long signalNumber, Object handler, + @Cached("create()") ReadAttributeFromObjectNode readNode) { + int signum = getSignum(signalNumber); + ConcurrentLinkedDeque queue = getQueue(self, readNode); Object retval; + SignalTriggerAction signalTrigger = new SignalTriggerAction(handler, signum); try { retval = Signals.setSignalHandler(signum, () -> { - callTarget.call(arguments); + queue.add(signalTrigger); }); } catch (IllegalArgumentException e) { throw raise(PythonErrorType.ValueError, e); @@ -190,30 +245,15 @@ private Object installSignalHandler(int signum, Object handler, RootCallTarget c signalHandlers.put(signum, handler); return retval; } - // TODO: This needs to be fixed, any object with a "__call__" should work - // TODO: the second argument should be the interrupted, currently executing frame - // we'll get that when we switch to executing these handlers (just like finalizers) - // on the main thread - @Specialization - @TruffleBoundary - Object signal(int signum, PBuiltinFunction handler) { - return installSignalHandler(signum, handler, handler.getCallTarget(), createArgs.execute(new Object[]{signum, PNone.NONE})); - } - - @Specialization - @TruffleBoundary - Object signal(int signum, PFunction handler) { - return installSignalHandler(signum, handler, handler.getCallTarget(), createArgs.execute(new Object[]{signum, PNone.NONE})); - } - - @Specialization - @TruffleBoundary - Object signal(long signum, PFunction handler) { - try { - return installSignalHandler(toIntExact(signum), handler, handler.getCallTarget(), createArgs.execute(new Object[]{signum, PNone.NONE})); - } catch (ArithmeticException ae) { - throw raise(PythonBuiltinClassType.OverflowError, "Python int too large to convert to C int"); + private static ConcurrentLinkedDeque getQueue(PythonModule self, ReadAttributeFromObjectNode readNode) { + Object queueObject = readNode.execute(self, signalQueueKey); + if (queueObject instanceof ConcurrentLinkedDeque) { + @SuppressWarnings("unchecked") + ConcurrentLinkedDeque queue = (ConcurrentLinkedDeque) queueObject; + return queue; + } else { + throw new IllegalStateException("the signal trigger queue was modified!"); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java index 9565304e87..c5f71ce221 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java @@ -143,7 +143,7 @@ private void initClosureAndCellVars(VirtualFrame frame) { @Override public Object execute(VirtualFrame frame) { - contextRef.get().triggerAsyncActions(); + contextRef.get().triggerAsyncActions(frame); initClosureAndCellVars(frame); return body.execute(frame); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 89264920ad..744510cb23 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -55,6 +55,7 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; +import com.oracle.truffle.api.frame.Frame; public final class PythonContext { @@ -331,8 +332,8 @@ public PosixResources getResources() { /** * Trigger any pending asynchronous actions */ - public void triggerAsyncActions() { - handler.triggerAsyncActions(); + public void triggerAsyncActions(Frame frame) { + handler.triggerAsyncActions(core.factory().createPFrame(frame)); } public void registerAsyncAction(Supplier actionSupplier) { From addbde0ba5a19c8462d164b60d06c96fe98d1449 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 14:02:31 +0100 Subject: [PATCH 008/202] avoid creating a PFrame eagerly and also avoid processing async triggers from multiple threads --- .../graal/python/runtime/AsyncHandler.java | 40 ++++++++++++------- .../graal/python/runtime/PythonContext.java | 2 +- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 9a8fcda77c..c909040285 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -6,15 +6,17 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicMarkableReference; import java.util.function.Supplier; import com.oracle.graal.python.PythonLanguage; -import com.oracle.graal.python.builtins.objects.frame.PFrame; import com.oracle.graal.python.nodes.call.CallNode; +import com.oracle.graal.python.runtime.object.PythonObjectFactory; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.RootNode; @@ -49,7 +51,7 @@ default int frameIndex() { } private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); - private ConcurrentLinkedQueue scheduledActions = new ConcurrentLinkedQueue<>(); + private AtomicMarkableReference> scheduledActions = new AtomicMarkableReference<>(new ConcurrentLinkedQueue<>(), false); private AtomicBoolean hasScheduledAction = new AtomicBoolean(false); private static final int ASYNC_ACTION_DELAY = 3; @@ -63,7 +65,7 @@ public AsyncRunnable(Supplier actionSupplier) { public void run() { AsyncAction asyncAction = actionSupplier.get(); if (asyncAction != null) { - scheduledActions.add(asyncAction); + scheduledActions.getReference().add(asyncAction); hasScheduledAction.set(true); } } @@ -80,7 +82,7 @@ protected CallRootNode(TruffleLanguage language) { public Object execute(VirtualFrame frame) { Object[] frameArguments = frame.getArguments(); Object callable = frameArguments[0]; - Object arguments = Arrays.copyOfRange(frameArguments, 1, frameArguments.length); + Object[] arguments = Arrays.copyOfRange(frameArguments, 1, frameArguments.length); return callNode.execute(frame, callable, arguments); } } @@ -96,19 +98,29 @@ void registerAction(Supplier actionSupplier) { executorService.scheduleWithFixedDelay(new AsyncRunnable(actionSupplier), ASYNC_ACTION_DELAY, ASYNC_ACTION_DELAY, TimeUnit.MILLISECONDS); } - void triggerAsyncActions(PFrame pFrame) { + void triggerAsyncActions(Frame frame, PythonObjectFactory factory) { if (hasScheduledAction.getAndSet(false)) { - CompilerDirectives.transferToInterpreter(); // TODO: (tfel) - for now all async actions are slow path - for (AsyncAction action : scheduledActions) { - Object[] arguments = action.arguments(); - Object[] args = new Object[arguments.length + 1]; - System.arraycopy(arguments, 0, args, 1, arguments.length); - args[0] = action.callable(); - if (action.frameIndex() >= 0) { - args[action.frameIndex() + 1] = pFrame; + CompilerDirectives.transferToInterpreter(); + ConcurrentLinkedQueue actions = scheduledActions.getReference(); + if (scheduledActions.compareAndSet(actions, actions, false, true)) { + // if we're here, we marked the scheduled actions as executing, so no other thread + // will enter this branch (other threads would just return) + try { + for (AsyncAction action : actions) { + Object[] arguments = action.arguments(); + Object[] args = new Object[arguments.length + 1]; + System.arraycopy(arguments, 0, args, 1, arguments.length); + args[0] = action.callable(); + if (action.frameIndex() >= 0) { + args[action.frameIndex() + 1] = factory.createPFrame(frame); + } + callTarget.call(args); + } + } finally { + // unmark, we're done here + scheduledActions.compareAndSet(actions, actions, true, false); } - callTarget.call(args); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 744510cb23..27eec0f7ac 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -333,7 +333,7 @@ public PosixResources getResources() { * Trigger any pending asynchronous actions */ public void triggerAsyncActions(Frame frame) { - handler.triggerAsyncActions(core.factory().createPFrame(frame)); + handler.triggerAsyncActions(frame, core.factory()); } public void registerAsyncAction(Supplier actionSupplier) { From 4049ef6890ea29e00ff953bda96032176934a992 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 14:41:50 +0100 Subject: [PATCH 009/202] pass the node from which async actions are triggered so we get a frame location --- .../builtins/modules/GcModuleBuiltins.java | 2 +- .../python/builtins/objects/frame/PFrame.java | 9 ++++ .../nodes/function/FunctionRootNode.java | 2 +- .../graal/python/runtime/AsyncHandler.java | 51 ++++++++++--------- .../graal/python/runtime/PythonContext.java | 5 +- .../runtime/object/PythonObjectFactory.java | 4 ++ 6 files changed, 45 insertions(+), 28 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java index 14886bf518..e2eb0d3a56 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java @@ -57,7 +57,7 @@ abstract static class GcCollectNode extends PythonBuiltinNode { int collect(VirtualFrame frame) { doGc(); // collect some weak references now - getContext().triggerAsyncActions(frame); + getContext().triggerAsyncActions(frame, this); return 0; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java index dbc86587b1..ab50ea50fe 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java @@ -77,6 +77,15 @@ public PFrame(LazyPythonClass cls, Frame frame) { this.inClassScope = PArguments.getSpecialArgument(frame) instanceof ClassBodyRootNode; } + public PFrame(LazyPythonClass cls, Frame frame, Node location) { + super(cls); + this.exception = null; + this.index = -1; + this.frame = frame; + this.location = location; + this.inClassScope = PArguments.getSpecialArgument(frame) instanceof ClassBodyRootNode; + } + public PFrame(LazyPythonClass cls, Frame frame, Object locals) { super(cls); this.exception = null; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java index c5f71ce221..c1b5b3a0bb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java @@ -143,7 +143,7 @@ private void initClosureAndCellVars(VirtualFrame frame) { @Override public Object execute(VirtualFrame frame) { - contextRef.get().triggerAsyncActions(frame); + contextRef.get().triggerAsyncActions(frame, this); initClosureAndCellVars(frame); return body.execute(frame); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index c909040285..96c2b5c580 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -6,7 +6,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicMarkableReference; import java.util.function.Supplier; import com.oracle.graal.python.PythonLanguage; @@ -18,6 +17,7 @@ import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.RootNode; @@ -51,9 +51,10 @@ default int frameIndex() { } private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); - private AtomicMarkableReference> scheduledActions = new AtomicMarkableReference<>(new ConcurrentLinkedQueue<>(), false); + private ConcurrentLinkedQueue scheduledActions = new ConcurrentLinkedQueue<>(); private AtomicBoolean hasScheduledAction = new AtomicBoolean(false); - private static final int ASYNC_ACTION_DELAY = 3; + private AtomicBoolean executingActions = new AtomicBoolean(false); + private static final int ASYNC_ACTION_DELAY = 100; private class AsyncRunnable implements Runnable { private final Supplier actionSupplier; @@ -65,7 +66,7 @@ public AsyncRunnable(Supplier actionSupplier) { public void run() { AsyncAction asyncAction = actionSupplier.get(); if (asyncAction != null) { - scheduledActions.getReference().add(asyncAction); + scheduledActions.add(asyncAction); hasScheduledAction.set(true); } } @@ -98,30 +99,32 @@ void registerAction(Supplier actionSupplier) { executorService.scheduleWithFixedDelay(new AsyncRunnable(actionSupplier), ASYNC_ACTION_DELAY, ASYNC_ACTION_DELAY, TimeUnit.MILLISECONDS); } - void triggerAsyncActions(Frame frame, PythonObjectFactory factory) { - if (hasScheduledAction.getAndSet(false)) { - // TODO: (tfel) - for now all async actions are slow path - CompilerDirectives.transferToInterpreter(); - ConcurrentLinkedQueue actions = scheduledActions.getReference(); - if (scheduledActions.compareAndSet(actions, actions, false, true)) { - // if we're here, we marked the scheduled actions as executing, so no other thread - // will enter this branch (other threads would just return) - try { - for (AsyncAction action : actions) { - Object[] arguments = action.arguments(); - Object[] args = new Object[arguments.length + 1]; - System.arraycopy(arguments, 0, args, 1, arguments.length); - args[0] = action.callable(); - if (action.frameIndex() >= 0) { - args[action.frameIndex() + 1] = factory.createPFrame(frame); - } + void triggerAsyncActions(Frame frame, Node location, PythonObjectFactory factory) { + if (executingActions.compareAndSet(false, true)) { + if (hasScheduledAction.compareAndSet(true, false)) { + CompilerDirectives.transferToInterpreter(); + // TODO: (tfel) - for now all async actions are slow path + ConcurrentLinkedQueue actions = scheduledActions; + for (AsyncAction action : actions) { + Object[] arguments = action.arguments(); + Object[] args = new Object[arguments.length + 1]; + System.arraycopy(arguments, 0, args, 1, arguments.length); + args[0] = action.callable(); + if (action.frameIndex() >= 0) { + args[action.frameIndex() + 1] = factory.createPFrame(frame, location); + } + try { callTarget.call(args); + } catch (RuntimeException e) { + // we cannot raise the exception here (well, we could, but CPython + // doesn't), so we do what they do and just print it + + // TODO: print a nice Python stacktrace + e.printStackTrace(); } - } finally { - // unmark, we're done here - scheduledActions.compareAndSet(actions, actions, true, false); } } + executingActions.set(false); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 27eec0f7ac..f2dac2c2eb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -56,6 +56,7 @@ import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.nodes.Node; public final class PythonContext { @@ -332,8 +333,8 @@ public PosixResources getResources() { /** * Trigger any pending asynchronous actions */ - public void triggerAsyncActions(Frame frame) { - handler.triggerAsyncActions(frame, core.factory()); + public void triggerAsyncActions(Frame frame, Node location) { + handler.triggerAsyncActions(frame, location, core.factory()); } public void registerAsyncAction(Supplier actionSupplier) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index 9bd709bab7..6b28160ca7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -574,6 +574,10 @@ public PFrame createPFrame(Frame frame) { return trace(new PFrame(PythonBuiltinClassType.PFrame, frame)); } + public PFrame createPFrame(Frame frame, Node location) { + return trace(new PFrame(PythonBuiltinClassType.PFrame, frame, location)); + } + public PFrame createPFrame(Frame frame, Object locals) { return trace(new PFrame(PythonBuiltinClassType.PFrame, frame, locals)); } From 4f11e43c94924ff9b8fcd28b738f6bbb4f279e80 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 15:02:46 +0100 Subject: [PATCH 010/202] last step, signal handlers actually need to have a full stack available, so we'll create a full frame with backrefs --- .../src/tests/test_signal.py | 70 +++++-------------- .../src/tests/test_weakref.py | 2 +- .../builtins/modules/GcModuleBuiltins.java | 5 +- .../builtins/modules/SysModuleBuiltins.java | 7 +- .../python/builtins/objects/frame/PFrame.java | 9 --- .../nodes/function/FunctionRootNode.java | 2 +- .../graal/python/runtime/AsyncHandler.java | 28 ++++---- .../graal/python/runtime/PythonContext.java | 6 +- .../runtime/object/PythonObjectFactory.java | 4 -- 9 files changed, 43 insertions(+), 90 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py b/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py index 9297ea15aa..402bb046be 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py @@ -37,69 +37,31 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -def skip_test_alarm(): - # (tfel): this test is very brittle, because it is supposed to work with our - # first, very primitive implementation of signal handlers, which does not - # allow Python code to run in the handler. So we rely on a side-effect on an - # open file descriptor instead. +def test_alarm2(): try: import _signal except ImportError: import signal as _signal - import posix import time - import sys - # first, we start opening files until the fd is the same as SIGALRM - fds = [] - dupd_fd = None - fd = None + triggered = None - try: - fd = posix.open(__file__, posix.O_RDONLY) - while fd < _signal.SIGALRM: - fds.append(fd) - fd = posix.open(__file__, posix.O_RDONLY) - - if fd > _signal.SIGALRM: - dupd_fd = posix.dup(_signal.SIGALRM) - posix.close(_signal.SIGALRM) - fd = posix.open(__file__, posix.O_RDONLY) - - # close the unneeded fds - for oldfd in fds: - posix.close(oldfd) - - assert fd == _signal.SIGALRM, "fd not equal to SIGALRM" + def handler(signal, frame): + nonlocal triggered + triggered = (signal, frame) - # temporary: graalpython doesn't check the argcount for the handler atm - if sys.implementation.name == "graalpython": - handler = posix.close - else: - handler = lambda s,f: posix.close(s) + oldhandler = _signal.signal(_signal.SIGALRM, handler) + assert oldhandler == _signal.SIG_DFL, "oldhandler != SIG_DFL" + assert _signal.getsignal(_signal.SIGALRM) is handler, "getsignal handler != handler" - oldhandler = _signal.signal(_signal.SIGALRM, handler) - assert oldhandler == _signal.SIG_DFL, "oldhandler != SIG_DFL" - assert _signal.getsignal(_signal.SIGALRM) is handler, "getsignal handler != handler" + _signal.alarm(1) - # schedule the alarm signal, that will trigger the handler, which - # will in turn close our file - _signal.alarm(1) + def dummy(): + pass - # wait for the signal to come in and be handled - time.sleep(1.5) + while not triggered: + dummy() + time.sleep(0.5) - # check for the side-effect - try: - posix.read(fd, 1) - except OSError: - assert True - else: - assert False, "file is still open" - finally: - if dupd_fd is not None: - try: - posix.close(fd) - except OSError: - pass - posix.dup(dupd_fd) # duplicates back into just free'd fd + assert triggered[0] == _signal.SIGALRM + assert triggered[1].f_code.co_name == "test_alarm2", triggered[1].f_code.co_name diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py b/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py index 652f1b49ac..2a66dd2066 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_weakref.py @@ -50,6 +50,6 @@ class A(): pass cleaned_up = False -def cleanup(_=None): +def cleanup(ref): global cleaned_up cleaned_up = True diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java index e2eb0d3a56..d229535217 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java @@ -40,7 +40,6 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.frame.VirtualFrame; @CoreFunctions(defineModule = "gc") public final class GcModuleBuiltins extends PythonBuiltins { @@ -54,10 +53,10 @@ protected List= 0. The array returned - * by {@link #arguments()} should have a space for the frame already. + * If the arguments need to include an element for the currently executing frame upon which + * this async action is triggered, this method should return something >= 0. The array + * returned by {@link #arguments()} should have a space for the frame already, as it will be + * filled in without growing the arguments array. */ default int frameIndex() { return -1; @@ -74,6 +73,7 @@ public void run() { private static class CallRootNode extends RootNode { @Child CallNode callNode = CallNode.create(); + @Child GetFrameNode getFrameNode = GetFrameNode.create(); protected CallRootNode(TruffleLanguage language) { super(language); @@ -83,7 +83,11 @@ protected CallRootNode(TruffleLanguage language) { public Object execute(VirtualFrame frame) { Object[] frameArguments = frame.getArguments(); Object callable = frameArguments[0]; - Object[] arguments = Arrays.copyOfRange(frameArguments, 1, frameArguments.length); + int frameIndex = (int) frameArguments[1]; + Object[] arguments = Arrays.copyOfRange(frameArguments, 2, frameArguments.length); + if (frameIndex >= 0) { + arguments[frameIndex] = getFrameNode.execute(2); + } return callNode.execute(frame, callable, arguments); } } @@ -99,7 +103,7 @@ void registerAction(Supplier actionSupplier) { executorService.scheduleWithFixedDelay(new AsyncRunnable(actionSupplier), ASYNC_ACTION_DELAY, ASYNC_ACTION_DELAY, TimeUnit.MILLISECONDS); } - void triggerAsyncActions(Frame frame, Node location, PythonObjectFactory factory) { + void triggerAsyncActions() { if (executingActions.compareAndSet(false, true)) { if (hasScheduledAction.compareAndSet(true, false)) { CompilerDirectives.transferToInterpreter(); @@ -107,12 +111,10 @@ void triggerAsyncActions(Frame frame, Node location, PythonObjectFactory factory ConcurrentLinkedQueue actions = scheduledActions; for (AsyncAction action : actions) { Object[] arguments = action.arguments(); - Object[] args = new Object[arguments.length + 1]; - System.arraycopy(arguments, 0, args, 1, arguments.length); + Object[] args = new Object[arguments.length + 2]; + System.arraycopy(arguments, 0, args, 2, arguments.length); args[0] = action.callable(); - if (action.frameIndex() >= 0) { - args[action.frameIndex() + 1] = factory.createPFrame(frame, location); - } + args[1] = action.frameIndex(); try { callTarget.call(args); } catch (RuntimeException e) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index f2dac2c2eb..89264920ad 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -55,8 +55,6 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; -import com.oracle.truffle.api.frame.Frame; -import com.oracle.truffle.api.nodes.Node; public final class PythonContext { @@ -333,8 +331,8 @@ public PosixResources getResources() { /** * Trigger any pending asynchronous actions */ - public void triggerAsyncActions(Frame frame, Node location) { - handler.triggerAsyncActions(frame, location, core.factory()); + public void triggerAsyncActions() { + handler.triggerAsyncActions(); } public void registerAsyncAction(Supplier actionSupplier) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index 6b28160ca7..9bd709bab7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -574,10 +574,6 @@ public PFrame createPFrame(Frame frame) { return trace(new PFrame(PythonBuiltinClassType.PFrame, frame)); } - public PFrame createPFrame(Frame frame, Node location) { - return trace(new PFrame(PythonBuiltinClassType.PFrame, frame, location)); - } - public PFrame createPFrame(Frame frame, Object locals) { return trace(new PFrame(PythonBuiltinClassType.PFrame, frame, locals)); } From f8935c7fa75d670188e8cad55a7245cec7c5ead0 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 15:12:46 +0100 Subject: [PATCH 011/202] fix test --- .../graal/python/builtins/modules/SignalModuleBuiltins.java | 1 + 1 file changed, 1 insertion(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java index 7c45043f45..b0d37ae031 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java @@ -186,6 +186,7 @@ Object defaultIntHandler(@SuppressWarnings("unused") Object[] args) { } } + @TypeSystemReference(PythonArithmeticTypes.class) @Builtin(name = "signal", fixedNumOfPositionalArgs = 3, declaresExplicitSelf = true) @GenerateNodeFactory abstract static class SignalNode extends PythonTernaryBuiltinNode { From 6f3d57d4905c1fc0a40928511ca7f4bb77040f90 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 15:21:37 +0100 Subject: [PATCH 012/202] fix copyrights, remove dead code --- .../src/tests/test_signal.py | 2 +- .../graal/python/builtins/PythonBuiltins.java | 2 +- .../python/builtins/objects/frame/PFrame.java | 2 +- .../nodes/function/FunctionRootNode.java | 4 +- .../graal/python/runtime/AsyncHandler.java | 40 +++++++++++++++++++ .../graal/python/runtime/PythonCore.java | 2 +- 6 files changed, 45 insertions(+), 7 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py b/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py index 402bb046be..4a9f2d2241 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java index 23ef7a6c83..e50e792a00 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java index dbc86587b1..e15b068d77 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java index 9565304e87..824975b480 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -29,7 +29,6 @@ import com.oracle.graal.python.builtins.objects.cell.PCell; import com.oracle.graal.python.builtins.objects.function.PArguments; import com.oracle.graal.python.nodes.PClosureFunctionRootNode; -import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.graal.python.nodes.cell.CellSupplier; import com.oracle.graal.python.nodes.expression.ExpressionNode; import com.oracle.graal.python.parser.ExecutionCellSlots; @@ -60,7 +59,6 @@ public class FunctionRootNode extends PClosureFunctionRootNode implements CellSu private boolean isRewritten = false; @Child private ExpressionNode body; - @Child private CallNode callNode; private ExpressionNode uninitializedBody; public FunctionRootNode(PythonLanguage language, SourceSection sourceSection, String functionName, boolean isGenerator, FrameDescriptor frameDescriptor, ExpressionNode body, diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 325c42d3fd..e944a68127 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -1,3 +1,43 @@ +/* + * Copyright (c) 2019, 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 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ package com.oracle.graal.python.runtime; import java.util.Arrays; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java index 3af3fc7128..8b7c8a615e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. From 1e947f2cbe1976666588277274416d88f5f035b0 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 15:24:52 +0100 Subject: [PATCH 013/202] minimize diff a bit --- .../src/com/oracle/graal/python/runtime/PythonContext.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 89264920ad..129930697c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -239,14 +239,15 @@ public void patch(Env newEnv) { } private void setupRuntimeInformation() { + PythonModule sysModule = core.lookupBuiltinModule("sys"); + sysModules = (PDict) sysModule.getAttribute("modules"); + builtinsModule = core.lookupBuiltinModule("builtins"); mainModule = core.factory().createPythonModule(__MAIN__); mainModule.setAttribute(__BUILTINS__, builtinsModule); mainModule.setDict(core.factory().createDictFixedStorage(mainModule)); - PythonModule sysModule = core.lookupBuiltinModule("sys"); - sysModules = (PDict) sysModule.getAttribute("modules"); sysModules.setItem(__MAIN__, mainModule); OpaqueBytes.initializeForNewContext(this); From 96c00caf577c0fda9a50b2fb967245ad00fd44c6 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 15:24:59 +0100 Subject: [PATCH 014/202] choose a reasonably low but otherwise arbitrary time for scheduling async actions --- .../src/com/oracle/graal/python/runtime/AsyncHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index e944a68127..6e7f1b303b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -93,7 +93,7 @@ default int frameIndex() { private ConcurrentLinkedQueue scheduledActions = new ConcurrentLinkedQueue<>(); private AtomicBoolean hasScheduledAction = new AtomicBoolean(false); private AtomicBoolean executingActions = new AtomicBoolean(false); - private static final int ASYNC_ACTION_DELAY = 100; + private static final int ASYNC_ACTION_DELAY = 15; // chosen by a fair D20 dice roll private class AsyncRunnable implements Runnable { private final Supplier actionSupplier; From 4844de38774923fe8011805044a0b22cfce68018 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 16:44:50 +0100 Subject: [PATCH 015/202] wait on the signalQueue so we don't spin on checking if signals arrived --- .../python/builtins/modules/SignalModuleBuiltins.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java index b0d37ae031..d2bc49cdf6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java @@ -104,6 +104,12 @@ public void postInitialize(PythonCore core) { signalModule.setAttribute(signalQueueKey, signalQueue); core.getContext().registerAsyncAction(() -> { + synchronized (signalQueue) { + try { + signalQueue.wait(); + } catch (InterruptedException e) { + } + } return signalQueue.poll(); }); } @@ -232,6 +238,9 @@ Object signal(PythonModule self, long signalNumber, Object handler, try { retval = Signals.setSignalHandler(signum, () -> { queue.add(signalTrigger); + synchronized (queue) { + queue.notify(); + } }); } catch (IllegalArgumentException e) { throw raise(PythonErrorType.ValueError, e); From 3fc0093dffbd97cdbee65ddc28e9d6328be0b513 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 24 Jan 2019 16:45:25 +0100 Subject: [PATCH 016/202] since we don't use spinning executors, we need to use a thread pool --- .../src/com/oracle/graal/python/runtime/AsyncHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 6e7f1b303b..6f8b60abf7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -89,7 +89,7 @@ default int frameIndex() { } } - private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); private ConcurrentLinkedQueue scheduledActions = new ConcurrentLinkedQueue<>(); private AtomicBoolean hasScheduledAction = new AtomicBoolean(false); private AtomicBoolean executingActions = new AtomicBoolean(false); From 4cb6a858f4d4df17bb644e9b01f099e251508c30 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 25 Jan 2019 13:33:09 +0100 Subject: [PATCH 017/202] allow arbitrary objects in python weakrefs --- .../python/builtins/modules/WeakRefModuleBuiltins.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java index 23189f7d54..86b6d19992 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java @@ -126,13 +126,13 @@ public abstract static class ReferenceTypeNode extends PythonBuiltinNode { @Child ReadAttributeFromObjectNode readQueue = ReadAttributeFromObjectNode.create(); @Specialization - public PReferenceType refType(PythonClass cls, PythonObject pythonObject, PNone none) { - return factory().createReferenceType(cls, pythonObject, null, getWeakReferenceQueue()); + public PReferenceType refType(PythonClass cls, Object object, PNone none) { + return factory().createReferenceType(cls, object, null, getWeakReferenceQueue()); } @Specialization - public PReferenceType refType(PythonClass cls, PythonObject pythonObject, Object callback) { - return factory().createReferenceType(cls, pythonObject, callback, getWeakReferenceQueue()); + public PReferenceType refType(PythonClass cls, Object object, Object callback) { + return factory().createReferenceType(cls, object, callback, getWeakReferenceQueue()); } private ReferenceQueue getWeakReferenceQueue() { From 61bcc3707930e625fe8cef115c2c8b88f85f54c4 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 25 Jan 2019 13:34:30 +0100 Subject: [PATCH 018/202] don't trigger actions in inlined function calls --- .../oracle/graal/python/nodes/function/FunctionRootNode.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java index 824975b480..c9de8a641c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java @@ -34,6 +34,7 @@ import com.oracle.graal.python.parser.ExecutionCellSlots; import com.oracle.graal.python.runtime.PythonContext; import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; @@ -141,7 +142,9 @@ private void initClosureAndCellVars(VirtualFrame frame) { @Override public Object execute(VirtualFrame frame) { - contextRef.get().triggerAsyncActions(); + if (CompilerDirectives.inInterpreter() || CompilerDirectives.inCompilationRoot()) { + contextRef.get().triggerAsyncActions(); + } initClosureAndCellVars(frame); return body.execute(frame); } From 899e2483d446765b94ceff0e30cfedd957ce42bc Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 09:29:30 +0100 Subject: [PATCH 019/202] check that async action has a callable --- .../graal/python/runtime/AsyncHandler.java | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 6f8b60abf7..95ac564687 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -150,19 +150,22 @@ void triggerAsyncActions() { // TODO: (tfel) - for now all async actions are slow path ConcurrentLinkedQueue actions = scheduledActions; for (AsyncAction action : actions) { - Object[] arguments = action.arguments(); - Object[] args = new Object[arguments.length + 2]; - System.arraycopy(arguments, 0, args, 2, arguments.length); - args[0] = action.callable(); - args[1] = action.frameIndex(); - try { - callTarget.call(args); - } catch (RuntimeException e) { - // we cannot raise the exception here (well, we could, but CPython - // doesn't), so we do what they do and just print it - - // TODO: print a nice Python stacktrace - e.printStackTrace(); + Object callable = action.callable(); + if (callable != null) { + Object[] arguments = action.arguments(); + Object[] args = new Object[arguments.length + 2]; + System.arraycopy(arguments, 0, args, 2, arguments.length); + args[0] = callable; + args[1] = action.frameIndex(); + try { + callTarget.call(args); + } catch (RuntimeException e) { + // we cannot raise the exception here (well, we could, but CPython + // doesn't), so we do what they do and just print it + + // TODO: print a nice Python stacktrace + e.printStackTrace(); + } } } } From c3a2cc2a5af2afa10b75f3aac86480c9d966b1f4 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 10:07:24 +0100 Subject: [PATCH 020/202] if a PFrame has an attached exception, we can get the RootNode from that if no call location is available --- .../builtins/objects/frame/FrameBuiltins.java | 13 ++++--------- .../graal/python/builtins/objects/frame/PFrame.java | 12 ++++++++++++ .../python/runtime/object/PythonObjectFactory.java | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java index 3314d1294f..87ad0a22ee 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java @@ -51,7 +51,6 @@ import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.Frame; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -135,16 +134,12 @@ Object get(PFrame self) { public abstract static class GetCodeNode extends PythonBuiltinNode { @Specialization Object get(PFrame self) { - Node callNode = self.getCallNode(); - if (callNode == null) { - return PNone.NONE; - } - RootNode rootNode = callNode.getRootNode(); - if (rootNode == null) { - return PNone.NONE; - } else { + RootNode rootNode = self.getTarget(); + if (rootNode != null) { return factory().createCode(rootNode); } + return factory().createCode(PythonBuiltinClassType.PCode, -1, -1, -1, -1, -1, new byte[0], new Object[0], new Object[0], new Object[0], new Object[0], new Object[0], "", + "", -1, new byte[0]); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java index e15b068d77..527f3b5320 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java @@ -55,6 +55,7 @@ import com.oracle.truffle.api.TruffleStackTraceElement; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.SourceSection; public final class PFrame extends PythonBuiltinObject { @@ -198,4 +199,15 @@ public boolean hasFrame() { public boolean inClassScope() { return inClassScope; } + + @TruffleBoundary + public RootNode getTarget() { + if (location != null) { + return location.getRootNode(); + } else if (exception != null) { + return exception.getStackTrace().get(index).getTarget().getRootNode(); + } else { + return null; + } + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index 9bd709bab7..8697b853cb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -765,7 +765,7 @@ public PCode createCode(RootNode result) { return trace(new PCode(PythonBuiltinClassType.PCode, result, getCore())); } - public PCode createCode(PythonClass cls, int argcount, int kwonlyargcount, + public PCode createCode(LazyPythonClass cls, int argcount, int kwonlyargcount, int nlocals, int stacksize, int flags, byte[] codestring, Object[] constants, Object[] names, Object[] varnames, Object[] freevars, Object[] cellvars, From e049178311dad0f1c179376db2b0b51e9ee486e6 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 10:08:34 +0100 Subject: [PATCH 021/202] trigger async actions in loops --- .../com.oracle.graal.python.test/src/tests/test_signal.py | 6 +----- .../src/com/oracle/graal/python/nodes/control/ForNode.java | 3 ++- .../com/oracle/graal/python/nodes/control/WhileNode.java | 7 ++++--- .../graal/python/nodes/generator/GeneratorForNode.java | 5 ++++- .../graal/python/nodes/generator/GeneratorWhileNode.java | 5 ++++- .../src/com/oracle/graal/python/runtime/AsyncHandler.java | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py b/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py index 4a9f2d2241..983833fe95 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_signal.py @@ -56,12 +56,8 @@ def handler(signal, frame): _signal.alarm(1) - def dummy(): - pass - while not triggered: - dummy() time.sleep(0.5) assert triggered[0] == _signal.SIGALRM - assert triggered[1].f_code.co_name == "test_alarm2", triggered[1].f_code.co_name + assert triggered[1].f_code.co_name == "test_alarm2", triggered[1].f_code diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/ForNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/ForNode.java index b7bc63529a..82e93ba581 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/ForNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/ForNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -71,6 +71,7 @@ public boolean executeRepeating(VirtualFrame frame) { throw raise(PythonErrorType.RuntimeError, "internal error: unexpected frame slot type"); } body.executeVoid(frame); + getContext().triggerAsyncActions(); return true; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/WhileNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/WhileNode.java index 00e1820c11..844b994d7b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/WhileNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/WhileNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -25,16 +25,16 @@ */ package com.oracle.graal.python.nodes.control; +import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.expression.CastToBooleanNode; import com.oracle.graal.python.nodes.statement.StatementNode; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.nodes.RepeatingNode; import com.oracle.truffle.api.profiles.LoopConditionProfile; -final class WhileRepeatingNode extends Node implements RepeatingNode { +final class WhileRepeatingNode extends PNodeWithContext implements RepeatingNode { private final LoopConditionProfile conditionProfile = LoopConditionProfile.createCountingProfile(); @@ -50,6 +50,7 @@ final class WhileRepeatingNode extends Node implements RepeatingNode { public boolean executeRepeating(VirtualFrame frame) { if (conditionProfile.profile(condition.executeBoolean(frame))) { body.executeVoid(frame); + getContext().triggerAsyncActions(); return true; } return false; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorForNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorForNode.java index e64e79b60d..0c857fc68b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorForNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorForNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -31,6 +31,7 @@ import com.oracle.graal.python.nodes.frame.WriteNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.nodes.statement.StatementNode; +import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.exception.YieldException; import com.oracle.truffle.api.CompilerDirectives; @@ -93,6 +94,7 @@ public void executeVoid(VirtualFrame frame) { } Object nextIterator = null; + PythonContext context = getContext(); int count = 0; try { while (true) { @@ -108,6 +110,7 @@ public void executeVoid(VirtualFrame frame) { if (CompilerDirectives.inInterpreter()) { count++; } + context.triggerAsyncActions(); } return; } catch (YieldException e) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorWhileNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorWhileNode.java index 91344cf858..c755a36b14 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorWhileNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorWhileNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. @@ -28,6 +28,7 @@ import com.oracle.graal.python.nodes.control.LoopNode; import com.oracle.graal.python.nodes.expression.CastToBooleanNode; import com.oracle.graal.python.nodes.statement.StatementNode; +import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.exception.BreakException; import com.oracle.graal.python.runtime.exception.YieldException; import com.oracle.truffle.api.CompilerDirectives; @@ -68,12 +69,14 @@ public void executeVoid(VirtualFrame frame) { } boolean nextFlag = false; int count = 0; + PythonContext context = getContext(); try { do { body.executeVoid(frame); if (CompilerDirectives.inInterpreter()) { count++; } + context.triggerAsyncActions(); } while (condition.executeBoolean(frame)); return; } catch (YieldException e) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 95ac564687..bb147a4a17 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -126,7 +126,7 @@ public Object execute(VirtualFrame frame) { int frameIndex = (int) frameArguments[1]; Object[] arguments = Arrays.copyOfRange(frameArguments, 2, frameArguments.length); if (frameIndex >= 0) { - arguments[frameIndex] = getFrameNode.execute(2); + arguments[frameIndex] = getFrameNode.execute(1); } return callNode.execute(frame, callable, arguments); } From fecad9e1777304998ece9316368f1d202b3c8206 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 10:34:04 +0100 Subject: [PATCH 022/202] forgot to remove handled async actions from the queue --- .../src/com/oracle/graal/python/runtime/AsyncHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index bb147a4a17..aab0b34088 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -149,7 +149,8 @@ void triggerAsyncActions() { CompilerDirectives.transferToInterpreter(); // TODO: (tfel) - for now all async actions are slow path ConcurrentLinkedQueue actions = scheduledActions; - for (AsyncAction action : actions) { + AsyncAction action; + while ((action = actions.poll()) != null) { Object callable = action.callable(); if (callable != null) { Object[] arguments = action.arguments(); From 20ee2bb4c4619257bc323362af6107d773dc0cef Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 11:10:42 +0100 Subject: [PATCH 023/202] move postInit for posix module into posix module --- .../graal/python/builtins/Python3Core.java | 14 ------------- .../builtins/modules/PosixModuleBuiltins.java | 20 +++++++++++++++++++ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java index 7d368bcc6c..c5e4dbf7ed 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java @@ -429,10 +429,6 @@ public void postInitialize() { loadFile(__BUILTINS_PATCHES__, PythonCore.getCoreHomeOrFail()); - PythonModule os = lookupBuiltinModule("posix"); - Object environAttr = os.getAttribute("environ"); - ((PDict) environAttr).setDictStorage(createEnvironDict().getDictStorage()); - initialized = true; } } @@ -639,16 +635,6 @@ private void loadFile(String s, String prefix) { callTarget.call(PArguments.withGlobals(mod)); } - @TruffleBoundary - private PDict createEnvironDict() { - Map getenv = System.getenv(); - PDict environ = factory.createDict(); - for (Entry entry : getenv.entrySet()) { - environ.setItem(factory.createBytes(entry.getKey().getBytes()), factory.createBytes(entry.getValue().getBytes())); - } - return environ; - } - public PythonObjectFactory factory() { return factory; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index e61f52b922..41baf031ad 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -66,6 +66,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Random; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -89,10 +91,12 @@ import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GetItemNode; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.ToByteArrayNode; +import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum; import com.oracle.graal.python.builtins.objects.floats.PFloat; import com.oracle.graal.python.builtins.objects.function.PKeyword; import com.oracle.graal.python.builtins.objects.ints.PInt; +import com.oracle.graal.python.builtins.objects.module.PythonModule; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.PythonClass; @@ -244,6 +248,22 @@ public void initialize(PythonCore core) { builtinConstants.put("environ", core.factory().createDict()); } + @Override + public void postInitialize(PythonCore core) { + super.postInitialize(core); + + // fill the environ dictionary with the current environment + Map getenv = System.getenv(); + PDict environ = core.factory().createDict(); + for (Entry entry : getenv.entrySet()) { + environ.setItem(core.factory().createBytes(entry.getKey().getBytes()), core.factory().createBytes(entry.getValue().getBytes())); + } + + PythonModule posix = core.lookupBuiltinModule("posix"); + Object environAttr = posix.getAttribute("environ"); + ((PDict) environAttr).setDictStorage(environ.getDictStorage()); + } + @Builtin(name = "getcwd", fixedNumOfPositionalArgs = 0) @GenerateNodeFactory public abstract static class CwdNode extends PythonBuiltinNode { From 38595a4763ed50e3c83e6cae4c0ffd32ec6bad49 Mon Sep 17 00:00:00 2001 From: Danilo Ansaloni Date: Mon, 28 Jan 2019 11:16:13 +0100 Subject: [PATCH 024/202] [GR-13583] Set versions for next dev cycle. --- mx.graalpython/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index 4ec0c5748c..73ddc92a52 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -8,7 +8,7 @@ "name": "graalpython", "versionConflictResolution": "latest", - "version": "1.0.0-rc12", + "version": "1.0.0-rc13", "release": False, "groupId": "org.graalvm.graalpython", "url": "http://www.graalvm.org/", From f75f0276a6a6a59bb9fb0d1f6927112a6e235a4d Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 11:34:29 +0100 Subject: [PATCH 025/202] use a lock instead of a second AtomicBoolean to guard the scheduledActions list while some thread is processing it + don't force interpreter transfer, just end of PE when we trigger the actions --- .../graal/python/runtime/AsyncHandler.java | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index aab0b34088..86c84f90d9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -46,6 +46,8 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; import com.oracle.graal.python.PythonLanguage; @@ -55,6 +57,7 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.RootNode; @@ -90,9 +93,9 @@ default int frameIndex() { } private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); - private ConcurrentLinkedQueue scheduledActions = new ConcurrentLinkedQueue<>(); - private AtomicBoolean hasScheduledAction = new AtomicBoolean(false); - private AtomicBoolean executingActions = new AtomicBoolean(false); + private final ConcurrentLinkedQueue scheduledActions = new ConcurrentLinkedQueue<>(); + private final AtomicBoolean hasScheduledAction = new AtomicBoolean(false); + private final Lock executingScheduledActions = new ReentrantLock(); private static final int ASYNC_ACTION_DELAY = 15; // chosen by a fair D20 dice roll private class AsyncRunnable implements Runnable { @@ -105,8 +108,15 @@ public AsyncRunnable(Supplier actionSupplier) { public void run() { AsyncAction asyncAction = actionSupplier.get(); if (asyncAction != null) { - scheduledActions.add(asyncAction); - hasScheduledAction.set(true); + // If there's thread executing scheduled actions right now, + // we wait until adding the next work item + executingScheduledActions.lock(); + try { + scheduledActions.add(asyncAction); + hasScheduledAction.set(true); + } finally { + executingScheduledActions.unlock(); + } } } } @@ -144,10 +154,23 @@ void registerAction(Supplier actionSupplier) { } void triggerAsyncActions() { - if (executingActions.compareAndSet(false, true)) { - if (hasScheduledAction.compareAndSet(true, false)) { - CompilerDirectives.transferToInterpreter(); - // TODO: (tfel) - for now all async actions are slow path + if (hasScheduledAction.compareAndSet(true, false)) { + processAsyncActions(); + } + } + + @TruffleBoundary + private void processAsyncActions() { + // We'll likely be able to get the lock and start working through the async actions. But + // there could be a race between the atomic switch of the hasScheduledAction flag, an + // AsyncRunnable thread and the acquisition of the lock, so a second thread may end up + // clearing the flag again. In that case, both would get here, but only will get the lock + // and the other will skip over this and return. In any case, by the time a thread has + // this lock and is handling async actions, nothing new will be pushed to the + // scheduledActions queue, so we won't have a race between finishing the while loop and + // returning from this method. + if (executingScheduledActions.tryLock()) { + try { ConcurrentLinkedQueue actions = scheduledActions; AsyncAction action; while ((action = actions.poll()) != null) { @@ -169,8 +192,9 @@ void triggerAsyncActions() { } } } + } finally { + executingScheduledActions.unlock(); } - executingActions.set(false); } } } From 5b9526d50e93922a7a1ee3a96681d15dacdc77a0 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 11:35:53 +0100 Subject: [PATCH 026/202] update copyright --- .../graal/python/builtins/objects/frame/FrameBuiltins.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java index 87ad0a22ee..62fb546e5e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. From 634ffb004927e47daa2582f05735ec8d9797ef93 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 11:52:52 +0100 Subject: [PATCH 027/202] do transferToInterpreter --- .../src/com/oracle/graal/python/runtime/AsyncHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 86c84f90d9..579ce18c43 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -55,9 +55,9 @@ import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.RootNode; @@ -155,6 +155,7 @@ void registerAction(Supplier actionSupplier) { void triggerAsyncActions() { if (hasScheduledAction.compareAndSet(true, false)) { + CompilerDirectives.transferToInterpreter(); processAsyncActions(); } } From a0cdb85f7127edd594555249fdd11f57bfa47a34 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 14:22:21 +0100 Subject: [PATCH 028/202] use a TruffleFile to build sources that we think are from a file, to ensure all appropriate properties are set --- .../oracle/graal/python/PythonLanguage.java | 39 +++++++++++++------ .../builtins/modules/BuiltinFunctions.java | 34 +++------------- 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index 00c6b03756..e9747bbee3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -26,7 +26,6 @@ package com.oracle.graal.python; import java.io.IOException; -import java.net.URI; import java.net.URL; import java.text.MessageFormat; import java.util.ArrayList; @@ -89,7 +88,6 @@ import com.oracle.truffle.api.object.ObjectType; import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.source.Source.LiteralBuilder; import com.oracle.truffle.api.source.Source.SourceBuilder; import com.oracle.truffle.api.source.SourceSection; @@ -428,13 +426,31 @@ public static TruffleLogger getLogger() { return TruffleLogger.getLogger(ID); } - public static Source newSource(PythonContext ctxt, String src, String name, URI uri) { + public static Source newSource(PythonContext ctxt, String src, String name, boolean mayBeFile) { try { - LiteralBuilder sourceBuilder = Source.newBuilder(ID, src, name); - if (uri != null) { - sourceBuilder.uri(uri); + SourceBuilder sourceBuilder = null; + if (mayBeFile) { + try { + TruffleFile truffleFile = ctxt.getEnv().getTruffleFile(name); + if (truffleFile.exists()) { + // XXX: (tfel): We don't know if the expression has anything to do with the + // filename that's given. We would really have to compare the entire + // contents, but as a first approximation, we compare the content lengths. + // We override the contents of the source builder with the given source + // regardless. + if (src.length() == truffleFile.size()) { + sourceBuilder = Source.newBuilder(ID, truffleFile); + sourceBuilder.content(src); + } + } + } catch (SecurityException | IOException e) { + sourceBuilder = null; + } + } + if (sourceBuilder == null) { + sourceBuilder = Source.newBuilder(ID, src, name); } - return newSource(ctxt, sourceBuilder, name); + return newSource(ctxt, sourceBuilder); } catch (IOException e) { throw new AssertionError(); } @@ -446,7 +462,7 @@ public Source newSource(PythonContext ctxt, TruffleFile src, String name) throws try { return cachedSources.computeIfAbsent(src, t -> { try { - return newSource(ctxt, Source.newBuilder(ID, src), name); + return newSource(ctxt, Source.newBuilder(ID, src).name(name)); } catch (IOException e) { throw new RuntimeException(e); } @@ -460,7 +476,7 @@ public Source newSource(PythonContext ctxt, URL url, String name) throws IOExcep try { return cachedSources.computeIfAbsent(url, t -> { try { - return newSource(ctxt, Source.newBuilder(ID, url), name); + return newSource(ctxt, Source.newBuilder(ID, url).name(name)); } catch (IOException e) { throw new RuntimeException(e); } @@ -470,14 +486,13 @@ public Source newSource(PythonContext ctxt, URL url, String name) throws IOExcep } } - private static Source newSource(PythonContext ctxt, SourceBuilder srcBuilder, String name) throws IOException { - SourceBuilder newBuilder = srcBuilder.name(name).mimeType(MIME_TYPE); + private static Source newSource(PythonContext ctxt, SourceBuilder srcBuilder) throws IOException { boolean coreIsInitialized = ctxt.getCore().isInitialized(); boolean internal = !coreIsInitialized && !PythonOptions.getOption(ctxt, PythonOptions.ExposeInternalSources); if (internal) { srcBuilder.internal(true); } - return newBuilder.build(); + return srcBuilder.build(); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 70f382d36a..d2419b17ca 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -74,7 +74,6 @@ import java.io.PrintStream; import java.io.PrintWriter; import java.math.BigInteger; -import java.net.URI; import java.nio.CharBuffer; import java.util.List; import java.util.function.Supplier; @@ -167,7 +166,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; @@ -698,14 +696,14 @@ public abstract static class CompileNode extends PythonBuiltinNode { * Decides wether this node should attempt to map the filename to a URI for the benefit of * Truffle tooling */ - private final boolean mapFilenameToUri; + private final boolean mayBeFromFile; - public CompileNode(boolean mapFilenameToUri) { - this.mapFilenameToUri = mapFilenameToUri; + public CompileNode(boolean mayBeFromFile) { + this.mayBeFromFile = mayBeFromFile; } public CompileNode() { - this.mapFilenameToUri = true; + this.mayBeFromFile = true; } public abstract PCode execute(Object source, String filename, String mode, Object kwFlags, Object kwDontInherit, Object kwOptimize); @@ -728,8 +726,7 @@ PCode compile(OpaqueBytes source, String filename, String mode, Object kwFlags, @TruffleBoundary PCode compile(String expression, String filename, String mode, Object kwFlags, Object kwDontInherit, Object kwOptimize) { PythonContext context = getContext(); - URI uri = mapToUri(expression, filename, context); - Source source = PythonLanguage.newSource(context, expression, filename, uri); + Source source = PythonLanguage.newSource(context, expression, filename, mayBeFromFile); ParserMode pm; if (mode.equals("exec")) { pm = ParserMode.File; @@ -748,27 +745,6 @@ PCode compile(String expression, String filename, String mode, Object kwFlags, O } } - private URI mapToUri(String expression, String filename, PythonContext context) { - if (mapFilenameToUri) { - URI uri = null; - try { - TruffleFile truffleFile = context.getEnv().getTruffleFile(filename); - if (truffleFile.exists()) { - // XXX: (tfel): We don't know if the expression has anything to do with the - // filename that's given. We would really have to compare the entire - // contents, but as a first approximation, we compare the content lengths - if (expression.length() == truffleFile.size()) { - uri = truffleFile.toUri(); - } - } - } catch (SecurityException | IOException e) { - } - return uri; - } else { - return null; - } - } - @SuppressWarnings("unused") @Specialization PCode compile(PCode code, String filename, String mode, Object flags, Object dontInherit, Object optimize) { From e284be8dd330bd1eebbdd648cffa329ce68b0658 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 28 Jan 2019 15:23:03 +0100 Subject: [PATCH 029/202] remove workaround for TruffleFile.isSymlink --- .../builtins/modules/PosixModuleBuiltins.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index e61f52b922..24962a64b0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -445,18 +445,8 @@ Object stat(String path, boolean followSymlinks) { } else if (f.isSymbolicLink()) { mode |= S_IFLNK; } else { - // TODO: remove the additional check for symlink once GR-13265 is fixed - TruffleFile canonicalFile = null; - try { - canonicalFile = f.getCanonicalFile(); - } catch (IOException e) { - } - if (!f.getAbsoluteFile().equals(canonicalFile)) { - mode |= S_IFLNK; - } else { - // TODO: differentiate these - mode |= S_IFSOCK | S_IFBLK | S_IFCHR | S_IFIFO; - } + // TODO: differentiate these + mode |= S_IFSOCK | S_IFBLK | S_IFCHR | S_IFIFO; } try { mtime = fileTimeToSeconds(f.getLastModifiedTime(linkOptions)); From f45d78018403a964a1729044e3b77cf5d60de5a4 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 29 Jan 2019 08:34:10 +0100 Subject: [PATCH 030/202] bump imports --- .../include/truffle.h | 96 +------------------ mx.graalpython/suite.py | 4 +- 2 files changed, 3 insertions(+), 97 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/include/truffle.h b/graalpython/com.oracle.graal.python.cext/include/truffle.h index e831e895b7..0279cb81e1 100644 --- a/graalpython/com.oracle.graal.python.cext/include/truffle.h +++ b/graalpython/com.oracle.graal.python.cext/include/truffle.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. * * All rights reserved. * @@ -57,100 +57,6 @@ bool truffle_cannot_be_handle(void *nativeHandle); // wrapping functions void *truffle_decorate_function(void *function, void *wrapper); -/* - * All function below here are deprecated and will be removed in a future release. - * Use the equivalent functions from instead. - */ - -void *truffle_import(const char *name); // renamed to polyglot_import -void *truffle_import_cached(const char *name); // no replacement, use polyglot_import - -void *truffle_address_to_function(void *address); // deprecated, does nothing - -void *truffle_get_arg(int i); // renamed to polyglot_get_arg - -// Predicates: -bool truffle_is_executable(const void *object); // renamed to polyglot_can_execute -bool truffle_is_null(const void *object); // renamed to polyglot_is_null -bool truffle_has_size(const void *object); // renamed to polyglot_has_array_elements -bool truffle_is_boxed(const void *object); // no replacement -bool truffle_is_truffle_object(const void *object); // renamed to polyglot_is_value - -// Execute: deprecated, use typecast to function pointer instead -void *truffle_execute(void *object, ...); -int truffle_execute_i(void *object, ...); -long truffle_execute_l(void *object, ...); -char truffle_execute_c(void *object, ...); -float truffle_execute_f(void *object, ...); -double truffle_execute_d(void *object, ...); -bool truffle_execute_b(void *object, ...); - -// Invoke: -void *truffle_invoke(void *object, const char *name, ...); // renamed to polyglot_invoke -int truffle_invoke_i(void *object, const char *name, ...); // deprecated, use polyglot_as_i32(polyglot_invoke(...)) -long truffle_invoke_l(void *object, const char *name, ...); // deprecated, use polyglot_as_i64(polyglot_invoke(...)) -char truffle_invoke_c(void *object, const char *name, ...); // deprecated, use polyglot_as_i8(polyglot_invoke(...)) -float truffle_invoke_f(void *object, const char *name, ...); // deprecated, use polyglot_as_float(polyglot_invoke(...)) -double truffle_invoke_d(void *object, const char *name, ...); // deprecated, use polyglot_as_double(polyglot_invoke(...)) -bool truffle_invoke_b(void *object, const char *name, ...); // deprecated, use polyglot_as_boolean(polyglot_invoke(...)) - -// GetSize -int truffle_get_size(const void *object); // renamed to polyglot_get_array_size - -// Unbox -int truffle_unbox_i(void *object); // renamed to polyglot_as_i32 -long truffle_unbox_l(void *object); // renamed to polyglot_as_i64 -char truffle_unbox_c(void *object); // renamed to polyglot_as_i8 -float truffle_unbox_f(void *object); // renamed to polyglot_as_float -double truffle_unbox_d(void *object); // renamed to polyglot_as_double -bool truffle_unbox_b(void *object); // renamed to polyglot_as_boolean - -// Read -void *truffle_read(void *object, const char *name); // renamed to polyglot_get_member -int truffle_read_i(void *object, const char *name); // deprecated, use polyglot_as_i32(polyglot_get_member(...)) -long truffle_read_l(void *object, const char *name); // deprecated, use polyglot_as_i64(polyglot_get_member(...)) -char truffle_read_c(void *object, const char *name); // deprecated, use polyglot_as_i8(polyglot_get_member(...)) -float truffle_read_f(void *object, const char *name); // deprecated, use polyglot_as_float(polyglot_get_member(...)) -double truffle_read_d(void *object, const char *name); // deprecated, use polyglot_as_double(polyglot_get_member(...)) -bool truffle_read_b(void *object, const char *name); // deprecated, use polyglot_as_boolean(polyglot_get_member(...)) - -void *truffle_read_idx(void *object, int idx); // renamed to polyglot_get_array_element -int truffle_read_idx_i(void *object, int idx); // deprecated, use polyglot_as_i32(polyglot_get_array_element(...)) -long truffle_read_idx_l(void *object, int idx); // deprecated, use polyglot_as_i64(polyglot_get_array_element(...)) -char truffle_read_idx_c(void *object, int idx); // deprecated, use polyglot_as_i8(polyglot_get_array_element(...)) -float truffle_read_idx_f(void *object, int idx); // deprecated, use polyglot_as_float(polyglot_get_array_element(...)) -double truffle_read_idx_d(void *object, int idx); // deprecated, use polyglot_as_double(polyglot_get_array_element(...)) -bool truffle_read_idx_b(void *object, int idx); // deprecated, use polyglot_as_boolean(polyglot_get_array_element(...)) - -// Write -void truffle_write(void *object, const char *name, void *value); // renamed to polyglot_put_member -void truffle_write_i(void *object, const char *name, int value); // deprecated, use polyglot_put_member -void truffle_write_l(void *object, const char *name, long value); // deprecated, use polyglot_put_member -void truffle_write_c(void *object, const char *name, char value); // deprecated, use polyglot_put_member -void truffle_write_f(void *object, const char *name, float value); // deprecated, use polyglot_put_member -void truffle_write_d(void *object, const char *name, double value); // deprecated, use polyglot_put_member -void truffle_write_b(void *object, const char *name, bool value); // deprecated, use polyglot_put_member - -void truffle_write_idx(void *object, int idx, void *value); // renamed to polyglot_set_array_element -void truffle_write_idx_i(void *object, int idx, int value); // deprecated, use polyglot_set_array_element -void truffle_write_idx_l(void *object, int idx, long value); // deprecated, use polyglot_set_array_element -void truffle_write_idx_c(void *object, int idx, char value); // deprecated, use polyglot_set_array_element -void truffle_write_idx_f(void *object, int idx, float value); // deprecated, use polyglot_set_array_element -void truffle_write_idx_d(void *object, int idx, double value); // deprecated, use polyglot_set_array_element -void truffle_write_idx_b(void *object, int idx, bool value); // deprecated, use polyglot_set_array_element - -// Strings -void *truffle_read_string(const char *string); // deprecated, use polyglot_from_string instead -void *truffle_read_n_string(const char *string, int n); // deprecated, use polyglot_from_string_n instead -void *truffle_read_bytes(const char *bytes); // deprecated, no replacement -void *truffle_read_n_bytes(const char *bytes, int n); // deprecated, no replacement -const char *truffle_string_to_cstr(const char *string); // deprecated, use polyglot_as_string instead -void truffle_free_cstr(const char *truffle_allocated_cstr); // deprecated, no replacement - -void *truffle_sulong_function_to_native_pointer(void *sulongFunctionPointer, const void *signature); // deprecated, no replacement - -void *truffle_polyglot_eval(const char *mimeType, const char *code); // deprecated, use polyglot_eval instead - #if defined(__cplusplus) } #endif diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index 73ddc92a52..d8ff3b2f49 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -43,7 +43,7 @@ }, { "name": "sulong", - "version": "9d229909cf650948b7cf438fee2addb4b97603c1", + "version": "db68412a9a704b40d65cfa45be71097ec88258d2", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, @@ -51,7 +51,7 @@ }, { "name": "regex", - "version": "9d229909cf650948b7cf438fee2addb4b97603c1", + "version": "db68412a9a704b40d65cfa45be71097ec88258d2", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, From deb4dbc4877fc38ebd0174d4e74ae1ff7d08c606 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 09:54:34 +0100 Subject: [PATCH 031/202] Also handle SecurityException. --- .../graal/python/builtins/modules/PosixModuleBuiltins.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index 1f37f5be8c..deb2071743 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -516,7 +516,7 @@ Object stat(String path, boolean followSymlinks) { TruffleFile canonical; try { canonical = f.getCanonicalFile(); - } catch (IOException e) { + } catch (IOException | SecurityException e) { // best effort canonical = f.getAbsoluteFile(); } From 02c2051ba89a5586fe3e1d922b3f318732e34153 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 29 Jan 2019 10:54:29 +0100 Subject: [PATCH 032/202] with the lock for keeping out duplicate executions of async actions, allow races for the action flag --- .../com/oracle/graal/python/runtime/AsyncHandler.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 579ce18c43..23f02f627a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -45,7 +45,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; @@ -94,7 +93,7 @@ default int frameIndex() { private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); private final ConcurrentLinkedQueue scheduledActions = new ConcurrentLinkedQueue<>(); - private final AtomicBoolean hasScheduledAction = new AtomicBoolean(false); + private boolean hasScheduledAction = false; private final Lock executingScheduledActions = new ReentrantLock(); private static final int ASYNC_ACTION_DELAY = 15; // chosen by a fair D20 dice roll @@ -113,7 +112,7 @@ public void run() { executingScheduledActions.lock(); try { scheduledActions.add(asyncAction); - hasScheduledAction.set(true); + hasScheduledAction = true; } finally { executingScheduledActions.unlock(); } @@ -154,7 +153,9 @@ void registerAction(Supplier actionSupplier) { } void triggerAsyncActions() { - if (hasScheduledAction.compareAndSet(true, false)) { + // Uses weakCompareAndSet because we just want to do it in a timely manner, but we don't + // need the ordering guarantees. + if (hasScheduledAction) { CompilerDirectives.transferToInterpreter(); processAsyncActions(); } @@ -171,6 +172,7 @@ private void processAsyncActions() { // scheduledActions queue, so we won't have a race between finishing the while loop and // returning from this method. if (executingScheduledActions.tryLock()) { + hasScheduledAction = false; try { ConcurrentLinkedQueue actions = scheduledActions; AsyncAction action; From 07b7f6e2562dddbb59dfd19ffae8b912ac95af78 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 29 Jan 2019 11:13:05 +0100 Subject: [PATCH 033/202] document the race in trigger async actions and why it's ok --- .../graal/python/runtime/AsyncHandler.java | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 23f02f627a..bd177ca8cc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -161,16 +161,40 @@ void triggerAsyncActions() { } } + /** + * It's fine that there is a race between checking the hasScheduledAction flag and processing + * actions, we use the executingScheduledActions lock to ensure that only one thread is + * processing and that no asynchronous handler thread would set it again while we're processing. + * While the nice scenario would be any variation of: + * + *
    + *
  • Thread2 - acquireLock, pushWork, setFlag, releaseLock
  • + *
  • Thread1 - checkFlag, acquireLock, resetFlag, processActions, releaseLock
  • + *
+ * + *
    + *
  • Thread1 - checkFlag
  • + *
  • Thread2 - acquireLock, pushWork, setFlag, releaseLock
  • + *
  • Thread1 - acquireLock, resetFlag, processActions, releaseLock
  • + *
+ * + * it's also fine if we get into a race for example like this: + * + *
    + *
  • Thread2 - acquireLock, pushWork, setFlag
  • + *
  • Thread1 - checkFlag, tryAcquireLock, bail out
  • + *
  • Thread2 - releaseLock
  • + *
+ * + * because Thread1 is sure to check the flag again soon enough, and very likely much sooner than + * the {@value #ASYNC_ACTION_DELAY} ms delay between successive runs of the async handler + * threads (Thread2 in this example). Of course, there can be more than one handler thread, but + * it's unlikely that there are so many that it would completely saturate the ability to process + * async actions on the main thread, because there's only one per "type" of async thing (e.g. 1 + * for weakref finalizers, 1 for signals, 1 for destructors). + */ @TruffleBoundary private void processAsyncActions() { - // We'll likely be able to get the lock and start working through the async actions. But - // there could be a race between the atomic switch of the hasScheduledAction flag, an - // AsyncRunnable thread and the acquisition of the lock, so a second thread may end up - // clearing the flag again. In that case, both would get here, but only will get the lock - // and the other will skip over this and return. In any case, by the time a thread has - // this lock and is handling async actions, nothing new will be pushed to the - // scheduledActions queue, so we won't have a race between finishing the while loop and - // returning from this method. if (executingScheduledActions.tryLock()) { hasScheduledAction = false; try { From 9d79611cabd39e3903b2edbde25b92fe809cb320 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Wed, 23 Jan 2019 14:49:15 +0100 Subject: [PATCH 034/202] Adapt to the new splitting heuristic. --- .../src/com/oracle/graal/python/runtime/PythonOptions.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java index f39e5a9f37..622135becf 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java @@ -123,8 +123,8 @@ private PythonOptions() { @Option(category = OptionCategory.EXPERT, help = "Switch on/off using lazy strings for performance reasons. Default true.") // public static final OptionKey LazyStrings = new OptionKey<>(true); - @Option(category = OptionCategory.EXPERT, help = "Enable forced splitting (of builtins). Default true.") // - public static final OptionKey EnableForcedSplits = new OptionKey<>(true); + @Option(category = OptionCategory.EXPERT, help = "Enable forced splitting (of builtins). Default false.") // + public static final OptionKey EnableForcedSplits = new OptionKey<>(false); @Option(category = OptionCategory.EXPERT, help = "Set by the launcher if an interactive console is used to run Python.") // public static final OptionKey TerminalIsInteractive = new OptionKey<>(false); From 47426a178426d7ec5bbe8d1b10eae62c974a80d1 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Fri, 25 Jan 2019 13:47:33 +0100 Subject: [PATCH 035/202] Truffle update. --- mx.graalpython/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index d8ff3b2f49..c9a5d7157e 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -43,7 +43,7 @@ }, { "name": "sulong", - "version": "db68412a9a704b40d65cfa45be71097ec88258d2", + "version": "8b71a9c6237531225ad7b61c85b7a683ca462cba", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, @@ -51,7 +51,7 @@ }, { "name": "regex", - "version": "db68412a9a704b40d65cfa45be71097ec88258d2", + "version": "8b71a9c6237531225ad7b61c85b7a683ca462cba", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, From 258735ce650355536ebb59ed62faa6a632e81414 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 25 Jan 2019 16:56:36 +0100 Subject: [PATCH 036/202] fix wrong specialization in random.seed --- .../objects/random/RandomBuiltins.java | 65 +++++++++++++------ 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/RandomBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/RandomBuiltins.java index 73bd70e028..11c946f4b2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/RandomBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/RandomBuiltins.java @@ -51,14 +51,19 @@ import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.nodes.PGuards; +import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; +import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; import com.oracle.graal.python.runtime.exception.PythonErrorType; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.nodes.UnexpectedResultException; @CoreFunctions(extendClasses = PythonBuiltinClassType.PRandom) @@ -70,6 +75,7 @@ protected List> getNodeFactor @Builtin(name = "seed", fixedNumOfPositionalArgs = 2) @GenerateNodeFactory + @TypeSystemReference(PythonArithmeticTypes.class) public abstract static class SeedNode extends PythonBuiltinNode { @Specialization @@ -80,7 +86,7 @@ public PNone seed(PRandom random, @SuppressWarnings("unused") PNone none) { } @Specialization - public PNone seed(PRandom random, int inputSeed) { + public PNone seed(PRandom random, long inputSeed) { random.setSeed(inputSeed); return PNone.NONE; } @@ -97,26 +103,47 @@ public PNone seed(PRandom random, double inputSeed) { return PNone.NONE; } - @Specialization(rewriteOn = UnexpectedResultException.class) - public PNone seedObject(PRandom random, Object inputSeed, - @Cached("create(__HASH__)") LookupAndCallUnaryNode callHash) throws UnexpectedResultException { - long hash = callHash.executeLong(inputSeed); - random.setSeed(hash); - return PNone.NONE; - } + @CompilationFinal boolean gotUnexpectedHashResult = false; + @Child LookupAndCallUnaryNode callHash; - @Specialization(replaces = "seedObject") - public PNone seedNonLong(PRandom random, Object inputSeed, - @Cached("create(__HASH__)") LookupAndCallUnaryNode callHash) { - Object object = callHash.executeObject(inputSeed); - if (PGuards.isInteger(object)) { - random.setSeed(((Number) object).intValue()); - } else if (PGuards.isPInt(object)) { - random.setSeed(((PInt) object).intValue()); + @Fallback + public PNone seedNonLong(Object random, Object inputSeed) { + if (random instanceof PRandom) { + if (callHash == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + callHash = insert(LookupAndCallUnaryNode.create(SpecialMethodNames.__HASH__)); + } + Object hashResult = null; + if (!gotUnexpectedHashResult) { + try { + long hash = callHash.executeLong(inputSeed); + ((PRandom) random).setSeed(hash); + return PNone.NONE; + } catch (UnexpectedResultException e) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + gotUnexpectedHashResult = true; + hashResult = e.getResult(); + } + } + if (gotUnexpectedHashResult) { + if (hashResult == null) { + hashResult = callHash.executeObject(inputSeed); + } + if (PGuards.isInteger(hashResult)) { + ((PRandom) random).setSeed(((Number) hashResult).intValue()); + } else if (PGuards.isPInt(hashResult)) { + ((PRandom) random).setSeed(((PInt) hashResult).intValue()); + } else { + throw raise(PythonErrorType.TypeError, "__hash__ method should return an integer"); + } + return PNone.NONE; + } else { + assert false : "cannot reach here"; + return PNone.NONE; + } } else { - throw raise(PythonErrorType.TypeError, "__hash__ method should return an integer"); + throw raise(PythonErrorType.TypeError, "descriptor 'seed' requires a '_random.Random' object but received a '%p'", random); } - return PNone.NONE; } } From 82e726a4e37ed5c3517a535e381f9cbe25500af3 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Sun, 27 Jan 2019 11:55:14 +0100 Subject: [PATCH 037/202] update copyrights --- .../com.oracle.graal.python.test/src/tests/test_random.py | 2 +- .../graal/python/builtins/objects/random/RandomBuiltins.java | 2 +- .../src/com/oracle/graal/python/nodes/call/InvokeNode.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_random.py b/graalpython/com.oracle.graal.python.test/src/tests/test_random.py index f3a3f474db..a56bacb856 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_random.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_random.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. # Copyright (C) 1996-2017 Python Software Foundation # # Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/RandomBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/RandomBuiltins.java index 11c946f4b2..aa2112a0ac 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/RandomBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/RandomBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/InvokeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/InvokeNode.java index 81f95a9982..8ef7914fa5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/InvokeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/InvokeNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. From 818de7906d2fd11374beee35533c1e75b85a83b1 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Wed, 30 Jan 2019 08:48:31 +0100 Subject: [PATCH 038/202] Truffle update. --- mx.graalpython/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index c9a5d7157e..2d04d09e8b 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -43,7 +43,7 @@ }, { "name": "sulong", - "version": "8b71a9c6237531225ad7b61c85b7a683ca462cba", + "version": "526f76f44f59943be852c07e6999d08401b40962", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, @@ -51,7 +51,7 @@ }, { "name": "regex", - "version": "8b71a9c6237531225ad7b61c85b7a683ca462cba", + "version": "526f76f44f59943be852c07e6999d08401b40962", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, From d2d9ee6457fbff7fe72cb112c28cf602cde09047 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Wed, 30 Jan 2019 09:04:11 +0100 Subject: [PATCH 039/202] Update overlay. --- ci.jsonnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci.jsonnet b/ci.jsonnet index fa87daf5d7..a9c8244f1d 100644 --- a/ci.jsonnet +++ b/ci.jsonnet @@ -1,5 +1,5 @@ { - overlay: "3cf78c3623442ad827eed58a1780784a6eb95676", + overlay: "e08ca6c848943a04c5e46d54272ff927ff3d51f7", // ====================================================================================================== // From 53652254d86d93945ed1173830677027a71a3daf Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 30 Jan 2019 09:24:38 +0100 Subject: [PATCH 040/202] update imports --- mx.graalpython/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index d8ff3b2f49..2d04d09e8b 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -43,7 +43,7 @@ }, { "name": "sulong", - "version": "db68412a9a704b40d65cfa45be71097ec88258d2", + "version": "526f76f44f59943be852c07e6999d08401b40962", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, @@ -51,7 +51,7 @@ }, { "name": "regex", - "version": "db68412a9a704b40d65cfa45be71097ec88258d2", + "version": "526f76f44f59943be852c07e6999d08401b40962", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, From 8a811c0f897ad80f6159aaae2c1dd4ee2e648d79 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 30 Jan 2019 09:57:20 +0100 Subject: [PATCH 041/202] implement PEP 553 breakpoint() message --- .../builtins/modules/BuiltinFunctions.java | 32 ++++++++++++++++--- .../graal/python/nodes/BuiltinNames.java | 3 +- .../python/nodes/call/PythonCallNode.java | 2 +- graalpython/lib-graalpython/sys.py | 26 +++++++++++++++ 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 432732fa79..3d53ffef9f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -55,7 +55,8 @@ import static com.oracle.graal.python.nodes.BuiltinNames.ROUND; import static com.oracle.graal.python.nodes.BuiltinNames.SETATTR; import static com.oracle.graal.python.nodes.BuiltinNames.SUM; -import static com.oracle.graal.python.nodes.BuiltinNames.__BREAKPOINT__; +import static com.oracle.graal.python.nodes.BuiltinNames.BREAKPOINT; +import static com.oracle.graal.python.nodes.BuiltinNames.BREAKPOINTHOOK; import static com.oracle.graal.python.nodes.BuiltinNames.__BUILTIN__; import static com.oracle.graal.python.nodes.BuiltinNames.__DEBUG__; import static com.oracle.graal.python.nodes.BuiltinNames.__DUMP_TRUFFLE_AST__; @@ -93,6 +94,7 @@ import com.oracle.graal.python.builtins.objects.bytes.PBytes; import com.oracle.graal.python.builtins.objects.code.PCode; import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes; +import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; import com.oracle.graal.python.builtins.objects.common.PHashingCollection; import com.oracle.graal.python.builtins.objects.common.SequenceNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; @@ -168,6 +170,7 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.debug.Debugger; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -1501,12 +1504,33 @@ public Object setAttr(Object object, Object key, Object value, } } - @Builtin(name = __BREAKPOINT__, fixedNumOfPositionalArgs = 0) + @Builtin(name = BREAKPOINT, takesVarArgs = true, takesVarKeywordArgs = true) @GenerateNodeFactory public abstract static class BreakPointNode extends PythonBuiltinNode { + @Child HashingStorageNodes.GetItemNode getSysModuleNode; + @Child ReadAttributeFromObjectNode getBreakpointhookNode; + @Child CallNode callNode; + @Specialization - public Object doIt() { - return PNone.NONE; + public Object doIt(VirtualFrame frame, Object[] args, PKeyword[] kwargs) { + if (Debugger.find(getContext().getEnv()).getSessionCount() > 0) { + // we already have a Truffle debugger attached, it'll stop here + return PNone.NONE; + } else { + if (getSysModuleNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getSysModuleNode = insert(HashingStorageNodes.GetItemNode.create()); + getBreakpointhookNode = insert(ReadAttributeFromObjectNode.create()); + callNode = insert(CallNode.create()); + } + PDict sysModules = getContext().getSysModules(); + Object sysModule = getSysModuleNode.execute(sysModules.getDictStorage(), "sys"); + Object breakpointhook = getBreakpointhookNode.execute(sysModule, BREAKPOINTHOOK); + if (breakpointhook == PNone.NO_VALUE) { + throw raise(PythonBuiltinClassType.RuntimeError, "lost sys.breakpointhook"); + } + return callNode.execute(frame, breakpointhook, args, kwargs); + } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java index 3ac9c3e011..5ba5e789ff 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java @@ -45,10 +45,10 @@ public abstract class BuiltinNames { public static final String SELF = "self"; // graalpython internals - public static final String __BREAKPOINT__ = "__breakpoint__"; public static final String __BUILTINS_PATCHES__ = "__builtins_patches__"; // cpython internals + public static final String BREAKPOINT = "breakpoint"; public static final String MODULE = "module"; public static final String __BUILD_CLASS__ = "__build_class__"; public static final String __MAIN__ = "__main__"; @@ -56,6 +56,7 @@ public abstract class BuiltinNames { public static final String __DEBUG__ = "__debug__"; // sys + public static final String BREAKPOINTHOOK = "breakpointhook"; public static final String EXCEPTHOOK = "excepthook"; public static final String LAST_TYPE = "last_type"; public static final String LAST_VALUE = "last_value"; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/PythonCallNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/PythonCallNode.java index b36e484b3c..65413fb53d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/PythonCallNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/PythonCallNode.java @@ -272,6 +272,6 @@ private static boolean isCall(Class tag) { } private boolean isBreakpoint(Class tag) { - return tag == DebuggerTags.AlwaysHalt.class && calleeName.equals(BuiltinNames.__BREAKPOINT__); + return tag == DebuggerTags.AlwaysHalt.class && calleeName.equals(BuiltinNames.BREAKPOINT); } } diff --git a/graalpython/lib-graalpython/sys.py b/graalpython/lib-graalpython/sys.py index d9dd57ae39..2fb58cde88 100644 --- a/graalpython/lib-graalpython/sys.py +++ b/graalpython/lib-graalpython/sys.py @@ -175,6 +175,32 @@ def __print_traceback__(typ, value, tb): del make_excepthook +@__builtin__ +def breakpointhook(*args, **kws): + import importlib, os, warnings + hookname = os.getenv('PYTHONBREAKPOINT') + if hookname is None or len(hookname) == 0: + warnings.warn('Graal Python cannot run pdb, yet, consider using `--inspect` on the commandline', RuntimeWarning) + hookname = 'pdb.set_trace' + elif hookname == '0': + return None + modname, dot, funcname = hookname.rpartition('.') + if dot == '': + modname = 'builtins' + try: + module = importlib.import_module(modname) + hook = getattr(module, funcname) + except: + warnings.warn( + 'Ignoring unimportable $PYTHONBREAKPOINT: {}'.format( + hookname), + RuntimeWarning) + return hook(*args, **kws) + + +__breakpointhook__ = breakpointhook + + @__builtin__ def getrecursionlimit(): return 1000 From 92e55edce2350d37479212d93ee6dc48a60c3db4 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 31 Jan 2019 10:50:25 +0100 Subject: [PATCH 042/202] update jdk --- ci.jsonnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci.jsonnet b/ci.jsonnet index fa87daf5d7..674a5ac109 100644 --- a/ci.jsonnet +++ b/ci.jsonnet @@ -127,7 +127,7 @@ local labsjdk8Mixin = { downloads +: { - JAVA_HOME: utils.download("labsjdk", "8u172-jvmci-0.48"), + JAVA_HOME: utils.download("labsjdk", "8u192-jvmci-0.54"), EXTRA_JAVA_HOMES : { pathlist: [utils.download("oraclejdk", "11+20")] }, }, environment +: { From 0afb8f7ee961adf00af010dc0eba9129b35e8015 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 31 Jan 2019 10:52:01 +0100 Subject: [PATCH 043/202] update copyright --- .../src/com/oracle/graal/python/nodes/BuiltinNames.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java index 5ba5e789ff..e56258d606 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 From 00428880135eb31261343a58906c90dd383454d2 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 31 Jan 2019 14:53:38 +0100 Subject: [PATCH 044/202] Put Throwable.getMessage behind a boundary in posix builtins --- .../graal/python/builtins/modules/PosixModuleBuiltins.java | 2 +- .../src/com/oracle/graal/python/nodes/PNodeWithContext.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index 3e780bcd1a..c68a48dff6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -1838,7 +1838,7 @@ String readlink(String str, @SuppressWarnings("unused") PNone none) { try { return getContext().getEnv().getTruffleFile(str).getCanonicalFile().getPath(); } catch (IOException e) { - throw raise(OSError, e.getMessage()); + throw raise(OSError, getMessage(e)); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java index a26110ea64..fe96f49faf 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java @@ -117,7 +117,7 @@ public final PException raise(PythonBuiltinClassType type, Exception e) { } @TruffleBoundary - private static final String getMessage(Exception e) { + protected static final String getMessage(Exception e) { return e.getMessage(); } From 616590103422cf094564c76563fcf9e07c796358 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 1 Feb 2019 11:42:48 +0100 Subject: [PATCH 045/202] bump imports --- mx.graalpython/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index 2d04d09e8b..925538ab2e 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -43,7 +43,7 @@ }, { "name": "sulong", - "version": "526f76f44f59943be852c07e6999d08401b40962", + "version": "175738c97f96974ba44251e913a597aa64a7d3c2", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, @@ -51,7 +51,7 @@ }, { "name": "regex", - "version": "526f76f44f59943be852c07e6999d08401b40962", + "version": "175738c97f96974ba44251e913a597aa64a7d3c2", "subdir": True, "urls": [ {"url": "https://github.com/oracle/graal", "kind": "git"}, From ece140a70fbca465938b4a443caf8a19f33578a7 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 1 Feb 2019 11:44:52 +0100 Subject: [PATCH 046/202] add missing TruffleBoundary --- .../graal/python/builtins/modules/BuiltinFunctions.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 3d53ffef9f..049794bde4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -1513,7 +1513,7 @@ public abstract static class BreakPointNode extends PythonBuiltinNode { @Specialization public Object doIt(VirtualFrame frame, Object[] args, PKeyword[] kwargs) { - if (Debugger.find(getContext().getEnv()).getSessionCount() > 0) { + if (getDebuggerSessionCount() > 0) { // we already have a Truffle debugger attached, it'll stop here return PNone.NONE; } else { @@ -1532,6 +1532,11 @@ public Object doIt(VirtualFrame frame, Object[] args, PKeyword[] kwargs) { return callNode.execute(frame, breakpointhook, args, kwargs); } } + + @TruffleBoundary + private int getDebuggerSessionCount() { + return Debugger.find(getContext().getEnv()).getSessionCount(); + } } @Builtin(name = "__tdebug__", takesVarArgs = true) From 94b9f1fb01828f3459d3425b086a2866772999dc Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 1 Feb 2019 13:54:55 +0100 Subject: [PATCH 047/202] increase darwin time limit --- ci.jsonnet | 1 + 1 file changed, 1 insertion(+) diff --git a/ci.jsonnet b/ci.jsonnet index b5f576c1c7..14d2177914 100644 --- a/ci.jsonnet +++ b/ci.jsonnet @@ -88,6 +88,7 @@ local darwinMixin = { capabilities +: ["darwin_sierra", "amd64"], + timelimit: TIME_LIMIT["1h"], packages +: { "pip:astroid": "==1.1.0", "pip:pylint": "==1.1.0", From d1f7beb4ba369ee0efc24bee627ac0df942d86d9 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Sun, 3 Feb 2019 16:01:08 +0100 Subject: [PATCH 048/202] use a custom thread factory to mark our async handler threads as daemons --- .../com/oracle/graal/python/runtime/AsyncHandler.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index bd177ca8cc..80332652ff 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -44,6 +44,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -91,7 +92,13 @@ default int frameIndex() { } } - private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); + private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2, new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread t = Executors.defaultThreadFactory().newThread(r); + t.setDaemon(true); + return t; + } + }); private final ConcurrentLinkedQueue scheduledActions = new ConcurrentLinkedQueue<>(); private boolean hasScheduledAction = false; private final Lock executingScheduledActions = new ReentrantLock(); From 0b44f09cedc7bea9bf4c910b73881ca822e1bb2d Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Sun, 3 Feb 2019 16:01:23 +0100 Subject: [PATCH 049/202] when the context shuts down cleanly, we'd like to shutdown our async handler threads, too --- .../src/com/oracle/graal/python/runtime/AsyncHandler.java | 4 ++++ .../src/com/oracle/graal/python/runtime/PythonContext.java | 1 + 2 files changed, 5 insertions(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java index 80332652ff..ea21c32e6d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java @@ -231,4 +231,8 @@ private void processAsyncActions() { } } } + + public void shutdown() { + executorService.shutdownNow(); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 129930697c..1e8bc7313e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -288,6 +288,7 @@ public void deregisterShutdownHook(Object callable) { @TruffleBoundary public void runShutdownHooks() { + handler.shutdown(); for (CallTarget f : atExitHooks.values()) { f.call(); } From d8199b02954aaac6daeccfea90996b59f8e2b0c1 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 15 Jan 2019 13:31:19 +0100 Subject: [PATCH 050/202] Use node to access the MRO of a Python type. --- .../builtins/modules/BuiltinConstructors.java | 29 +++++++++----- .../builtins/modules/TruffleCextBuiltins.java | 12 +++++- .../cext/PythonObjectNativeWrapperMR.java | 3 +- .../GetSetDescriptorTypeBuiltins.java | 16 +++++++- .../objects/superobject/SuperBuiltins.java | 28 ++++++++----- .../builtins/objects/type/PythonClass.java | 4 +- .../builtins/objects/type/TypeNodes.java | 40 ++++++++++++++++++- .../attributes/LookupAttributeInMRONode.java | 21 +++++++--- .../nodes/classes/IsFixedSubtypeMRONode.java | 8 ++-- .../nodes/classes/IsSubtypeMRONode.java | 19 +++++++-- .../python/nodes/classes/IsSubtypeNode.java | 19 +++++++-- .../python/nodes/statement/ExceptNode.java | 16 ++++++-- .../python/nodes/statement/RaiseNode.java | 15 ++++++- .../interop/PythonMessageResolution.java | 25 ++++++++++-- 14 files changed, 206 insertions(+), 49 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index fa55512b07..13c622fcf1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -117,6 +117,7 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.argument.CreateArgumentsNode; @@ -1355,11 +1356,12 @@ Object doObjectIndirect(PythonClass self, Object[] varargs, PKeyword[] kwargs) { } @Specialization(guards = "self.needsNativeAllocation()") - Object doNativeObjectIndirect(PythonClass self, Object[] varargs, PKeyword[] kwargs) { + Object doNativeObjectIndirect(PythonClass self, Object[] varargs, PKeyword[] kwargs, + @Cached("create()") GetMroNode getMroNode) { if (varargs.length > 0 || kwargs.length > 0) { // TODO: tfel: this should throw an error only if init isn't overridden } - PythonNativeClass nativeBaseClass = findFirstNativeBaseClass(self.getMethodResolutionOrder()); + PythonNativeClass nativeBaseClass = findFirstNativeBaseClass(getMroNode.execute(self)); return callNativeGenericNewNode(nativeBaseClass, varargs, kwargs); } @@ -1726,6 +1728,8 @@ public abstract static class TypeNode extends PythonBuiltinNode { @Child private CExtNodes.PCallCapiFunction callAddNativeSlotsNode; @Child private CExtNodes.ToSulongNode toSulongNode; @Child private ReadCallerFrameNode readCallerFrameNode; + @Child private GetMroNode getMroNode; + @Child private IsSubtypeNode isSubtypeNode; @Specialization(guards = {"isNoValue(bases)", "isNoValue(dict)"}) @SuppressWarnings("unused") @@ -2015,7 +2019,7 @@ private CastToListNode getCastToListNode() { private boolean addDictIfNative(PythonClass pythonClass) { boolean addedNewDict = false; if (pythonClass.needsNativeAllocation()) { - for (Object cls : pythonClass.getMethodResolutionOrder()) { + for (Object cls : getMro(pythonClass)) { if (cls instanceof PythonNativeClass) { long dictoffset = ensureCastToIntNode().execute(ensureReadAttrNode().execute(cls, SpecialAttributeNames.__DICTOFFSET__)); long basicsize = ensureCastToIntNode().execute(ensureReadAttrNode().execute(cls, SpecialAttributeNames.__BASICSIZE__)); @@ -2040,6 +2044,14 @@ private boolean addDictIfNative(PythonClass pythonClass) { return addedNewDict; } + private PythonClass[] getMro(PythonClass pythonClass) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(pythonClass); + } + private PythonClass calculate_metaclass(PythonClass cls, PTuple bases, GetClassNode getMetaclassNode) { PythonClass winner = cls; for (Object base : bases.getArray()) { @@ -2056,13 +2068,12 @@ private PythonClass calculate_metaclass(PythonClass cls, PTuple bases, GetClassN return winner; } - private static boolean isSubType(PythonClass subclass, PythonClass superclass) { - for (PythonClass base : subclass.getMethodResolutionOrder()) { - if (base == superclass) { - return true; - } + private boolean isSubType(PythonClass subclass, PythonClass superclass) { + if (isSubtypeNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isSubtypeNode = insert(IsSubtypeNode.create()); } - return false; + return isSubtypeNode.execute(subclass, superclass); } protected abstract Object execute(VirtualFrame frame, Object cls, Object name, Object bases, Object dict, PKeyword[] kwds); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 493894e89a..37a3a48457 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -131,6 +131,7 @@ import com.oracle.graal.python.builtins.objects.type.GetTypeFlagsNode; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialAttributeNames; @@ -558,6 +559,7 @@ abstract static class PyType_ReadyNode extends PythonBuiltinNode { @Child private HashingStorageNodes.ContainsKeyNode containsKeyNode; @Child private CExtNodes.PCallCapiFunction callAddNativeSlotsNode; @Child private CExtNodes.ToSulongNode toSulongNode; + @Child private GetMroNode getMroNode; private HashingStorageNodes.GetItemNode getGetItemNode() { if (getItemNode == null) { @@ -612,7 +614,7 @@ Object run(Object typestruct, PythonClass metaClass, PTuple baseClasses, PDict n private void computeAndSetDictoffset(Object tpDictoffset, PythonNativeClass cclass, long basicsize, long itemsize) { int initialDictoffset = castToIntNode.execute(tpDictoffset); if (initialDictoffset == 0) { - for (Object cls : cclass.getMethodResolutionOrder()) { + for (Object cls : getMro(cclass)) { if (cls != cclass) { if (cls instanceof PythonNativeClass) { int baseDictoffset = castToIntNode.execute(ensureReadAttrNode().execute(cls, __DICTOFFSET__)); @@ -679,6 +681,14 @@ private Object getLongItem(PDict nativeMembers, String key) { } return (long) item; } + + private PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } } @Builtin(name = "PyTruffle_Type_Slots", fixedNumOfPositionalArgs = 2, declaresExplicitSelf = true) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index d351616f29..758d156a8f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -97,6 +97,7 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialAttributeNames; @@ -251,7 +252,7 @@ private static Object getSulongTypeForClass(PythonClass klass) { } private static Object findBuiltinClass(PythonClass klass) { - PythonClass[] mro = klass.getMethodResolutionOrder(); + PythonClass[] mro = GetMroNode.doSlowPath(klass); Object sulongType = null; for (PythonClass superClass : mro) { sulongType = superClass.getSulongType(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java index f5d48a97f2..c37fdba82c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java @@ -55,6 +55,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; @@ -65,6 +66,7 @@ import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; import com.oracle.graal.python.nodes.object.GetClassNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateNodeFactory; @@ -92,6 +94,8 @@ Object repr(GetSetDescriptor descr) { abstract static class GetSetNode extends PythonTernaryBuiltinNode { + @Child private GetMroNode getMroNode; + private final IsBuiltinClassProfile isNoneBuiltinClassProfile = IsBuiltinClassProfile.create(); private final ConditionProfile isBuiltinProfile = ConditionProfile.createBinaryProfile(); private final IsBuiltinClassProfile isBuiltinClassProfile = IsBuiltinClassProfile.create(); @@ -106,13 +110,13 @@ protected boolean descr_check(LazyPythonClass descrType, String name, Object obj } if (isBuiltinProfile.profile(descrType instanceof PythonBuiltinClassType)) { PythonBuiltinClassType builtinClassType = (PythonBuiltinClassType) descrType; - for (PythonClass o : type.getMethodResolutionOrder()) { + for (PythonClass o : getMro(type)) { if (isBuiltinClassProfile.profileClass(o, builtinClassType)) { return false; } } } else { - for (PythonClass o : type.getMethodResolutionOrder()) { + for (PythonClass o : getMro(type)) { if (o == descrType) { return false; } @@ -121,6 +125,14 @@ protected boolean descr_check(LazyPythonClass descrType, String name, Object obj errorBranch.enter(); throw raise(TypeError, "descriptor '%s' for '%s' objects doesn't apply to '%s' object", name, descrType.getName(), type.getName()); } + + private PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } } @Builtin(name = __GET__, fixedNumOfPositionalArgs = 3) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java index a9981fd91c..25797c96ca 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -60,6 +60,7 @@ import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetTypeNodeGen; import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.SuperInitNodeFactory; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.argument.ReadIndexedArgumentNode; @@ -397,13 +398,14 @@ public Object get(SuperObject self, Object obj, @SuppressWarnings("unused") Obje @Builtin(name = SpecialMethodNames.__GETATTRIBUTE__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory public abstract static class GetattributeNode extends PythonBinaryBuiltinNode { - @Child ReadAttributeFromObjectNode readFromDict = ReadAttributeFromObjectNode.create(); - @Child LookupInheritedAttributeNode readGet = LookupInheritedAttributeNode.create(SpecialMethodNames.__GET__); - @Child GetObjectTypeNode getObjectType = GetObjectTypeNodeGen.create(); - @Child GetTypeNode getType; - @Child GetObjectNode getObject; - @Child CallTernaryMethodNode callGet; - @Child ObjectBuiltins.GetAttributeNode objectGetattributeNode; + @Child private ReadAttributeFromObjectNode readFromDict = ReadAttributeFromObjectNode.create(); + @Child private LookupInheritedAttributeNode readGet = LookupInheritedAttributeNode.create(SpecialMethodNames.__GET__); + @Child private GetObjectTypeNode getObjectType = GetObjectTypeNodeGen.create(); + @Child private GetTypeNode getType; + @Child private GetObjectNode getObject; + @Child private CallTernaryMethodNode callGet; + @Child private ObjectBuiltins.GetAttributeNode objectGetattributeNode; + @Child private GetMroNode getMroNode; private Object genericGetAttr(Object object, Object attr) { if (objectGetattributeNode == null) { @@ -442,7 +444,7 @@ public Object get(SuperObject self, Object attr) { getType = insert(GetTypeNodeGen.create()); } - PythonClass[] mro = startType.getMethodResolutionOrder(); + PythonClass[] mro = getMro(startType); /* No need to check the last one: it's gonna be skipped anyway. */ int i = 0; int n = mro.length; @@ -479,6 +481,14 @@ public Object get(SuperObject self, Object attr) { return genericGetAttr(self, attr); } + + private PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } } @Builtin(name = "__thisclass__", fixedNumOfPositionalArgs = 1, isGetter = true) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java index c6e925055a..a3c38c6053 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -179,7 +179,7 @@ public PythonClass getSuperClass() { return getBaseClasses().length > 0 ? getBaseClasses()[0] : null; } - public PythonClass[] getMethodResolutionOrder() { + PythonClass[] getMethodResolutionOrder() { return methodResolutionOrder; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index efed659276..9149344f12 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -40,6 +40,44 @@ */ package com.oracle.graal.python.builtins.objects.type; +import com.oracle.graal.python.PythonLanguage; +import com.oracle.graal.python.builtins.PythonBuiltinClassType; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroNodeGen; +import com.oracle.graal.python.nodes.PNodeWithContext; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; + public abstract class TypeNodes { + public abstract static class GetMroNode extends PNodeWithContext { + + public abstract PythonClass[] execute(Object obj); + + @Specialization + PythonClass[] doPythonClass(PythonClass obj) { + return obj.getMethodResolutionOrder(); + } + + @Specialization + PythonClass[] doPythonClass(PythonBuiltinClassType obj) { + return getBuiltinPythonClass(obj).getMethodResolutionOrder(); + } + + @TruffleBoundary + public static PythonClass[] doSlowPath(Object obj) { + if (obj instanceof PythonClass) { + return ((PythonClass) obj).getMethodResolutionOrder(); + } else if (obj instanceof PythonBuiltinClassType) { + return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getMethodResolutionOrder(); + } + CompilerDirectives.transferToInterpreter(); + throw new IllegalStateException("unknown type " + obj.getClass().getName()); + } + + public static GetMroNode create() { + return GetMroNodeGen.create(); + } + } + } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index 9f83a8e50c..e2c304ff78 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -44,10 +44,12 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.runtime.PythonCore; import com.oracle.graal.python.runtime.PythonOptions; import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; @@ -90,6 +92,7 @@ protected Object lookup(PythonClass klass, Object key, } protected final String key; + @Child private GetMroNode getMroNode; public LookupAttributeInMRONode(String key) { this.key = key; @@ -143,7 +146,7 @@ final static class PythonClassAssumptionPair { } protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonClass klass) { - PythonClass[] mro = klass.getMethodResolutionOrder(); + PythonClass[] mro = getMro(klass); Assumption attrAssumption = klass.createAttributeInMROFinalAssumption(key); for (int i = 0; i < mro.length; i++) { PythonClass cls = mro[i]; @@ -182,7 +185,7 @@ protected ReadAttributeFromObjectNode[] create(int size) { protected Object lookupConstantMRO(@SuppressWarnings("unused") PythonClass klass, @Cached("klass") @SuppressWarnings("unused") PythonClass cachedKlass, @Cached("cachedKlass.getLookupStableAssumption()") @SuppressWarnings("unused") Assumption lookupStable, - @Cached(value = "cachedKlass.getMethodResolutionOrder()", dimensions = 1) PythonClass[] mro, + @Cached(value = "getMro(cachedKlass)", dimensions = 1) PythonClass[] mro, @Cached("mro.length") @SuppressWarnings("unused") int mroLength, @Cached("create(mroLength)") ReadAttributeFromObjectNode[] readAttrNodes) { for (int i = 0; i < mro.length; i++) { @@ -201,8 +204,16 @@ protected Object lookup(PythonClass klass, return lookupSlow(klass, key, readAttrNode); } + protected PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } + protected static Object lookupSlow(PythonClass klass, Object key, ReadAttributeFromObjectNode readAttrNode) { - PythonClass[] mro = klass.getMethodResolutionOrder(); + PythonClass[] mro = GetMroNode.doSlowPath(klass); for (int i = 0; i < mro.length; i++) { PythonClass kls = mro[i]; Object value = readAttrNode.execute(kls, key); @@ -214,7 +225,7 @@ protected static Object lookupSlow(PythonClass klass, Object key, ReadAttributeF } public static Object lookupSlow(PythonClass klass, String key) { - PythonClass[] mro = klass.getMethodResolutionOrder(); + PythonClass[] mro = GetMroNode.doSlowPath(klass); for (int i = 0; i < mro.length; i++) { PythonClass kls = mro[i]; Object value = kls.getAttribute(key); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsFixedSubtypeMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsFixedSubtypeMRONode.java index a5bd728f95..fbbf04ec69 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsFixedSubtypeMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsFixedSubtypeMRONode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -44,6 +44,7 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.truffle.api.dsl.Cached; @@ -92,9 +93,10 @@ protected boolean isSubtype(PythonBuiltinClass derived) { @Specialization protected boolean isSubtype(PythonClass derived, - @Cached("create()") IsBuiltinClassProfile profile) { + @Cached("create()") IsBuiltinClassProfile profile, + @Cached("create()") GetMroNode getMroNode) { - for (PythonClass mro : derived.getMethodResolutionOrder()) { + for (PythonClass mro : getMroNode.execute(derived)) { if (profile.profileClass(mro, clazz)) { return true; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeMRONode.java index 4752a4eec6..28738247a3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeMRONode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -44,8 +44,10 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; @@ -53,6 +55,8 @@ public abstract class IsSubtypeMRONode extends PNodeWithContext { + @Child private GetMroNode getMroNode; + private final ConditionProfile equalsProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile innerEqualsProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile falseProfile = BranchProfile.create(); @@ -107,7 +111,7 @@ protected static boolean isSubtype(@SuppressWarnings("unused") PythonBuiltinClas protected boolean isSubtype(PythonClass derived, PythonBuiltinClassType clazz, @Cached("create()") IsBuiltinClassProfile profile) { - for (PythonClass mro : derived.getMethodResolutionOrder()) { + for (PythonClass mro : getMro(derived)) { if (profile.profileClass(mro, clazz)) { return true; } @@ -118,8 +122,7 @@ protected boolean isSubtype(PythonClass derived, PythonBuiltinClassType clazz, @Specialization protected boolean isSubtype(PythonClass derived, PythonClass clazz) { - - for (PythonClass mro : derived.getMethodResolutionOrder()) { + for (PythonClass mro : getMro(derived)) { if (mro == clazz) { return true; } @@ -127,4 +130,12 @@ protected boolean isSubtype(PythonClass derived, PythonClass clazz) { falseProfile.enter(); return false; } + + private PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java index d05897e434..a0542f3e76 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -41,9 +41,11 @@ package com.oracle.graal.python.nodes.classes; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.runtime.PythonOptions; import com.oracle.graal.python.runtime.exception.PythonErrorType; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.ImportStatic; @@ -58,6 +60,7 @@ public abstract class IsSubtypeNode extends PNodeWithContext { @Child private AbstractObjectGetBasesNode getBasesNode = AbstractObjectGetBasesNode.create(); @Child private AbstractObjectIsSubclassNode abstractIsSubclassNode = AbstractObjectIsSubclassNode.create(); + @Child private GetMroNode getMroNode; private final ConditionProfile exceptionDerivedProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile exceptionClsProfile = ConditionProfile.createBinaryProfile(); @@ -73,7 +76,7 @@ public static IsSubtypeNode create() { boolean isSubtypeOfConstantType(@SuppressWarnings("unused") PythonClass derived, @SuppressWarnings("unused") PythonClass cls, @Cached("derived") PythonClass cachedDerived, @Cached("cls") PythonClass cachedCls) { - for (PythonClass n : cachedDerived.getMethodResolutionOrder()) { + for (PythonClass n : getMro(cachedDerived)) { if (n == cachedCls) { return true; } @@ -85,7 +88,7 @@ boolean isSubtypeOfConstantType(@SuppressWarnings("unused") PythonClass derived, @ExplodeLoop boolean isSubtypeOfVariableType(@SuppressWarnings("unused") PythonClass derived, PythonClass cls, @Cached("derived") PythonClass cachedDerived) { - for (PythonClass n : cachedDerived.getMethodResolutionOrder()) { + for (PythonClass n : getMro(cachedDerived)) { if (n == cls) { return true; } @@ -95,7 +98,7 @@ boolean isSubtypeOfVariableType(@SuppressWarnings("unused") PythonClass derived, @Specialization(replaces = {"isSubtypeOfConstantType", "isSubtypeOfVariableType"}) boolean issubTypeGeneric(PythonClass derived, PythonClass cls) { - for (PythonClass n : derived.getMethodResolutionOrder()) { + for (PythonClass n : getMro(derived)) { if (n == cls) { return true; } @@ -115,4 +118,12 @@ public boolean isSubclass(Object derived, Object cls) { return abstractIsSubclassNode.execute(derived, cls); } + + private PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java index 9eb7a01375..f944062d9e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -30,6 +30,7 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.expression.ExpressionNode; import com.oracle.graal.python.nodes.frame.WriteNode; @@ -54,6 +55,7 @@ public class ExceptNode extends PNodeWithContext implements InstrumentableNode { @Child private ExpressionNode exceptType; @Child private WriteNode exceptName; @Child private GetLazyClassNode getClass; + @Child private GetMroNode getMroNode; // "object" is the uninitialized value (since it's not a valid error type) @CompilationFinal private PythonBuiltinClassType singleBuiltinError = PythonBuiltinClassType.PythonObject; @@ -150,7 +152,7 @@ private boolean matchesExceptionCached(VirtualFrame frame, LazyPythonClass lazyC } } else { // non-builtin class: look through MRO - PythonClass[] mro = ((PythonClass) lazyClass).getMethodResolutionOrder(); + PythonClass[] mro = getMro((PythonClass) lazyClass); for (PythonClass current : mro) { if (isClassProfile.profileClass(current, cachedError)) { matches = true; @@ -214,7 +216,7 @@ private boolean matches(Object expectedType, PythonClass clazz) { if (equalsProfile.profile(expectedType == clazz)) { return true; } - PythonClass[] mro = clazz.getMethodResolutionOrder(); + PythonClass[] mro = getMro(clazz); for (PythonClass current : mro) { if (expectedType == current) { return true; @@ -272,4 +274,12 @@ public WrapperNode createWrapper(ProbeNode probeNode) { public boolean isInstrumentable() { return getSourceSection() != null; } + + private PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java index 38db3c121a..d8b7c63f43 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -32,6 +32,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.exception.PBaseException; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; import com.oracle.graal.python.nodes.expression.ExpressionNode; @@ -39,6 +40,7 @@ import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.exception.PythonErrorType; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; @@ -55,6 +57,7 @@ public abstract class RaiseNode extends StatementNode { private final IsBuiltinClassProfile simpleBaseCheckProfile = IsBuiltinClassProfile.create(); private final IsBuiltinClassProfile iterativeBaseCheckProfile = IsBuiltinClassProfile.create(); private final BranchProfile baseCheckFailedProfile = BranchProfile.create(); + @Child private GetMroNode getMroNode; @Specialization public void reraise(PNone type, Object cause, @@ -83,7 +86,7 @@ private void checkBaseClass(PythonClass pythonClass) { if (simpleBaseCheckProfile.profileClass(pythonClass, BaseException)) { return; } - for (PythonClass klass : pythonClass.getMethodResolutionOrder()) { + for (PythonClass klass : getMro(pythonClass)) { if (iterativeBaseCheckProfile.profileClass(klass, BaseException)) { return; } @@ -112,6 +115,14 @@ public void doRaise(Object exception, Object cause) { throw raise(TypeError, "exceptions must derive from BaseException"); } + private PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } + public static RaiseNode create(ExpressionNode type, ExpressionNode cause) { return RaiseNodeGen.create(type, cause); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java index 6b07233c6c..0890abb593 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -69,6 +69,7 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.attributes.DeleteAttributeNode; import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode; @@ -309,6 +310,7 @@ private static final class KeysNode extends Node { @Child private IsMappingNode isMapping = IsMappingNode.create(); @Child private GetItemNode getItemNode; @Child private LenNode lenNode; + @Child private GetMroNode getMroNode; @TruffleBoundary public Object execute(Object obj, boolean includeInternal) { @@ -319,7 +321,7 @@ public Object execute(Object obj, boolean includeInternal) { HashSet keys = new HashSet<>(); PythonClass klass = getClass.execute(object); - for (PythonObject o : klass.getMethodResolutionOrder()) { + for (PythonObject o : getMro(klass)) { addKeysFromObject(keys, o, includeInternal); } if (object instanceof PythonObject) { @@ -349,6 +351,14 @@ public Object execute(Object obj, boolean includeInternal) { return factory.createTuple(keys.toArray(new String[keys.size()])); } + private PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } + private static void addKeysFromObject(HashSet keys, PythonObject o, boolean includeInternal) { for (Object k : o.getStorage().getShape().getKeys()) { String strKey; @@ -765,6 +775,7 @@ abstract static class PKeyInfoNode extends Node { @Child private GetClassNode getClassNode = GetClassNode.create(); @Child private IsImmutable isImmutable = new IsImmutable(); @Child private KeyForItemAccess itemKey = new KeyForItemAccess(); + @Child private GetMroNode getMroNode; public int access(Object object, Object fieldName) { if (fieldName instanceof Integer) { @@ -781,7 +792,7 @@ public int access(Object object, Object fieldName) { Object attr = PNone.NO_VALUE; PythonClass klass = getClassNode.execute(object); - for (PythonClass c : klass.getMethodResolutionOrder()) { + for (PythonClass c : getMro(klass)) { attr = readNode.execute(c, fieldName); if (attr != PNone.NO_VALUE) { owner = c; @@ -843,6 +854,14 @@ public int access(Object object, Object fieldName) { return info; } + + private PythonClass[] getMro(PythonClass clazz) { + if (getMroNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroNode = insert(GetMroNode.create()); + } + return getMroNode.execute(clazz); + } } @Resolve(message = "HAS_KEYS") From 54d781a44cf8cb4a863b501bd3afb285e1427d94 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 15 Jan 2019 17:06:19 +0100 Subject: [PATCH 051/202] Use node to get name of Python types. --- .../graal/python/builtins/Python3Core.java | 5 +- .../builtins/modules/BuiltinConstructors.java | 20 +++- .../builtins/objects/cell/CellBuiltins.java | 9 +- .../builtins/objects/cext/CExtNodes.java | 13 ++- .../builtins/objects/cext/NativeWrappers.java | 8 +- .../cext/PythonObjectNativeWrapperMR.java | 23 +++-- .../objects/exception/PBaseException.java | 14 +-- .../function/BuiltinFunctionBuiltins.java | 3 +- .../objects/function/PBuiltinFunction.java | 7 +- .../GetSetDescriptorTypeBuiltins.java | 18 +++- .../objects/method/BuiltinMethodBuiltins.java | 15 ++- .../objects/method/MethodBuiltins.java | 7 +- .../objects/object/ObjectBuiltins.java | 18 +++- .../builtins/objects/object/PythonObject.java | 5 +- .../builtins/objects/thread/LockBuiltins.java | 7 +- .../objects/type/LazyPythonClass.java | 2 - .../builtins/objects/type/PythonClass.java | 2 +- .../builtins/objects/type/TypeNodes.java | 37 ++++++++ .../python/nodes/object/GetClassNode.java | 7 +- .../python/nodes/object/GetLazyClassNode.java | 25 ++--- .../python/nodes/truffle/PythonTypesUtil.java | 91 ------------------- .../formatting/ErrorMessageFormatter.java | 5 +- .../runtime/formatting/InternalFormat.java | 5 +- 23 files changed, 176 insertions(+), 170 deletions(-) delete mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypesUtil.java diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java index c5e4dbf7ed..7126f72bd7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java @@ -155,6 +155,7 @@ import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeBuiltins; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.builtins.objects.zipimporter.ZipImporterBuiltins; import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.PythonCore; @@ -482,7 +483,7 @@ public void exportCInterface(PythonContext context) { // export all exception classes for the C API for (PythonBuiltinClassType errorType : PythonBuiltinClassType.EXCEPTIONS) { PythonClass errorClass = lookupType(errorType); - env.exportSymbol("python_" + errorClass.getName(), errorClass); + env.exportSymbol("python_" + GetNameNode.doSlowPath(errorClass), errorClass); } } } @@ -586,7 +587,7 @@ private void addBuiltinsTo(PythonObject obj, PythonBuiltins builtinsForObj) { boolean isPublic = entry.getValue().getValue(); if (isPublic) { PythonBuiltinClass pythonClass = entry.getKey(); - obj.setAttribute(pythonClass.getName(), pythonClass); + obj.setAttribute(GetNameNode.doSlowPath(pythonClass), pythonClass); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index 13c622fcf1..194b08e297 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -117,7 +117,9 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.argument.CreateArgumentsNode; @@ -1670,24 +1672,26 @@ public PZip zip(PythonClass cls, Object[] args, @Builtin(name = "function", minNumOfPositionalArgs = 3, maxNumOfPositionalArgs = 6, constructsClass = PythonBuiltinClassType.PFunction, isPublic = false) @GenerateNodeFactory public abstract static class FunctionNode extends PythonBuiltinNode { + @Child private GetNameNode getNameNode; + @Specialization public PFunction function(PythonClass cls, PCode code, PDict globals, String name, @SuppressWarnings("unused") PNone defaultArgs, @SuppressWarnings("unused") PNone closure) { - return factory().createFunction(name, cls.getName(), code.getArity(), code.getRootCallTarget(), globals, null); + return factory().createFunction(name, getTypeName(cls), code.getArity(), code.getRootCallTarget(), globals, null); } @Specialization public PFunction function(PythonClass cls, PCode code, PDict globals, String name, @SuppressWarnings("unused") PNone defaultArgs, PTuple closure) { - return factory().createFunction(name, cls.getName(), code.getArity(), code.getRootCallTarget(), globals, (PCell[]) closure.getArray()); + return factory().createFunction(name, getTypeName(cls), code.getArity(), code.getRootCallTarget(), globals, (PCell[]) closure.getArray()); } @Specialization public PFunction function(PythonClass cls, PCode code, PDict globals, String name, PTuple defaultArgs, @SuppressWarnings("unused") PNone closure) { - return factory().createFunction(name, cls.getName(), code.getArity(), code.getRootCallTarget(), globals, defaultArgs.getArray(), null); + return factory().createFunction(name, getTypeName(cls), code.getArity(), code.getRootCallTarget(), globals, defaultArgs.getArray(), null); } @Specialization public PFunction function(PythonClass cls, PCode code, PDict globals, String name, PTuple defaultArgs, PTuple closure) { - return factory().createFunction(name, cls.getName(), code.getArity(), code.getRootCallTarget(), globals, defaultArgs.getArray(), (PCell[]) closure.getArray()); + return factory().createFunction(name, getTypeName(cls), code.getArity(), code.getRootCallTarget(), globals, defaultArgs.getArray(), (PCell[]) closure.getArray()); } @Fallback @@ -1695,6 +1699,14 @@ public PFunction function(PythonClass cls, PCode code, PDict globals, String nam public PFunction function(Object cls, Object code, Object globals, Object name, Object defaultArgs, Object closure) { throw raise(TypeError, "function construction not supported for (%p, %p, %p, %p, %p, %p)", cls, code, globals, name, defaultArgs, closure); } + + private String getTypeName(Object typeObj) { + if (getNameNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getNameNode = insert(TypeNodes.GetNameNode.create()); + } + return getNameNode.execute(typeObj); + } } // builtin-function(method-def, self, module) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/CellBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/CellBuiltins.java index 71bf94717c..17aacc1fac 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/CellBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/CellBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -55,6 +55,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PNotImplemented; import com.oracle.graal.python.builtins.objects.cell.CellBuiltinsFactory.GetRefNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.nodes.object.GetLazyClassNode; @@ -120,12 +121,14 @@ public abstract static class ReprNode extends PythonBuiltinNode { @TruffleBoundary public String repr(PCell self, @Cached("create()") GetRefNode getRef, - @Cached("create()") GetLazyClassNode getClassNode) { + @Cached("create()") GetLazyClassNode getClassNode, + @Cached("create()") TypeNodes.GetNameNode getNameNode) { Object ref = getRef.execute(self); if (ref == null) { return String.format("", self.hashCode()); } - return String.format("", self.hashCode(), getClassNode.execute(ref).getName(), ref.hashCode()); + String typeName = getNameNode.execute(getClassNode.execute(ref)); + return String.format("", self.hashCode(), typeName, ref.hashCode()); } @Fallback diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index 131974be3b..20a36d86f4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -74,6 +74,8 @@ import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialMethodNames; @@ -315,13 +317,14 @@ Object doNativeNull(PythonNativeNull object) { @Specialization(guards = {"!isNativeClass(object)", "object == cachedObject"}, limit = "3") Object doPythonClass(@SuppressWarnings("unused") PythonClass object, @SuppressWarnings("unused") @Cached("object") PythonClass cachedObject, - @Cached("wrap(object)") PythonClassNativeWrapper wrapper) { + @Cached("wrapNativeClass(object)") PythonClassNativeWrapper wrapper) { return wrapper; } @Specialization(replaces = "doPythonClass", guards = {"!isNativeClass(object)"}) - Object doPythonClassUncached(PythonClass object) { - return PythonClassNativeWrapper.wrap(object); + Object doPythonClassUncached(PythonClass object, + @Cached("create()") TypeNodes.GetNameNode getNameNode) { + return PythonClassNativeWrapper.wrap(object, getNameNode.execute(object)); } @Specialization(guards = {"cachedClass == object.getClass()", "!isPythonClass(object)", "!isNativeObject(object)", "!isNoValue(object)"}, limit = "3") @@ -362,6 +365,10 @@ protected static boolean isNativeObject(PythonAbstractObject o) { return o instanceof PythonNativeObject; } + protected static PythonClassNativeWrapper wrapNativeClass(PythonClass object) { + return PythonClassNativeWrapper.wrap(object, GetNameNode.doSlowPath(object)); + } + public static ToSulongNode create() { return ToSulongNodeGen.create(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java index b9524932e0..07e520183f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java @@ -275,9 +275,9 @@ public static class PythonClassNativeWrapper extends PythonObjectNativeWrapper { private Object getBufferProc; private Object releaseBufferProc; - public PythonClassNativeWrapper(PythonClass object) { + public PythonClassNativeWrapper(PythonClass object, String typeName) { super(object); - this.nameWrapper = new CStringWrapper(object.getName()); + this.nameWrapper = new CStringWrapper(typeName); } public CStringWrapper getNameWrapper() { @@ -300,11 +300,11 @@ public void setReleaseBufferProc(Object releaseBufferProc) { this.releaseBufferProc = releaseBufferProc; } - public static PythonClassNativeWrapper wrap(PythonClass obj) { + public static PythonClassNativeWrapper wrap(PythonClass obj, String typeName) { // important: native wrappers are cached PythonClassNativeWrapper nativeWrapper = obj.getNativeWrapper(); if (nativeWrapper == null) { - nativeWrapper = new PythonClassNativeWrapper(obj); + nativeWrapper = new PythonClassNativeWrapper(obj, typeName); obj.setNativeWrapper(nativeWrapper); } return nativeWrapper; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index 758d156a8f..55324dc53e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -97,7 +97,9 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialAttributeNames; @@ -245,7 +247,7 @@ private static Object getSulongTypeForClass(PythonClass klass) { CompilerDirectives.transferToInterpreter(); sulongType = findBuiltinClass(klass); if (sulongType == null) { - throw new IllegalStateException("sulong type for " + klass.getName() + " was not registered"); + throw new IllegalStateException("sulong type for " + GetNameNode.doSlowPath(klass) + " was not registered"); } } return sulongType; @@ -310,10 +312,11 @@ public Object access(PythonNativeWrapper object, String key) { @ImportStatic({NativeMemberNames.class, SpecialMethodNames.class, SpecialAttributeNames.class}) @TypeSystemReference(PythonArithmeticTypes.class) abstract static class ReadNativeMemberNode extends PNodeWithContext { - @Child GetClassNode getClassNode; + @Child private GetClassNode getClassNode; @Child private ToSulongNode toSulongNode; @Child private HashingStorageNodes.GetItemNode getItemNode; @Child private CExtNodes.SizeofWCharNode sizeofWcharNode; + @Child private GetNameNode getNameNode; abstract Object execute(Object receiver, String key); @@ -720,17 +723,17 @@ Object doMemoryview(PMemoryView object, String key, } protected boolean isPyDateTimeCAPI(PythonObject object) { - return getClass(object).getName().equals("PyDateTime_CAPI"); + return getClassName(object).equals("PyDateTime_CAPI"); } protected boolean isPyDateTime(PythonObject object) { - return getClass(object).getName().equals("datetime"); + return getClassName(object).equals("datetime"); } @Specialization(guards = "isPyDateTimeCAPI(object)") Object doDatetimeCAPI(PythonObject object, String key, @Cached("create()") LookupAttributeInMRONode.Dynamic getAttrNode) { - return getToSulongNode().execute(getAttrNode.execute(getClassNode.execute(object), key)); + return getToSulongNode().execute(getAttrNode.execute(getClass(object), key)); } @Specialization(guards = "isPyDateTime(object)") @@ -798,6 +801,14 @@ private PythonClass getClass(Object obj) { return getClassNode.execute(obj); } + private String getClassName(Object obj) { + if (getNameNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getNameNode = insert(TypeNodes.GetNameNode.create()); + } + return getNameNode.execute(getClass(obj)); + } + private static Object getSliceComponent(int sliceComponent) { if (sliceComponent == PSlice.MISSING_INDEX) { return PNone.NONE; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/PBaseException.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/PBaseException.java index bd2be077f4..544a24b666 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/PBaseException.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/PBaseException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -50,6 +50,7 @@ import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.control.TopLevelExceptionHandler; import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode; import com.oracle.graal.python.nodes.object.GetLazyClassNode; @@ -155,19 +156,20 @@ public Object[] getMessageArgs() { } public String getFormattedMessage(GetLazyClassNode getClassNode) { + String typeName = GetNameNode.doSlowPath(getLazyPythonClass()); if (args == null) { if (messageArgs != null && messageArgs.length > 0) { - return getLazyPythonClass().getName() + ": " + FORMATTER.format(getClassNode, messageFormat, getMessageArgs()); + return typeName + ": " + FORMATTER.format(getClassNode, messageFormat, getMessageArgs()); } - return getLazyPythonClass().getName() + ": " + messageFormat; + return typeName + ": " + messageFormat; } else if (args.getSequenceStorage().length() == 0) { - return getLazyPythonClass().getName(); + return typeName; } else if (args.getSequenceStorage().length() == 1) { SequenceStorage store = args.getSequenceStorage(); Object item = store instanceof BasicSequenceStorage ? store.getItemNormalized(0) : ""; - return getLazyPythonClass().getName() + ": " + item.toString(); + return typeName + ": " + item.toString(); } else { - return getLazyPythonClass().getName() + ": " + args.toString(); + return typeName + ": " + args.toString(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java index ce5fdb970c..f3bf1500a0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java @@ -35,6 +35,7 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; @@ -69,7 +70,7 @@ Object reprModuleFunction(PBuiltinFunction self) { @Specialization(guards = "self.getEnclosingType() != null") @TruffleBoundary Object reprClassFunction(PBuiltinFunction self) { - return String.format("", self.getName(), self.getEnclosingType().getName()); + return String.format("", self.getName(), GetNameNode.doSlowPath(self.getEnclosingType())); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java index 7e58bd8e32..8a3059c5e0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -32,6 +32,7 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; @@ -58,7 +59,7 @@ public PBuiltinFunction(LazyPythonClass clazz, String name, LazyPythonClass encl this.arity = arity; this.getStorage().define(__NAME__, name); if (enclosingType != null) { - this.getStorage().define(__QUALNAME__, enclosingType.getName() + "." + name); + this.getStorage().define(__QUALNAME__, GetNameNode.doSlowPath(enclosingType) + "." + name); } else { this.getStorage().define(__QUALNAME__, name); } @@ -103,7 +104,7 @@ public String toString() { if (enclosingType == null) { return String.format("PBuiltinFunction %s at 0x%x", name, hashCode()); } else { - return String.format("PBuiltinFunction %s.%s at 0x%x", enclosingType.getName(), name, hashCode()); + return String.format("PBuiltinFunction %s.%s at 0x%x", GetNameNode.doSlowPath(enclosingType), name, hashCode()); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java index c37fdba82c..163c3d13ca 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java @@ -56,6 +56,7 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; @@ -88,13 +89,14 @@ abstract static class GetSetReprNode extends PythonUnaryBuiltinNode { @Specialization @TruffleBoundary Object repr(GetSetDescriptor descr) { - return String.format("", descr.getName(), descr.getType().getName()); + return String.format("", descr.getName(), GetNameNode.doSlowPath(descr.getType())); } } abstract static class GetSetNode extends PythonTernaryBuiltinNode { @Child private GetMroNode getMroNode; + @Child private GetNameNode getNameNode; private final IsBuiltinClassProfile isNoneBuiltinClassProfile = IsBuiltinClassProfile.create(); private final ConditionProfile isBuiltinProfile = ConditionProfile.createBinaryProfile(); @@ -123,7 +125,7 @@ protected boolean descr_check(LazyPythonClass descrType, String name, Object obj } } errorBranch.enter(); - throw raise(TypeError, "descriptor '%s' for '%s' objects doesn't apply to '%s' object", name, descrType.getName(), type.getName()); + throw raise(TypeError, "descriptor '%s' for '%s' objects doesn't apply to '%s' object", name, getTypeName(descrType), getTypeName(type)); } private PythonClass[] getMro(PythonClass clazz) { @@ -133,6 +135,14 @@ private PythonClass[] getMro(PythonClass clazz) { } return getMroNode.execute(clazz); } + + protected Object getTypeName(LazyPythonClass descrType) { + if (getNameNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getNameNode = insert(GetNameNode.create()); + } + return getNameNode.execute(descrType); + } } @Builtin(name = __GET__, fixedNumOfPositionalArgs = 3) @@ -151,7 +161,7 @@ Object get(GetSetDescriptor descr, Object obj, PythonClass type, return callNode.executeObject(descr.getGet(), obj); } else { branchProfile.enter(); - throw raise(AttributeError, "attribute '%s' of '%s' objects is not readable", descr.getName(), descr.getType().getName()); + throw raise(AttributeError, "attribute '%s' of '%s' objects is not readable", descr.getName(), getTypeName(descr.getType())); } } @@ -187,7 +197,7 @@ Object set(GetSetDescriptor descr, Object obj, Object value, return callNode.executeObject(descr.getSet(), obj, value); } else { branchProfile.enter(); - throw raise(AttributeError, "attribute '%s' of '%s' object is not writable", descr.getName(), descr.getType().getName()); + throw raise(AttributeError, "attribute '%s' of '%s' object is not writable", descr.getName(), getTypeName(descr.getType())); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/method/BuiltinMethodBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/method/BuiltinMethodBuiltins.java index bdc654d65b..36847ce17b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/method/BuiltinMethodBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/method/BuiltinMethodBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. @@ -40,6 +40,7 @@ import com.oracle.graal.python.builtins.objects.function.AbstractFunctionBuiltins; import com.oracle.graal.python.builtins.objects.function.PFunction; import com.oracle.graal.python.builtins.objects.module.PythonModule; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.attributes.GetAttributeNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; @@ -92,16 +93,20 @@ String reprBuiltinFunction(PBuiltinMethod self, @TruffleBoundary Object reprBuiltinMethod(PBuiltinMethod self, @Cached("create()") GetLazyClassNode getClassNode, - @Cached("createGetAttributeNode()") GetAttributeNode getNameNode) { - return String.format("", getNameNode.executeObject(self.getFunction()), getClassNode.execute(self.getSelf()).getName(), self.hashCode()); + @Cached("createGetAttributeNode()") GetAttributeNode getNameNode, + @Cached("create()") GetNameNode getTypeNameNode) { + String typeName = getTypeNameNode.execute(getClassNode.execute(self.getSelf())); + return String.format("", getNameNode.executeObject(self.getFunction()), typeName, self.hashCode()); } @Specialization(guards = "!isBuiltinFunction(self)") @TruffleBoundary Object reprBuiltinMethod(PMethod self, @Cached("create()") GetLazyClassNode getClassNode, - @Cached("createGetAttributeNode()") GetAttributeNode getNameNode) { - return String.format("", getNameNode.executeObject(self.getFunction()), getClassNode.execute(self.getSelf()).getName(), self.hashCode()); + @Cached("createGetAttributeNode()") GetAttributeNode getNameNode, + @Cached("create()") GetNameNode getTypeNameNode) { + String typeName = getTypeNameNode.execute(getClassNode.execute(self.getSelf())); + return String.format("", getNameNode.executeObject(self.getFunction()), typeName, self.hashCode()); } protected static GetAttributeNode createGetAttributeNode() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/method/MethodBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/method/MethodBuiltins.java index 0c62a5983d..2df5b498bd 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/method/MethodBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/method/MethodBuiltins.java @@ -43,6 +43,7 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.function.FunctionBuiltins; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.attributes.GetAttributeNode; import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode; @@ -96,8 +97,10 @@ public abstract static class ReprNode extends PythonUnaryBuiltinNode { @TruffleBoundary Object reprMethod(PMethod self, @Cached("create()") GetLazyClassNode getClassNode, - @Cached("createGetAttributeNode()") GetAttributeNode getNameAttrNode) { - return String.format("", getNameAttrNode.executeObject(self.getFunction()), getClassNode.execute(self.getSelf()).getName(), self.hashCode()); + @Cached("createGetAttributeNode()") GetAttributeNode getNameAttrNode, + @Cached("create()") GetNameNode getTypeNameNode) { + String typeName = getTypeNameNode.execute(getClassNode.execute(self.getSelf())); + return String.format("", getNameAttrNode.executeObject(self.getFunction()), typeName, self.hashCode()); } protected static GetAttributeNode createGetAttributeNode() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java index 257c4ef9cf..bb9cb8ceb9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java @@ -69,6 +69,7 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; @@ -110,9 +111,10 @@ protected List> getNodeFa @Builtin(name = __CLASS__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) @GenerateNodeFactory abstract static class ClassNode extends PythonBinaryBuiltinNode { - @Child LookupAttributeInMRONode lookupSlotsInSelf; - @Child LookupAttributeInMRONode lookupSlotsInOther; - @Child BinaryComparisonNode slotsAreEqual; + @Child private LookupAttributeInMRONode lookupSlotsInSelf; + @Child private LookupAttributeInMRONode lookupSlotsInOther; + @Child private BinaryComparisonNode slotsAreEqual; + @Child private TypeNodes.GetNameNode getTypeNameNode; private static final String ERROR_MESSAGE = "__class__ assignment only supported for heap types or ModuleType subclasses"; @@ -152,7 +154,7 @@ PNone setClass(PythonObject self, PythonClass value, Object otherSlots = getLookupSlotsInOther().execute(value); if (otherSlots == PNone.NO_VALUE || !getSlotsAreEqual().executeBool(selfSlots, otherSlots)) { errorSlotsBranch.enter(); - throw raise(TypeError, "__class__ assignment: '%s' object layout differs from '%s'", value.getName(), lazyClass.getName()); + throw raise(TypeError, "__class__ assignment: '%s' object layout differs from '%s'", getTypeName(value), getTypeName(lazyClass)); } } self.setLazyPythonClass(value); @@ -192,6 +194,14 @@ PythonClass getClass(@SuppressWarnings("unused") Object self, @SuppressWarnings( PythonClass getClass(@SuppressWarnings("unused") Object self, Object value) { throw raise(TypeError, "__class__ must be set to a class, not '%p' object", value); } + + private String getTypeName(LazyPythonClass clazz) { + if (getTypeNameNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getTypeNameNode = insert(TypeNodes.GetNameNode.create()); + } + return getTypeNameNode.execute(clazz); + } } @Builtin(name = __INIT__, takesVarArgs = true, minNumOfPositionalArgs = 1, takesVarKeywordArgs = true) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java index 602c8e1e8b..a4675978f4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -36,6 +36,7 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -176,7 +177,7 @@ public int compareTo(Object o) { */ @Override public String toString() { - return "<" + getLazyPythonClass().getName() + " object at 0x" + Integer.toHexString(hashCode()) + ">"; + return "<" + GetNameNode.doSlowPath(getLazyPythonClass()) + " object at 0x" + Integer.toHexString(hashCode()) + ">"; } /** diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/LockBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/LockBuiltins.java index eb69a7fd32..022760b6db 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/LockBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/LockBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -57,6 +57,7 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.thread.LockBuiltinsFactory.AcquireLockNodeFactory; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.expression.CastToBooleanNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; @@ -198,7 +199,7 @@ abstract static class ReprLockNode extends PythonUnaryBuiltinNode { String repr(PLock self) { return String.format("<%s %s object at %s>", (self.locked()) ? "locked" : "unlocked", - self.getPythonClass().getName(), + GetNameNode.doSlowPath(self.getPythonClass()), self.hashCode()); } @@ -207,7 +208,7 @@ String repr(PLock self) { String repr(PRLock self) { return String.format("<%s %s object owner=%d count=%d at %s>", (self.locked()) ? "locked" : "unlocked", - self.getPythonClass().getName(), + GetNameNode.doSlowPath(self.getPythonClass()), self.getOwnerId(), self.getCount(), self.hashCode()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java index a6da5f49d1..675aafd300 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java @@ -45,6 +45,4 @@ public interface LazyPythonClass { Shape getInstanceShape(); - - String getName(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java index a3c38c6053..3fa4561c80 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java @@ -183,7 +183,7 @@ PythonClass[] getMethodResolutionOrder() { return methodResolutionOrder; } - public String getName() { + String getName() { return className; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 9149344f12..89d404aeaf 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -43,6 +43,8 @@ import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetNameNodeGen; +import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -80,4 +82,39 @@ public static GetMroNode create() { } } + public abstract static class GetNameNode extends PNodeWithContext { + + public abstract String execute(Object obj); + + @Specialization + String doPythonClass(PythonClass obj) { + return obj.getName(); + } + + @Specialization + String doPythonClass(PythonBuiltinClassType obj) { + return obj.getName(); + } + + @TruffleBoundary + public static String doSlowPath(Object obj) { + if (obj instanceof PythonClass) { + return ((PythonClass) obj).getName(); + } else if (obj instanceof PythonBuiltinClassType) { + // TODO(fa): remove this special case + if (obj == PythonBuiltinClassType.TruffleObject) { + return BuiltinNames.FOREIGN; + } + return ((PythonBuiltinClassType) obj).getName(); + } + CompilerDirectives.transferToInterpreter(); + throw new IllegalStateException("unknown type " + obj.getClass().getName()); + } + + public static GetNameNode create() { + return GetNameNodeGen.create(); + } + + } + } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java index 02328136ca..8563b3cea7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -246,10 +246,13 @@ public static PythonClass getItSlowPath(Object o) { return core.lookupType(PythonBuiltinClassType.Boolean); } else if (o instanceof Double || o instanceof Float) { return core.lookupType(PythonBuiltinClassType.PFloat); - } else if (o instanceof Integer || o instanceof Long || o instanceof Short || o instanceof Byte) { + } else if (o instanceof Integer || o instanceof Long || o instanceof Short || o instanceof Byte || o instanceof PythonNativeVoidPtr) { return core.lookupType(PythonBuiltinClassType.PInt); } else if (o instanceof PythonObject) { return ((PythonObject) o).getPythonClass(); + } else if (o instanceof PythonNativeObject) { + // TODO(fa): implement + throw new UnsupportedOperationException("get class of native object on slow path not yet implemented"); } else if (o instanceof PEllipsis) { return core.lookupType(PythonBuiltinClassType.PEllipsis); } else if (o instanceof PNotImplemented) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java index 6d8dcf0e7d..f2c5193bf9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -51,7 +51,6 @@ import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; -import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.truffle.PythonTypes; @@ -177,32 +176,24 @@ public static LazyPythonClass getItSlowPath(Object o) { return PythonBuiltinClassType.Boolean; } else if (o instanceof Double || o instanceof Float) { return PythonBuiltinClassType.PFloat; - } else if (o instanceof Integer || o instanceof Long || o instanceof Short || o instanceof Byte) { + } else if (o instanceof Integer || o instanceof Long || o instanceof Short || o instanceof Byte || o instanceof PythonNativeVoidPtr) { return PythonBuiltinClassType.PInt; } else if (o instanceof PythonObject) { return ((PythonObject) o).getLazyPythonClass(); + } else if (o instanceof PythonNativeObject) { + // TODO(fa): implement + throw new UnsupportedOperationException("get class of native object on slow path not yet implemented"); } else if (o instanceof PEllipsis) { return PythonBuiltinClassType.PEllipsis; } else if (o instanceof PNotImplemented) { return PythonBuiltinClassType.PNotImplemented; } else if (o instanceof PNone) { return PythonBuiltinClassType.PNone; - } else { - return null; - } - } - - @TruffleBoundary - public static String getNameSlowPath(Object o) { - if (PGuards.isForeignObject(o)) { - return BuiltinNames.FOREIGN; - } - LazyPythonClass lazyClass = getItSlowPath(o); - if (lazyClass != null) { - return lazyClass.getName(); + } else if (o instanceof GetSetDescriptor) { + return PythonBuiltinClassType.GetSetDescriptor; } else { CompilerDirectives.transferToInterpreter(); - return o.toString(); + throw new IllegalStateException("unknown type " + o.getClass().getName()); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypesUtil.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypesUtil.java deleted file mode 100644 index b252a962a2..0000000000 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypesUtil.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. - * Copyright (c) 2013, Regents of the University of California - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.oracle.graal.python.nodes.truffle; - -import com.oracle.truffle.api.CompilerAsserts; - -import static com.oracle.graal.python.nodes.BuiltinNames.COMPLEX; -import static com.oracle.graal.python.nodes.BuiltinNames.DICT; -import static com.oracle.graal.python.nodes.BuiltinNames.FLOAT; -import static com.oracle.graal.python.nodes.BuiltinNames.INT; -import static com.oracle.graal.python.nodes.BuiltinNames.LIST; -import static com.oracle.graal.python.nodes.BuiltinNames.RANGE; -import static com.oracle.graal.python.nodes.BuiltinNames.SET; -import static com.oracle.graal.python.nodes.BuiltinNames.STR; -import static com.oracle.graal.python.nodes.BuiltinNames.TUPLE; - -import com.oracle.graal.python.builtins.objects.PNone; -import com.oracle.graal.python.builtins.objects.array.PArray; -import com.oracle.graal.python.builtins.objects.complex.PComplex; -import com.oracle.graal.python.builtins.objects.dict.PDict; -import com.oracle.graal.python.builtins.objects.ints.PInt; -import com.oracle.graal.python.builtins.objects.list.PList; -import com.oracle.graal.python.builtins.objects.object.PythonObject; -import com.oracle.graal.python.builtins.objects.range.PRange; -import com.oracle.graal.python.builtins.objects.set.PSet; -import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.PythonClass; - -public class PythonTypesUtil { - - /** - * TODO This method should be extended to support the remaining types. - */ - public static String getPythonTypeName(Object object) { - CompilerAsserts.neverPartOfCompilation(); - - if (object instanceof Integer || object instanceof PInt) { - return INT; - } else if (object instanceof Double) { - return FLOAT; - } else if (object instanceof PComplex) { - return COMPLEX; - } else if (object instanceof String) { - return STR; - } else if (object instanceof PList) { - return LIST; - } else if (object instanceof PTuple) { - return TUPLE; - } else if (object instanceof PRange) { - return RANGE; - } else if (object instanceof PArray) { - return "array"; - } else if (object instanceof PSet) { - return SET; - } else if (object instanceof PDict) { - return DICT; - } else if (object instanceof PNone) { - return "None"; - } else if (object instanceof PythonClass) { - return object.toString(); - } else if (object instanceof PythonObject) { - return ((PythonObject) object).getLazyPythonClass().getName(); - } - - throw new RuntimeException("Unsupported type name " + object.getClass()); - } - -} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/ErrorMessageFormatter.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/ErrorMessageFormatter.java index d75be145b6..4e69a26e07 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/ErrorMessageFormatter.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/ErrorMessageFormatter.java @@ -44,6 +44,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.object.GetLazyClassNode; /** @@ -106,9 +107,9 @@ public String format(GetLazyClassNode getClassNode, String format, Object... arg private static String getClassName(GetLazyClassNode getClassNode, Object obj) { if (getClassNode != null) { - return getClassNode.execute(obj).getName(); + return GetNameNode.doSlowPath(getClassNode.execute(obj)); } - return GetLazyClassNode.getNameSlowPath(obj); + return GetNameNode.doSlowPath(GetLazyClassNode.getItSlowPath(obj)); } private static Object[] compact(Object[] args, int removedCnt) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/InternalFormat.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/InternalFormat.java index 5d019f97c8..0b358a342d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/InternalFormat.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/InternalFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) -2016 Jython Developers * * Licensed under PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 @@ -12,7 +12,6 @@ import com.oracle.graal.python.builtins.objects.bytes.PBytes; import com.oracle.graal.python.builtins.objects.str.PString; -import com.oracle.graal.python.nodes.truffle.PythonTypesUtil; import com.oracle.graal.python.runtime.PythonCore; import com.oracle.graal.python.runtime.PythonParser.ParserErrorCallback; import com.oracle.graal.python.runtime.exception.PException; @@ -52,7 +51,7 @@ public static Spec fromText(PythonCore core, Object text, String method) { } else if (text instanceof String) { return fromText(core, (String) text); } else { - throw core.raise(TypeError, "%s argument 1 must be str, not %s", method, PythonTypesUtil.getPythonTypeName(text)); + throw core.raise(TypeError, "%s argument 1 must be str, not %p", method, text); } } From adf8ace6d4ab44d3bd2deb86b10c2ed7a1d3a4cb Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 15 Jan 2019 17:43:06 +0100 Subject: [PATCH 052/202] Move 'GetTypeFlagsNode' to 'TypeNodes'. --- .../builtins/modules/TruffleCextBuiltins.java | 2 +- .../cext/PythonObjectNativeWrapperMR.java | 2 +- .../objects/type/GetTypeFlagsNode.java | 70 ------------------- .../builtins/objects/type/TypeNodes.java | 27 +++++++ 4 files changed, 29 insertions(+), 72 deletions(-) delete mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/GetTypeFlagsNode.java diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 37a3a48457..2f7fb30713 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -128,10 +128,10 @@ import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.GetTypeFlagsNode; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialAttributeNames; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index 55324dc53e..96570d4f4b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -93,13 +93,13 @@ import com.oracle.graal.python.builtins.objects.set.PSet; import com.oracle.graal.python.builtins.objects.slice.PSlice; import com.oracle.graal.python.builtins.objects.str.PString; -import com.oracle.graal.python.builtins.objects.type.GetTypeFlagsNode; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialAttributeNames; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/GetTypeFlagsNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/GetTypeFlagsNode.java deleted file mode 100644 index 116bab0006..0000000000 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/GetTypeFlagsNode.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2018, 2018, 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 - * - * Subject to the condition set forth below, permission is hereby granted to any - * person obtaining a copy of this software, associated documentation and/or - * data (collectively the "Software"), free of charge and under any and all - * copyright rights in the Software, and any and all patent rights owned or - * freely licensable by each licensor hereunder covering either (i) the - * unmodified Software as contributed to or provided by such licensor, or (ii) - * the Larger Works (as defined below), to deal in both - * - * (a) the Software, and - * - * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if - * one is included with the Software each a "Larger Work" to which the Software - * is contributed by such licensors), - * - * without restriction, including without limitation the rights to copy, create - * derivative works of, display, perform, and distribute the Software and make, - * use, sell, offer for sale, import, export, have made, and have sold the - * Software and the Larger Work(s), and to sublicense the foregoing rights on - * either these or other terms. - * - * This license is subject to the following condition: - * - * The above copyright notice and either this complete permission notice or at a - * minimum a reference to the UPL must be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.oracle.graal.python.builtins.objects.type; - -import com.oracle.graal.python.nodes.PNodeWithContext; -import com.oracle.truffle.api.dsl.Specialization; - -public abstract class GetTypeFlagsNode extends PNodeWithContext { - - public abstract long execute(PythonClass clazz); - - @Specialization(guards = "isInitialized(clazz)") - long doInitialized(PythonClass clazz) { - return clazz.getFlagsContainer().flags; - } - - @Specialization - long doGeneric(PythonClass clazz) { - if (!isInitialized(clazz)) { - return clazz.getFlags(); - } - return clazz.getFlagsContainer().flags; - } - - protected static boolean isInitialized(PythonClass clazz) { - return clazz.getFlagsContainer().initialDominantBase == null; - } - - public static GetTypeFlagsNode create() { - return GetTypeFlagsNodeGen.create(); - } -} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 89d404aeaf..33f50dd470 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -44,6 +44,7 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetNameNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetTypeFlagsNodeGen; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.truffle.api.CompilerDirectives; @@ -52,6 +53,32 @@ public abstract class TypeNodes { + public abstract static class GetTypeFlagsNode extends PNodeWithContext { + + public abstract long execute(PythonClass clazz); + + @Specialization(guards = "isInitialized(clazz)") + long doInitialized(PythonClass clazz) { + return clazz.getFlagsContainer().flags; + } + + @Specialization + long doGeneric(PythonClass clazz) { + if (!isInitialized(clazz)) { + return clazz.getFlags(); + } + return clazz.getFlagsContainer().flags; + } + + protected static boolean isInitialized(PythonClass clazz) { + return clazz.getFlagsContainer().initialDominantBase == null; + } + + public static GetTypeFlagsNode create() { + return GetTypeFlagsNodeGen.create(); + } + } + public abstract static class GetMroNode extends PNodeWithContext { public abstract PythonClass[] execute(Object obj); From a3a0fae8535c3c6fecae2715a4914e317cbf0efe Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 15 Jan 2019 17:50:33 +0100 Subject: [PATCH 053/202] Use node to get base/super type of a Python type. --- .../cext/PythonObjectNativeWrapperMR.java | 9 +++-- .../builtins/objects/type/PythonClass.java | 2 +- .../builtins/objects/type/TypeNodes.java | 34 +++++++++++++++++-- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index 96570d4f4b..0115334c37 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -99,6 +99,7 @@ import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSuperClassNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; @@ -400,10 +401,12 @@ Object doTpName(PythonClass object, @SuppressWarnings("unused") String key) { } @Specialization(guards = "eq(TP_BASE, key)") - Object doTpBase(PythonClass object, @SuppressWarnings("unused") String key) { - PythonClass superClass = object.getSuperClass(); + Object doTpBase(PythonClass object, @SuppressWarnings("unused") String key, + @Cached("create()") GetSuperClassNode getSuperClassNode, + @Cached("createBinaryProfile()") ConditionProfile profile) { + LazyPythonClass superClass = getSuperClassNode.execute(object); if (superClass != null) { - return getToSulongNode().execute(superClass); + return getToSulongNode().execute(getPythonClass(superClass, profile)); } return getToSulongNode().execute(object); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java index 3fa4561c80..3df0d4d001 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java @@ -175,7 +175,7 @@ public Shape getInstanceShape() { return instanceShape; } - public PythonClass getSuperClass() { + PythonClass getSuperClass() { return getBaseClasses().length > 0 ? getBaseClasses()[0] : null; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 33f50dd470..d68ebec1bc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -44,10 +44,10 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetNameNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSuperClassNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetTypeFlagsNodeGen; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.PNodeWithContext; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; @@ -100,7 +100,6 @@ public static PythonClass[] doSlowPath(Object obj) { } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getMethodResolutionOrder(); } - CompilerDirectives.transferToInterpreter(); throw new IllegalStateException("unknown type " + obj.getClass().getName()); } @@ -134,7 +133,6 @@ public static String doSlowPath(Object obj) { } return ((PythonBuiltinClassType) obj).getName(); } - CompilerDirectives.transferToInterpreter(); throw new IllegalStateException("unknown type " + obj.getClass().getName()); } @@ -144,4 +142,34 @@ public static GetNameNode create() { } + public abstract static class GetSuperClassNode extends PNodeWithContext { + + public abstract LazyPythonClass execute(Object obj); + + @Specialization + LazyPythonClass doPythonClass(PythonClass obj) { + return obj.getSuperClass(); + } + + @Specialization + LazyPythonClass doPythonClass(PythonBuiltinClassType obj) { + return obj.getBase(); + } + + @TruffleBoundary + public static LazyPythonClass doSlowPath(Object obj) { + if (obj instanceof PythonClass) { + return ((PythonClass) obj).getSuperClass(); + } else if (obj instanceof PythonBuiltinClassType) { + return ((PythonBuiltinClassType) obj).getBase(); + } + throw new IllegalStateException("unknown type " + obj.getClass().getName()); + } + + public static GetSuperClassNode create() { + return GetSuperClassNodeGen.create(); + } + + } + } From fd07a52447bf01127783f9ef26ffa042503ce461 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 15 Jan 2019 18:10:32 +0100 Subject: [PATCH 054/202] Use node to access subclasses set of a Python type. --- .../builtins/modules/TruffleCextBuiltins.java | 12 ++++--- .../cext/PythonObjectNativeWrapperMR.java | 3 +- .../builtins/objects/type/PythonClass.java | 4 +-- .../builtins/objects/type/TypeBuiltins.java | 15 ++++++--- .../builtins/objects/type/TypeNodes.java | 33 +++++++++++++++++++ 5 files changed, 56 insertions(+), 11 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 2f7fb30713..f08e02363b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -63,6 +63,7 @@ import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Set; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.Builtin; @@ -130,6 +131,7 @@ import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; @@ -1604,8 +1606,10 @@ Object doUnpackLongOvf(Object start, Object stop, Object step, Object lengthObj, abstract static class PyTruffle_Add_Subclass extends NativeBuiltin { @Specialization - int doManagedSubclass(PythonClassNativeWrapper base, @SuppressWarnings("unused") Object key, PythonClassNativeWrapper value) { - addToSet((PythonClass) base.getPythonObject(), (PythonClass) value.getPythonObject()); + int doManagedSubclass(PythonClassNativeWrapper base, @SuppressWarnings("unused") Object key, PythonClassNativeWrapper value, + @Cached("create()") TypeNodes.GetSubclassesNode getSubclassesNode) { + Set subclasses = getSubclassesNode.execute(base.getPythonObject()); + addToSet(subclasses, (PythonClass) value.getPythonObject()); return 0; } @@ -1615,8 +1619,8 @@ int doGeneric(@SuppressWarnings("unused") Object base, @SuppressWarnings("unused } @TruffleBoundary - private static void addToSet(PythonClass base, PythonClass value) { - base.getSubClasses().add(value); + private static void addToSet(Set subclasses, PythonClass value) { + subclasses.add(value); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index 0115334c37..e5fa8ed065 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -99,6 +99,7 @@ import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSuperClassNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; @@ -880,7 +881,7 @@ Object doTpSubclasses(PythonClass object, @SuppressWarnings("unused") String key // TODO more type checking; do fast path PDict dict = (PDict) value.getPythonObject(); for (Object item : dict.items()) { - object.getSubClasses().add((PythonClass) item); + GetSubclassesNode.doSlowPath(object).add((PythonClass) item); } return value; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java index 3df0d4d001..936cd56c52 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java @@ -273,7 +273,7 @@ public void setAttribute(Object key, Object value) { * This method supports initialization and solves boot-order problems and should not normally be * used. */ - public void unsafeSetSuperClass(PythonClass... newBaseClasses) { + private void unsafeSetSuperClass(PythonClass... newBaseClasses) { // TODO: if this is used outside bootstrapping, it needs to call // computeMethodResolutionOrder for subclasses. @@ -288,7 +288,7 @@ public void unsafeSetSuperClass(PythonClass... newBaseClasses) { computeMethodResolutionOrder(); } - public final Set getSubClasses() { + final Set getSubClasses() { return subClasses; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index a6b56f0422..fb8d11c6e5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. @@ -50,6 +50,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Set; import com.oracle.graal.python.builtins.Builtin; import com.oracle.graal.python.builtins.CoreFunctions; @@ -64,6 +65,7 @@ import com.oracle.graal.python.builtins.objects.mappingproxy.PMappingproxy; import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.type.TypeBuiltinsFactory.CallNodeFactory; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.argument.positional.PositionalArgumentsNode; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; @@ -463,10 +465,15 @@ boolean instanceCheck(PythonClass cls, Object derived) { static abstract class SubclassesNode extends PythonUnaryBuiltinNode { @Specialization - @TruffleBoundary - PList getSubclasses(PythonClass cls) { + PList getSubclasses(PythonClass cls, + @Cached("create()") GetSubclassesNode getSubclassesNode) { // TODO: missing: keep track of subclasses - return factory().createList(cls.getSubClasses().toArray()); + return factory().createList(toArray(getSubclassesNode.execute(cls))); + } + + @TruffleBoundary + private static Object[] toArray(Set subclasses) { + return subclasses.toArray(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index d68ebec1bc..8f968282f5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -40,10 +40,13 @@ */ package com.oracle.graal.python.builtins.objects.type; +import java.util.Set; + import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetNameNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSubclassesNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSuperClassNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetTypeFlagsNodeGen; import com.oracle.graal.python.nodes.BuiltinNames; @@ -172,4 +175,34 @@ public static GetSuperClassNode create() { } + public abstract static class GetSubclassesNode extends PNodeWithContext { + + public abstract Set execute(Object obj); + + @Specialization + Set doPythonClass(PythonClass obj) { + return obj.getSubClasses(); + } + + @Specialization + Set doPythonClass(PythonBuiltinClassType obj) { + return getBuiltinPythonClass(obj).getSubClasses(); + } + + @TruffleBoundary + public static Set doSlowPath(Object obj) { + if (obj instanceof PythonClass) { + return ((PythonClass) obj).getSubClasses(); + } else if (obj instanceof PythonBuiltinClassType) { + return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getSubClasses(); + } + throw new IllegalStateException("unknown type " + obj.getClass().getName()); + } + + public static GetSubclassesNode create() { + return GetSubclassesNodeGen.create(); + } + + } + } From 2fca05502762a647ec65b40093d7e54359037d2a Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 16 Jan 2019 18:39:27 +0100 Subject: [PATCH 055/202] Refactor class hierarchy of Python type representation. --- .../com.oracle.graal.python.cext/src/capi.c | 5 + .../graal/python/builtins/Python3Core.java | 5 +- .../modules/BinasciiModuleBuiltins.java | 7 +- .../builtins/modules/BuiltinConstructors.java | 29 +- .../builtins/modules/BuiltinFunctions.java | 7 +- .../builtins/modules/TruffleCextBuiltins.java | 43 +-- .../builtins/objects/cext/CExtNodes.java | 137 ++++++- .../builtins/objects/cext/NativeWrappers.java | 15 +- .../builtins/objects/cext/PThreadStateMR.java | 5 +- .../objects/cext/PyBufferProcsWrapper.java | 8 +- .../objects/cext/PyBufferProcsWrapperMR.java | 36 +- .../objects/cext/PythonNativeClass.java | 34 +- .../cext/PythonObjectNativeWrapperMR.java | 71 ++-- .../function/BuiltinFunctionBuiltins.java | 4 +- .../GetSetDescriptorTypeBuiltins.java | 9 +- .../objects/object/ObjectBuiltins.java | 11 +- .../builtins/objects/object/PythonObject.java | 13 +- .../objects/superobject/SuperBuiltins.java | 39 +- .../objects/superobject/SuperObject.java | 12 +- .../objects/type/AbstractPythonClass.java | 6 + .../builtins/objects/type/MROMergeState.java | 8 +- .../objects/type/ManagedPythonClass.java | 324 +++++++++++++++++ .../objects/type/PythonBuiltinClass.java | 7 +- .../builtins/objects/type/PythonClass.java | 333 +----------------- .../builtins/objects/type/TypeBuiltins.java | 51 ++- .../builtins/objects/type/TypeNodes.java | 195 ++++++++-- .../oracle/graal/python/nodes/PGuards.java | 4 +- .../graal/python/nodes/PNodeWithContext.java | 11 +- .../attributes/LookupAttributeInMRONode.java | 70 ++-- .../nodes/attributes/ObjectAttributeNode.java | 4 +- .../ReadAttributeFromDynamicObjectNode.java | 11 +- .../ReadAttributeFromObjectNode.java | 56 ++- .../call/special/LookupAndCallBinaryNode.java | 10 +- .../special/LookupAndCallTernaryNode.java | 10 +- .../nodes/classes/IsFixedSubtypeMRONode.java | 3 +- .../nodes/classes/IsSubtypeMRONode.java | 15 +- .../python/nodes/classes/IsSubtypeNode.java | 9 +- .../control/TopLevelExceptionHandler.java | 4 +- .../python/nodes/object/GetClassNode.java | 87 ++--- .../nodes/object/IsBuiltinClassProfile.java | 4 +- .../python/nodes/statement/ExceptNode.java | 11 +- .../python/nodes/statement/RaiseNode.java | 6 +- .../python/nodes/statement/WithNode.java | 4 +- .../python/nodes/subscript/SetItemNode.java | 6 +- .../interop/PythonMessageResolution.java | 19 +- .../runtime/object/PythonObjectFactory.java | 9 +- 46 files changed, 1096 insertions(+), 671 deletions(-) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/AbstractPythonClass.java create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java diff --git a/graalpython/com.oracle.graal.python.cext/src/capi.c b/graalpython/com.oracle.graal.python.cext/src/capi.c index e49dbe0796..6d04cd42b9 100644 --- a/graalpython/com.oracle.graal.python.cext/src/capi.c +++ b/graalpython/com.oracle.graal.python.cext/src/capi.c @@ -280,6 +280,11 @@ void* get_ob_type(PyObject* obj) { } } +/** to be used from Java code only; reads native 'tp_dict' field */ +void* get_tp_dict(PyTypeObject* obj) { + return obj->tp_dict; +} + /** to be used from Java code only; returns the type ID for a byte array */ polyglot_typeid get_byte_array_typeid(uint64_t len) { return polyglot_array_typeid(polyglot_i8_typeid(), len); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java index 7126f72bd7..4596baf03d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java @@ -153,7 +153,6 @@ import com.oracle.graal.python.builtins.objects.traceback.TracebackBuiltins; import com.oracle.graal.python.builtins.objects.tuple.TupleBuiltins; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeBuiltins; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.builtins.objects.zipimporter.ZipImporterBuiltins; @@ -482,13 +481,13 @@ public void exportCInterface(PythonContext context) { // export all exception classes for the C API for (PythonBuiltinClassType errorType : PythonBuiltinClassType.EXCEPTIONS) { - PythonClass errorClass = lookupType(errorType); + PythonBuiltinClass errorClass = lookupType(errorType); env.exportSymbol("python_" + GetNameNode.doSlowPath(errorClass), errorClass); } } } - private PythonClass initializeBuiltinClass(PythonBuiltinClassType type) { + private PythonBuiltinClass initializeBuiltinClass(PythonBuiltinClassType type) { int index = type.ordinal(); if (builtinTypes[index] == null) { if (type.getBase() == type) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java index 0a444e7bc5..fc9d59806a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java @@ -59,6 +59,7 @@ import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView; import com.oracle.graal.python.builtins.objects.module.PythonModule; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; @@ -95,8 +96,10 @@ protected List> getNodeFa public void initialize(PythonCore core) { super.initialize(core); String pre = "binascii."; - builtinConstants.put(ERROR, core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, pre + ERROR, new PythonClass[]{core.lookupType(PythonBuiltinClassType.ValueError)})); - builtinConstants.put(INCOMPLETE, core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, pre + INCOMPLETE, new PythonClass[]{core.lookupType(PythonBuiltinClassType.Exception)})); + AbstractPythonClass[] errorBases = new AbstractPythonClass[]{core.lookupType(PythonBuiltinClassType.ValueError)}; + builtinConstants.put(ERROR, core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, pre + ERROR, errorBases)); + AbstractPythonClass[] incompleteBases = new AbstractPythonClass[]{core.lookupType(PythonBuiltinClassType.Exception)}; + builtinConstants.put(INCOMPLETE, core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, pre + INCOMPLETE, incompleteBases)); } @Builtin(name = "a2b_base64", fixedNumOfPositionalArgs = 1) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index 194b08e297..e838f32b84 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -114,6 +114,7 @@ import com.oracle.graal.python.builtins.objects.set.SetNodes; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.tuple.PTuple; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; @@ -1367,8 +1368,8 @@ Object doNativeObjectIndirect(PythonClass self, Object[] varargs, PKeyword[] kwa return callNativeGenericNewNode(nativeBaseClass, varargs, kwargs); } - private static PythonNativeClass findFirstNativeBaseClass(PythonClass[] methodResolutionOrder) { - for (PythonClass cls : methodResolutionOrder) { + private static PythonNativeClass findFirstNativeBaseClass(AbstractPythonClass[] methodResolutionOrder) { + for (AbstractPythonClass cls : methodResolutionOrder) { if (cls instanceof PythonNativeClass) { return (PythonNativeClass) cls; } @@ -1757,7 +1758,7 @@ public Object type(VirtualFrame frame, PythonClass cls, String name, PTuple base @Cached("create()") CallDispatchNode callNewFuncNode, @Cached("create()") CreateArgumentsNode createArgs) { // Determine the proper metatype to deal with this - PythonClass metaclass = calculate_metaclass(cls, bases, getMetaclassNode); + AbstractPythonClass metaclass = calculate_metaclass(cls, bases, getMetaclassNode); if (metaclass != cls) { Object newFunc = getNewFuncNode.execute(metaclass); if (newFunc instanceof PBuiltinFunction && (((PBuiltinFunction) newFunc).getFunctionRootNode() == getRootNode())) { @@ -1805,16 +1806,16 @@ private String getModuleNameFromGlobals(PythonObject globals) { } @TruffleBoundary - private Object typeMetaclass(String name, PTuple bases, PDict namespace, PythonClass metaclass) { + private Object typeMetaclass(String name, PTuple bases, PDict namespace, AbstractPythonClass metaclass) { Object[] array = bases.getArray(); - PythonClass[] basesArray; + AbstractPythonClass[] basesArray; if (array.length == 0) { // Adjust for empty tuple bases - basesArray = new PythonClass[]{getCore().lookupType(PythonBuiltinClassType.PythonObject)}; + basesArray = new AbstractPythonClass[]{getCore().lookupType(PythonBuiltinClassType.PythonObject)}; } else { - basesArray = new PythonClass[array.length]; + basesArray = new AbstractPythonClass[array.length]; for (int i = 0; i < array.length; i++) { // TODO: deal with non-class bases if (!(array[i] instanceof PythonClass)) { @@ -2056,7 +2057,7 @@ private boolean addDictIfNative(PythonClass pythonClass) { return addedNewDict; } - private PythonClass[] getMro(PythonClass pythonClass) { + private AbstractPythonClass[] getMro(PythonClass pythonClass) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -2064,10 +2065,10 @@ private PythonClass[] getMro(PythonClass pythonClass) { return getMroNode.execute(pythonClass); } - private PythonClass calculate_metaclass(PythonClass cls, PTuple bases, GetClassNode getMetaclassNode) { - PythonClass winner = cls; + private AbstractPythonClass calculate_metaclass(PythonClass cls, PTuple bases, GetClassNode getMetaclassNode) { + AbstractPythonClass winner = cls; for (Object base : bases.getArray()) { - PythonClass typ = getMetaclassNode.execute(base); + AbstractPythonClass typ = getMetaclassNode.execute(base); if (isSubType(winner, typ)) { continue; } else if (isSubType(typ, winner)) { @@ -2080,7 +2081,7 @@ private PythonClass calculate_metaclass(PythonClass cls, PTuple bases, GetClassN return winner; } - private boolean isSubType(PythonClass subclass, PythonClass superclass) { + private boolean isSubType(AbstractPythonClass subclass, AbstractPythonClass superclass) { if (isSubtypeNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); isSubtypeNode = insert(IsSubtypeNode.create()); @@ -2176,7 +2177,7 @@ public PythonModule module(PythonClass cls, String name, String path) { @Builtin(name = "NotImplementedType", fixedNumOfPositionalArgs = 1, constructsClass = PythonBuiltinClassType.PNotImplemented, isPublic = false) @GenerateNodeFactory public abstract static class NotImplementedTypeNode extends PythonBuiltinNode { - protected PythonClass getNotImplementedClass() { + protected PythonBuiltinClass getNotImplementedClass() { return getCore().lookupType(PythonBuiltinClassType.PNotImplemented); } @@ -2203,7 +2204,7 @@ public PEllipsis call(Object cls, Object args, Object kwds) { @Builtin(name = "NoneType", fixedNumOfPositionalArgs = 1, constructsClass = PythonBuiltinClassType.PNone, isPublic = false) @GenerateNodeFactory public abstract static class NoneTypeNode extends PythonBuiltinNode { - protected PythonClass getNoneClass() { + protected PythonBuiltinClass getNoneClass() { return getCore().lookupType(PythonBuiltinClassType.PNone); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 049794bde4..d74742725e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -114,8 +114,10 @@ import com.oracle.graal.python.builtins.objects.set.PFrozenSet; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.tuple.PTuple; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeBuiltins; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.GraalPythonTranslationErrorNode; import com.oracle.graal.python.nodes.PClosureRootNode; @@ -1037,9 +1039,10 @@ private boolean isInstanceCheckInternal(Object instance, Object cls) { @Specialization public boolean isInstance(Object instance, PythonClass cls, + @Cached("create()") TypeNodes.IsSameTypeNode isSameTypeNode, @Cached("create()") IsSubtypeNode isSubtypeNode) { - PythonClass instanceClass = getClassNode.execute(instance); - return instanceClass == cls || isSubtypeNode.execute(instanceClass, cls) || isInstanceCheckInternal(instance, cls); + AbstractPythonClass instanceClass = getClassNode.execute(instance); + return isSameTypeNode.execute(instanceClass, cls) || isSubtypeNode.execute(instanceClass, cls) || isInstanceCheckInternal(instance, cls); } @Specialization(guards = "getLength(clsTuple) == cachedLen", limit = "getVariableArgumentInlineCacheLimit()") diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index f08e02363b..65df3c2f74 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -129,6 +129,7 @@ import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; @@ -212,7 +213,7 @@ protected List> getNodeFa public void initialize(PythonCore core) { super.initialize(core); PythonClass errorHandlerClass = core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, "CErrorHandler", - new PythonClass[]{core.lookupType(PythonBuiltinClassType.PythonObject)}); + new AbstractPythonClass[]{core.lookupType(PythonBuiltinClassType.PythonObject)}); builtinConstants.put("CErrorHandler", errorHandlerClass); builtinConstants.put(ERROR_HANDLER, core.factory().createPythonObject(errorHandlerClass)); builtinConstants.put(NATIVE_NULL, new PythonNativeNull()); @@ -519,17 +520,6 @@ Object op5(Object a, Object b, @SuppressWarnings("unused") int op, } } - @Builtin(name = "PyType_Dict", fixedNumOfPositionalArgs = 1) - @GenerateNodeFactory - abstract static class PyType_DictNode extends PythonBuiltinNode { - @Specialization - PHashingCollection getDict(PythonNativeClass object) { - PHashingCollection dict = object.getDict(); - assert dict instanceof PDict; - return dict; - } - } - @Builtin(name = "PyTruffle_SetAttr", fixedNumOfPositionalArgs = 3) @GenerateNodeFactory abstract static class PyObject_Setattr extends PythonBuiltinNode { @@ -684,7 +674,7 @@ private Object getLongItem(PDict nativeMembers, String key) { return (long) item; } - private PythonClass[] getMro(PythonClass clazz) { + private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -1483,13 +1473,13 @@ abstract static class PyTruffle_GetTpFlags extends NativeBuiltin { @Specialization long doPythonObject(PythonNativeWrapper nativeWrapper) { - PythonClass pclass = getClassNode().execute(nativeWrapper.getDelegate()); + AbstractPythonClass pclass = getClassNode().execute(nativeWrapper.getDelegate()); return getTypeFlagsNode().execute(pclass); } @Specialization long doPythonObject(PythonAbstractObject object) { - PythonClass pclass = getClassNode().execute(object); + AbstractPythonClass pclass = getClassNode().execute(object); return getTypeFlagsNode().execute(pclass); } @@ -1601,29 +1591,6 @@ Object doUnpackLongOvf(Object start, Object stop, Object step, Object lengthObj, } } - @Builtin(name = "PyTruffle_Add_Subclass", fixedNumOfPositionalArgs = 3) - @GenerateNodeFactory - abstract static class PyTruffle_Add_Subclass extends NativeBuiltin { - - @Specialization - int doManagedSubclass(PythonClassNativeWrapper base, @SuppressWarnings("unused") Object key, PythonClassNativeWrapper value, - @Cached("create()") TypeNodes.GetSubclassesNode getSubclassesNode) { - Set subclasses = getSubclassesNode.execute(base.getPythonObject()); - addToSet(subclasses, (PythonClass) value.getPythonObject()); - return 0; - } - - @Fallback - int doGeneric(@SuppressWarnings("unused") Object base, @SuppressWarnings("unused") Object key, @SuppressWarnings("unused") Object value) { - return raiseNative(-1, SystemError, "Builtin can only handle managed base class."); - } - - @TruffleBoundary - private static void addToSet(Set subclasses, PythonClass value) { - subclasses.add(value); - } - } - @Builtin(name = "PyTruffle_GetSetDescriptor", keywordArguments = {"fget", "fset", "name", "owner"}) @GenerateNodeFactory public abstract static class GetSetDescriptorNode extends PythonBuiltinNode { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index 20a36d86f4..fc9527f12b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -42,6 +42,7 @@ import java.util.List; +import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.Builtin; import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.modules.BuiltinFunctions.GetAttrNode; @@ -72,6 +73,8 @@ import com.oracle.graal.python.builtins.objects.function.PKeyword; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.str.PString; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; @@ -260,6 +263,16 @@ protected TruffleObject importCAPISymbol(String name) { } } + protected static TruffleObject importCAPISymbolSlowPath(String name) { + TruffleObject capiLibrary = (TruffleObject) PythonLanguage.getContextRef().get().getCapiLibrary(); + try { + return (TruffleObject) ForeignAccess.sendRead(Message.READ.createNode(), capiLibrary, name); + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + CompilerDirectives.transferToInterpreter(); + throw e.raise(); + } + } + } public abstract static class ToSulongNode extends CExtBaseNode { @@ -301,7 +314,7 @@ Object doDouble(double d) { @Specialization Object doNativeClass(PythonNativeClass nativeClass) { - return nativeClass.object; + return nativeClass.getPtr(); } @Specialization @@ -314,15 +327,15 @@ Object doNativeNull(PythonNativeNull object) { return object.getPtr(); } - @Specialization(guards = {"!isNativeClass(object)", "object == cachedObject"}, limit = "3") - Object doPythonClass(@SuppressWarnings("unused") PythonClass object, - @SuppressWarnings("unused") @Cached("object") PythonClass cachedObject, + @Specialization(guards = "object == cachedObject", limit = "3") + Object doPythonClass(@SuppressWarnings("unused") ManagedPythonClass object, + @SuppressWarnings("unused") @Cached("object") ManagedPythonClass cachedObject, @Cached("wrapNativeClass(object)") PythonClassNativeWrapper wrapper) { return wrapper; } - @Specialization(replaces = "doPythonClass", guards = {"!isNativeClass(object)"}) - Object doPythonClassUncached(PythonClass object, + @Specialization(replaces = "doPythonClass") + Object doPythonClassUncached(ManagedPythonClass object, @Cached("create()") TypeNodes.GetNameNode getNameNode) { return PythonClassNativeWrapper.wrap(object, getNameNode.execute(object)); } @@ -353,25 +366,49 @@ Object run(Object obj) { return obj; } - protected static boolean isNativeClass(PythonAbstractObject o) { - return o instanceof PythonNativeClass; - } - protected static boolean isPythonClass(PythonAbstractObject o) { - return o instanceof PythonClass; + return o instanceof AbstractPythonClass; } protected static boolean isNativeObject(PythonAbstractObject o) { return o instanceof PythonNativeObject; } - protected static PythonClassNativeWrapper wrapNativeClass(PythonClass object) { + protected static PythonClassNativeWrapper wrapNativeClass(ManagedPythonClass object) { return PythonClassNativeWrapper.wrap(object, GetNameNode.doSlowPath(object)); } public static ToSulongNode create() { return ToSulongNodeGen.create(); } + + @TruffleBoundary + public static Object doSlowPath(Object o) { + if (o instanceof String) { + PythonObjectNativeWrapper.wrapSlowPath(PythonLanguage.getCore().factory().createString((String) o)); + } else if (o instanceof Integer) { + return PrimitiveNativeWrapper.createInt((Integer) o); + } else if (o instanceof Long) { + return PrimitiveNativeWrapper.createLong((Long) o); + } else if (o instanceof Double) { + return PrimitiveNativeWrapper.createDouble((Double) o); + } else if (o instanceof PythonNativeClass) { + return ((PythonNativeClass) o).getPtr(); + } else if (o instanceof PythonNativeObject) { + return ((PythonNativeObject) o).object; + } else if (o instanceof PythonNativeNull) { + return ((PythonNativeNull) o).getPtr(); + } else if (o instanceof ManagedPythonClass) { + return wrapNativeClass((ManagedPythonClass) o); + } else if (o instanceof PythonAbstractObject) { + assert !(o instanceof AbstractPythonClass); + return PythonObjectNativeWrapper.wrapSlowPath((PythonAbstractObject) o); + } else if (PGuards.isForeignObject(o)) { + return TruffleObjectNativeWrapper.wrap((TruffleObject) o); + } + assert o != null : "Java 'null' cannot be a Sulong value"; + return o; + } } /** @@ -492,9 +529,11 @@ public static Object doSlowPath(Object object) { if (object instanceof PythonNativeWrapper) { return ((PythonNativeWrapper) object).getDelegate(); } else if (IsBuiltinClassProfile.profileClassSlowPath(GetClassNode.getItSlowPath(object), PythonBuiltinClassType.TruffleObject)) { - throw new AssertionError("Unsupported slow path operation: converting 'to_java(" + object + ")"); + return PythonLanguage.getCore().factory().createNativeObjectWrapper((TruffleObject) object); + } else if (object instanceof Number || object instanceof Boolean) { + return object; } - return object; + throw PythonLanguage.getCore().raise(PythonErrorType.SystemError, "invalid object from native: %s", object); } private MaterializeDelegateNode getMaterializeNode() { @@ -700,6 +739,19 @@ public static ToJavaNode create() { public static ToJavaNode create(boolean forcePointer) { return ToJavaNodeGen.create(forcePointer); } + + @TruffleBoundary + public static Object doSlowPath(Object value, boolean forcePointer) { + if (value instanceof PythonAbstractObject || value instanceof String || value instanceof Boolean || value instanceof Integer || value instanceof Byte) { + return value; + } else if (value instanceof Long) { + String funName = forcePointer ? NativeCAPISymbols.FUN_NATIVE_LONG_TO_JAVA : NativeCAPISymbols.FUN_NATIVE_POINTER_TO_JAVA; + return AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(funName, value)); + } else if (value instanceof PythonNativeWrapper) { + return AsPythonObjectNode.doSlowPath(value); + } + return AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_NATIVE_TO_JAVA, value)); + } } public abstract static class AsCharPointer extends CExtBaseNode { @@ -890,6 +942,10 @@ private boolean executeCFunction(Object a, Object b) { } } + public boolean execute(PythonNativeClass a, PythonNativeClass b) { + return executeCFunction(a.getPtr(), b.getPtr()); + } + public boolean execute(PythonNativeObject a, PythonNativeObject b) { return executeCFunction(a.object, b.object); } @@ -1322,6 +1378,15 @@ public PCallCapiFunction(String name) { this.name = name; } + @TruffleBoundary + public static Object doSlowPath(String funNativeToJava, Object... args) { + try { + return ForeignAccess.sendExecute(Message.EXECUTE.createNode(), importCAPISymbolSlowPath(funNativeToJava), args); + } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) { + throw e.raise(); + } + } + public Object call(Object... args) { try { return ForeignAccess.sendExecute(getCallNode(), getFunction(), args); @@ -1510,12 +1575,17 @@ public static IsPointerNode create() { } } - public static class GetObjectDictNode extends CExtBaseNode { + public abstract static class GetNativeDictNode extends CExtBaseNode { + public abstract Object execute(Object obj); + } + + public static class GetObjectDictNode extends GetNativeDictNode { @CompilationFinal private TruffleObject func; @Child private Node exec; @Child private ToSulongNode toSulong; @Child private ToJavaNode toJava; + @Override public Object execute(Object self) { if (func == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -1532,8 +1602,45 @@ public Object execute(Object self) { } } + @TruffleBoundary + public static Object doSlowPath(Object self) { + try { + TruffleObject func = importCAPISymbolSlowPath(NativeCAPISymbols.FUN_PY_OBJECT_GENERIC_GET_DICT); + return ToJavaNode.doSlowPath(ForeignAccess.sendExecute(Message.EXECUTE.createNode(), func, ToSulongNode.doSlowPath(self)), true); + } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) { + CompilerDirectives.transferToInterpreter(); + throw e.raise(); + } + } + public static GetObjectDictNode create() { return new GetObjectDictNode(); } } + + public static class GetTypeDictNode extends GetNativeDictNode { + @Child private ToSulongNode toSulong; + @Child private ToJavaNode toJava; + @Child private PCallCapiFunction callGetTpDictNode; + + @Override + public Object execute(Object self) { + if (callGetTpDictNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + callGetTpDictNode = PCallCapiFunction.create(NativeCAPISymbols.FUN_PY_OBJECT_GENERIC_GET_DICT); + toSulong = insert(ToSulongNode.create()); + toJava = insert(ToJavaNode.create()); + } + return toJava.execute(callGetTpDictNode.call(toSulong.execute(self))); + } + + @TruffleBoundary + public static Object doSlowPath(Object self) { + return ToJavaNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_PY_OBJECT_GENERIC_GET_DICT, ToSulongNode.doSlowPath(self)), true); + } + + public static GetTypeDictNode create() { + return new GetTypeDictNode(); + } + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java index 07e520183f..01d5dae606 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java @@ -46,6 +46,7 @@ import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.str.PString; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; @@ -155,6 +156,16 @@ public static DynamicObjectNativeWrapper wrap(PythonAbstractObject obj, Conditio return nativeWrapper; } + public static DynamicObjectNativeWrapper wrapSlowPath(PythonAbstractObject obj) { + // important: native wrappers are cached + DynamicObjectNativeWrapper nativeWrapper = obj.getNativeWrapper(); + if (nativeWrapper == null) { + nativeWrapper = new PythonObjectNativeWrapper(obj); + obj.setNativeWrapper(nativeWrapper); + } + return nativeWrapper; + } + @Override public String toString() { CompilerAsserts.neverPartOfCompilation(); @@ -275,7 +286,7 @@ public static class PythonClassNativeWrapper extends PythonObjectNativeWrapper { private Object getBufferProc; private Object releaseBufferProc; - public PythonClassNativeWrapper(PythonClass object, String typeName) { + public PythonClassNativeWrapper(ManagedPythonClass object, String typeName) { super(object); this.nameWrapper = new CStringWrapper(typeName); } @@ -300,7 +311,7 @@ public void setReleaseBufferProc(Object releaseBufferProc) { this.releaseBufferProc = releaseBufferProc; } - public static PythonClassNativeWrapper wrap(PythonClass obj, String typeName) { + public static PythonClassNativeWrapper wrap(ManagedPythonClass obj, String typeName) { // important: native wrappers are cached PythonClassNativeWrapper nativeWrapper = obj.getNativeWrapper(); if (nativeWrapper == null) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java index 90049a6f99..5c99887c0e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java @@ -55,6 +55,7 @@ import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.exception.PBaseException; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; @@ -134,7 +135,7 @@ abstract static class ThreadStateReadNode extends PNodeWithContext { public abstract Object execute(Object key); @Specialization(guards = "eq(key, CUR_EXC_TYPE)") - PythonClass doCurExcType(@SuppressWarnings("unused") String key) { + AbstractPythonClass doCurExcType(@SuppressWarnings("unused") String key) { PythonContext context = getContext(); PException currentException = context.getCurrentException(); if (currentException != null) { @@ -167,7 +168,7 @@ PTraceback doCurExcTraceback(@SuppressWarnings("unused") String key) { } @Specialization(guards = "eq(key, EXC_TYPE)") - PythonClass doExcType(@SuppressWarnings("unused") String key) { + AbstractPythonClass doExcType(@SuppressWarnings("unused") String key) { PythonContext context = getContext(); PException currentException = context.getCaughtException(); if (currentException != null) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java index 1b86968c6a..510a2c528b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java @@ -41,13 +41,13 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonNativeWrapper; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.TruffleObject; public class PyBufferProcsWrapper extends PythonNativeWrapper { - public PyBufferProcsWrapper(PythonClass delegate) { + public PyBufferProcsWrapper(AbstractPythonClass delegate) { super(delegate); } @@ -60,7 +60,7 @@ public ForeignAccess getForeignAccess() { return PyBufferProcsWrapperMRForeign.ACCESS; } - public PythonClass getPythonClass() { - return (PythonClass) getDelegate(); + public AbstractPythonClass getPythonClass() { + return (AbstractPythonClass) getDelegate(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java index df7090983d..0e98422442 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java @@ -43,7 +43,12 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToSulongNode; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper; +import com.oracle.graal.python.builtins.objects.cext.PyBufferProcsWrapperMRFactory.GetBufferProcsNodeGen; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.MessageResolution; import com.oracle.truffle.api.interop.Resolve; import com.oracle.truffle.api.interop.UnknownIdentifierException; @@ -54,12 +59,30 @@ public class PyBufferProcsWrapperMR { @Resolve(message = "READ") abstract static class ReadNode extends Node { - @Child private ToSulongNode toSulongNode; + @Child private GetBufferProcsNode getBufferProcsNode; public Object access(PyBufferProcsWrapper object, String key) { + if (getBufferProcsNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getBufferProcsNode = insert(GetBufferProcsNodeGen.create()); + } + return getBufferProcsNode.execute(object.getPythonClass(), key); + } + } + + abstract static class GetBufferProcsNode extends PNodeWithContext { + @Child private ToSulongNode toSulongNode; + + public abstract Object execute(AbstractPythonClass clazz, String key); + + @Specialization + Object doManagedClass(ManagedPythonClass clazz, String key) { // translate key to attribute name - PythonClassNativeWrapper nativeWrapper = object.getPythonClass().getNativeWrapper(); - // TODO handle case if nativeWrapper does not exist yet + PythonClassNativeWrapper nativeWrapper = clazz.getNativeWrapper(); + + // Since this MR is directly called from native, there must be a native wrapper. + assert nativeWrapper != null; + Object result; switch (key) { case "bf_getbuffer": @@ -78,6 +101,12 @@ public Object access(PyBufferProcsWrapper object, String key) { return result == null ? getToSulongNode().execute(PNone.NO_VALUE) : result; } + @Specialization + Object doNativeClass(@SuppressWarnings("unused") PythonNativeClass clazz, @SuppressWarnings("unused") String key) { + CompilerDirectives.transferToInterpreter(); + throw new IllegalStateException("native member access to native class via interop"); + } + private ToSulongNode getToSulongNode() { if (toSulongNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -85,5 +114,6 @@ private ToSulongNode getToSulongNode() { } return toSulongNode; } + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java index d70166ac2a..f332bf9189 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java @@ -40,7 +40,10 @@ */ package com.oracle.graal.python.builtins.objects.cext; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.PythonAbstractObject; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.object.Shape; /** * A simple wrapper around types objects created through the Python C API that can be cast to @@ -48,11 +51,30 @@ * types are assumed to be mutated afterwards, so accessing the struct in native mode would work, * but our copy should just never become stale. */ -public class PythonNativeClass extends PythonClass { - public final Object object; +public final class PythonNativeClass extends PythonAbstractObject implements AbstractPythonClass { + public final Object ptr; - public PythonNativeClass(Object obj, PythonClass type, String name, PythonClass... bases) { - super(type, name, type.getInstanceShape(), bases); - object = obj; + public PythonNativeClass(Object ptr) { + this.ptr = ptr; + } + + public Object getPtr() { + return ptr; + } + + public int compareTo(Object o) { + CompilerDirectives.transferToInterpreter(); + throw new UnsupportedOperationException("cannot compare native class to anything else"); + } + + public Shape getInstanceShape() { + CompilerDirectives.transferToInterpreter(); + throw new UnsupportedOperationException("native class does not have a shape"); + } + + public void lookupChanged() { + // TODO invalidate cached native MRO + CompilerDirectives.transferToInterpreter(); + throw new UnsupportedOperationException("not yet implemented"); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index e5fa8ed065..be44e0a63d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -93,7 +93,9 @@ import com.oracle.graal.python.builtins.objects.set.PSet; import com.oracle.graal.python.builtins.objects.slice.PSlice; import com.oracle.graal.python.builtins.objects.str.PString; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; @@ -124,6 +126,7 @@ import com.oracle.graal.python.runtime.interop.PythonMessageResolution; import com.oracle.graal.python.runtime.sequence.PSequence; import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -210,8 +213,6 @@ public static PGetDynamicTypeNode create() { abstract static class GetSulongTypeNode extends PNodeWithContext { - private final ConditionProfile profile = ConditionProfile.createBinaryProfile(); - public abstract Object execute(LazyPythonClass clazz); @Specialization(guards = "clazz == cachedClass", limit = "10") @@ -222,46 +223,66 @@ Object doBuiltinCached(@SuppressWarnings("unused") PythonBuiltinClassType clazz, } @Specialization(replaces = "doBuiltinCached") - Object doBuiltinGeneric(PythonBuiltinClassType clazz) { - return getSulongTypeForBuiltinClass(clazz); + Object doBuiltinGeneric(PythonBuiltinClassType clazz, + @Cached("create()") TypeNodes.GetSulongTypeNode getSulongTypeNode, + @Cached("createBinaryProfile()") ConditionProfile profile, + @Cached("createBinaryProfile()") ConditionProfile hasSulongTypeProfile) { + ManagedPythonClass pythonClass = getPythonClass(clazz, profile); + return doManagedGeneric(pythonClass, getSulongTypeNode, hasSulongTypeProfile); } @Specialization(assumptions = "singleContextAssumption()", guards = "clazz == cachedClass") - Object doGeneric(@SuppressWarnings("unused") PythonClass clazz, - @Cached("clazz") @SuppressWarnings("unused") PythonClass cachedClass, - @Cached("doGeneric(clazz)") Object sulongType) { + Object doManagedCached(@SuppressWarnings("unused") ManagedPythonClass clazz, + @Cached("clazz") @SuppressWarnings("unused") ManagedPythonClass cachedClass, + @Cached("getSulongTypeForClass(cachedClass)") Object sulongType) { return sulongType; } - @Specialization - Object doGeneric(PythonClass clazz) { - return getSulongTypeForClass(clazz); + @Specialization(replaces = "doManagedCached") + Object doManagedGeneric(ManagedPythonClass clazz, + @Cached("create()") TypeNodes.GetSulongTypeNode getSulongTypeNode, + @Cached("createBinaryProfile()") ConditionProfile hasSulongTypeProfile) { + Object sulongType = getSulongTypeNode.execute(clazz); + if (hasSulongTypeProfile.profile(sulongType == null)) { + CompilerDirectives.transferToInterpreter(); + return resolveSulongTypeForClass(clazz); + } + return sulongType; } protected Object getSulongTypeForBuiltinClass(PythonBuiltinClassType clazz) { - PythonClass pythonClass = getPythonClass(clazz, profile); + CompilerAsserts.neverPartOfCompilation(); + AbstractPythonClass pythonClass = getPythonClass(clazz, ConditionProfile.createBinaryProfile()); return getSulongTypeForClass(pythonClass); } - private static Object getSulongTypeForClass(PythonClass klass) { - Object sulongType = klass.getSulongType(); + protected static Object getSulongTypeForClass(AbstractPythonClass clazz) { + CompilerAsserts.neverPartOfCompilation(); + Object sulongType = TypeNodes.GetSulongTypeNode.getSlowPath(clazz); if (sulongType == null) { CompilerDirectives.transferToInterpreter(); - sulongType = findBuiltinClass(klass); - if (sulongType == null) { - throw new IllegalStateException("sulong type for " + GetNameNode.doSlowPath(klass) + " was not registered"); - } + return resolveSulongTypeForClass(clazz); + } + return sulongType; + } + + /** resolves the Sulong type */ + private static Object resolveSulongTypeForClass(AbstractPythonClass klass) { + Object sulongType = findBuiltinClass(klass); + if (sulongType == null) { + throw new IllegalStateException("sulong type for " + GetNameNode.doSlowPath(klass) + " was not registered"); } return sulongType; } - private static Object findBuiltinClass(PythonClass klass) { - PythonClass[] mro = GetMroNode.doSlowPath(klass); + /** iterates over MRO and looks for the first builtin type with an existing Sulong type */ + private static Object findBuiltinClass(AbstractPythonClass klass) { + AbstractPythonClass[] mro = GetMroNode.doSlowPath(klass); Object sulongType = null; - for (PythonClass superClass : mro) { - sulongType = superClass.getSulongType(); + for (AbstractPythonClass superClass : mro) { + sulongType = TypeNodes.GetSulongTypeNode.getSlowPath(superClass); if (sulongType != null) { - klass.setSulongType(sulongType); + TypeNodes.GetSulongTypeNode.setSlowPath(klass, sulongType); break; } } @@ -492,7 +513,7 @@ Object doTpItemsize(PythonClass object, @SuppressWarnings("unused") String key, } @Specialization(guards = "eq(TP_DICTOFFSET, key)") - Object doTpDictoffset(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create()") CastToIndexNode castToIntNode, @Cached("create(__DICTOFFSET__)") LookupAttributeInMRONode getAttrNode) { // TODO properly implement 'tp_dictoffset' for builtin classes @@ -797,7 +818,7 @@ private int sizeofWchar() { return (int) sizeofWcharNode.execute(); } - private PythonClass getClass(Object obj) { + private AbstractPythonClass getClass(Object obj) { if (getClassNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getClassNode = insert(GetClassNode.create()); @@ -921,7 +942,7 @@ Object doTpDict(PythonClass object, @SuppressWarnings("unused") String key, Obje } @Specialization(guards = "eq(TP_DICTOFFSET, key)") - Object doTpDictoffset(PythonClass object, @SuppressWarnings("unused") String key, Object value, + Object doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") String key, Object value, @Cached("create()") CastToIntegerFromIntNode castToIntNode, @Cached("create(__SETATTR__)") LookupAndCallTernaryNode call) { // TODO properly implement 'tp_dictoffset' for builtin classes diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java index f3bf1500a0..4bb66e9173 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java @@ -34,7 +34,7 @@ import com.oracle.graal.python.builtins.CoreFunctions; import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.PythonBuiltins; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; @@ -85,7 +85,7 @@ Object objclassMissing(@SuppressWarnings("unused") PBuiltinFunction self) { @Specialization(guards = "self.getEnclosingType() != null") @TruffleBoundary - PythonClass objclass(PBuiltinFunction self, + ManagedPythonClass objclass(PBuiltinFunction self, @Cached("createBinaryProfile()") ConditionProfile profile) { return getPythonClass(self.getEnclosingType(), profile); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java index 163c3d13ca..2f636ed4a8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java @@ -53,6 +53,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.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; @@ -104,7 +105,7 @@ abstract static class GetSetNode extends PythonTernaryBuiltinNode { private final BranchProfile errorBranch = BranchProfile.create(); // https://github.com/python/cpython/blob/e8b19656396381407ad91473af5da8b0d4346e88/Objects/descrobject.c#L70 - protected boolean descr_check(LazyPythonClass descrType, String name, Object obj, PythonClass type) { + protected boolean descr_check(LazyPythonClass descrType, String name, Object obj, AbstractPythonClass type) { if (PGuards.isNone(obj)) { if (!isNoneBuiltinClassProfile.profileClass(type, PythonBuiltinClassType.PNone)) { return true; @@ -112,13 +113,13 @@ protected boolean descr_check(LazyPythonClass descrType, String name, Object obj } if (isBuiltinProfile.profile(descrType instanceof PythonBuiltinClassType)) { PythonBuiltinClassType builtinClassType = (PythonBuiltinClassType) descrType; - for (PythonClass o : getMro(type)) { + for (AbstractPythonClass o : getMro(type)) { if (isBuiltinClassProfile.profileClass(o, builtinClassType)) { return false; } } } else { - for (PythonClass o : getMro(type)) { + for (AbstractPythonClass o : getMro(type)) { if (o == descrType) { return false; } @@ -128,7 +129,7 @@ protected boolean descr_check(LazyPythonClass descrType, String name, Object obj throw raise(TypeError, "descriptor '%s' for '%s' objects doesn't apply to '%s' object", name, getTypeName(descrType), getTypeName(type)); } - private PythonClass[] getMro(PythonClass clazz) { + private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java index bb9cb8ceb9..b6db837434 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java @@ -66,6 +66,7 @@ import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction; import com.oracle.graal.python.builtins.objects.function.PKeyword; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; @@ -119,7 +120,7 @@ abstract static class ClassNode extends PythonBinaryBuiltinNode { private static final String ERROR_MESSAGE = "__class__ assignment only supported for heap types or ModuleType subclasses"; @Specialization(guards = "isNoValue(value)") - PythonClass getClass(Object self, @SuppressWarnings("unused") PNone value, + AbstractPythonClass getClass(Object self, @SuppressWarnings("unused") PNone value, @Cached("create()") GetClassNode getClass) { return getClass.execute(self); } @@ -135,7 +136,7 @@ PythonClass setClass(@SuppressWarnings("unused") Object self, @SuppressWarnings( } @Specialization - PNone setClass(PythonObject self, PythonClass value, + PNone setClass(PythonObject self, AbstractPythonClass value, @Cached("create()") BranchProfile errorValueBranch, @Cached("create()") BranchProfile errorSelfBranch, @Cached("create()") BranchProfile errorSlotsBranch, @@ -299,7 +300,7 @@ String repr(Object self, if (self == PNone.NONE) { return "None"; } - PythonClass type = getClass.execute(self); + AbstractPythonClass type = getClass.execute(self); Object moduleName = readModuleNode.execute(type, __MODULE__); Object qualName = readQualNameNode.execute(type, __QUALNAME__); if (moduleName != PNone.NO_VALUE && !moduleName.equals(getCore().getBuiltins().getModuleName())) { @@ -489,7 +490,7 @@ protected PNone doIt(Object object, Object key, Object value, LazyPythonClass type = getObjectClassNode.execute(object); Object descr = getExisting.execute(type, key); if (descr != PNone.NO_VALUE) { - PythonClass dataDescClass = getDataClassNode.execute(descr); + AbstractPythonClass dataDescClass = getDataClassNode.execute(descr); Object set = lookupSetNode.execute(dataDescClass); if (PGuards.isCallable(set)) { callSetNode.execute(set, descr, object, value); @@ -522,7 +523,7 @@ protected PNone doIt(Object object, Object key, LazyPythonClass type = getObjectClassNode.execute(object); Object descr = getExisting.execute(type, key); if (descr != PNone.NO_VALUE) { - PythonClass dataDescClass = getDataClassNode.execute(descr); + AbstractPythonClass dataDescClass = getDataClassNode.execute(descr); Object set = lookupDeleteNode.execute(dataDescClass); if (PGuards.isCallable(set)) { callSetNode.executeObject(set, descr, object); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java index a4675978f4..be4ecd733e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java @@ -33,7 +33,9 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PythonAbstractObject; import com.oracle.graal.python.builtins.objects.common.PHashingCollection; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; @@ -73,7 +75,7 @@ public PythonObject(LazyPythonClass pythonClass, Shape instanceShape) { storage = instanceShape.newInstance(); } - public final PythonClass getPythonClass() { + public final AbstractPythonClass getPythonClass() { CompilerAsserts.neverPartOfCompilation(); assert pythonClass != null; if (pythonClass instanceof PythonClass) { @@ -83,7 +85,7 @@ public final PythonClass getPythonClass() { } } - public final void setLazyPythonClass(PythonClass cls) { + public final void setLazyPythonClass(AbstractPythonClass cls) { pythonClass = cls; classStable.invalidate(); } @@ -154,11 +156,10 @@ public List getAttributeNames() { return keyList; } - public final PythonClass asPythonClass() { - if (this instanceof PythonClass) { - return (PythonClass) this; + public final AbstractPythonClass asPythonClass() { + if (this instanceof ManagedPythonClass) { + return (ManagedPythonClass) this; } - return getPythonClass(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java index 25797c96ca..b53a6b8e2b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java @@ -59,8 +59,10 @@ import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetObjectTypeNodeGen; import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetTypeNodeGen; import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.SuperInitNodeFactory; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.argument.ReadIndexedArgumentNode; @@ -118,17 +120,17 @@ Object uncached(SuperObject self) { } abstract static class GetObjectTypeNode extends Node { - abstract PythonClass execute(SuperObject self); + abstract AbstractPythonClass execute(SuperObject self); @Specialization(guards = "self == cachedSelf", assumptions = "cachedSelf.getNeverReinitializedAssumption()", limit = "1") - PythonClass cached(@SuppressWarnings("unused") SuperObject self, + AbstractPythonClass cached(@SuppressWarnings("unused") SuperObject self, @SuppressWarnings("unused") @Cached("self") SuperObject cachedSelf, - @Cached("self.getObjectType()") PythonClass type) { + @Cached("self.getObjectType()") AbstractPythonClass type) { return type; } @Specialization(replaces = "cached") - PythonClass uncached(SuperObject self) { + AbstractPythonClass uncached(SuperObject self) { return self.getObjectType(); } } @@ -195,7 +197,7 @@ public final Object execute(VirtualFrame frame, Object self, Object[] arguments, @Specialization(guards = {"!isNoValue(cls)", "!isNoValue(obj)"}) PNone init(SuperObject self, Object cls, Object obj) { if (obj != PNone.NONE) { - PythonClass type = supercheck(cls, obj); + AbstractPythonClass type = supercheck(cls, obj); self.init(cls, type, obj); } else { self.init(cls, null, null); @@ -328,7 +330,7 @@ private LookupAndCallBinaryNode getGetAttr() { return getAttrNode; } - private PythonClass supercheck(Object cls, Object object) { + private AbstractPythonClass supercheck(Object cls, Object object) { /* * Check that a super() call makes sense. Return a type object. * @@ -344,9 +346,9 @@ private PythonClass supercheck(Object cls, Object object) { * not a subclass of type, but obj.__class__ is! This will allow using super() with a * proxy for obj. */ - if (object instanceof PythonClass) { + if (object instanceof AbstractPythonClass) { if (getIsSubtype().execute(object, cls)) { - return (PythonClass) object; + return (AbstractPythonClass) object; } } @@ -406,6 +408,7 @@ public abstract static class GetattributeNode extends PythonBinaryBuiltinNode { @Child private CallTernaryMethodNode callGet; @Child private ObjectBuiltins.GetAttributeNode objectGetattributeNode; @Child private GetMroNode getMroNode; + @Child private IsSameTypeNode isSameTypeNode; private Object genericGetAttr(Object object, Object attr) { if (objectGetattributeNode == null) { @@ -417,7 +420,7 @@ private Object genericGetAttr(Object object, Object attr) { @Specialization public Object get(SuperObject self, Object attr) { - PythonClass startType = getObjectType.execute(self); + AbstractPythonClass startType = getObjectType.execute(self); if (startType == null) { return genericGetAttr(self, attr); } @@ -444,12 +447,12 @@ public Object get(SuperObject self, Object attr) { getType = insert(GetTypeNodeGen.create()); } - PythonClass[] mro = getMro(startType); + AbstractPythonClass[] mro = getMro(startType); /* No need to check the last one: it's gonna be skipped anyway. */ int i = 0; int n = mro.length; for (i = 0; i + 1 < n; i++) { - if (getType.execute(self) == mro[i]) { + if (isSameType(getType.execute(self), mro[i])) { break; } } @@ -459,7 +462,7 @@ public Object get(SuperObject self, Object attr) { } for (; i < n; i++) { - PythonClass tmp = mro[i]; + AbstractPythonClass tmp = mro[i]; Object res = readFromDict.execute(tmp, attr); if (res != PNone.NO_VALUE) { Object get = readGet.execute(res); @@ -482,7 +485,15 @@ public Object get(SuperObject self, Object attr) { return genericGetAttr(self, attr); } - private PythonClass[] getMro(PythonClass clazz) { + private boolean isSameType(Object execute, AbstractPythonClass abstractPythonClass) { + if (isSameTypeNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isSameTypeNode = insert(IsSameTypeNode.create()); + } + return isSameTypeNode.execute(execute, abstractPythonClass); + } + + private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -528,7 +539,7 @@ public abstract static class SelfClassNode extends PythonUnaryBuiltinNode { @Specialization Object getClass(SuperObject self) { - PythonClass objectType = getObjectType.execute(self); + AbstractPythonClass objectType = getObjectType.execute(self); if (objectType == null) { return PNone.NONE; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java index 441b50a8bd..fee34815eb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -41,21 +41,21 @@ package com.oracle.graal.python.builtins.objects.superobject; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.Truffle; public class SuperObject extends PythonBuiltinObject { private final Assumption neverReinitialized = Truffle.getRuntime().createAssumption("super object was never reinitialized"); private Object type; - private PythonClass objecttype; + private AbstractPythonClass objecttype; private Object object; - public SuperObject(PythonClass cls) { + public SuperObject(AbstractPythonClass cls) { super(cls); } - public void init(Object newType, PythonClass newObjecttype, Object newObject) { + public void init(Object newType, AbstractPythonClass newObjecttype, Object newObject) { if (this.type != null) { neverReinitialized.invalidate(); } @@ -64,7 +64,7 @@ public void init(Object newType, PythonClass newObjecttype, Object newObject) { this.object = newObject; } - public PythonClass getObjectType() { + public AbstractPythonClass getObjectType() { return objecttype; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/AbstractPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/AbstractPythonClass.java new file mode 100644 index 0000000000..272cab8158 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/AbstractPythonClass.java @@ -0,0 +1,6 @@ +package com.oracle.graal.python.builtins.objects.type; + +public interface AbstractPythonClass extends LazyPythonClass { + + void lookupChanged(); +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java index 5a83153145..b5ed327044 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java @@ -28,7 +28,7 @@ class MROMergeState { /** The mro of the base type we're representing. */ - public PythonClass[] mro; + public AbstractPythonClass[] mro; /** * The index of the next item to be merged from mro, or mro.length if this base has been @@ -40,14 +40,14 @@ public boolean isMerged() { return mro.length == next; } - public PythonClass getCandidate() { + public AbstractPythonClass getCandidate() { return mro[next]; } /** * Marks candidate as merged for this base if it's the next item to be merged. */ - public void noteMerged(PythonClass candidate) { + public void noteMerged(AbstractPythonClass candidate) { if (!isMerged() && getCandidate() == candidate) { next++; } @@ -56,7 +56,7 @@ public void noteMerged(PythonClass candidate) { /** * Returns true if candidate is in the items past this state's next item to be merged. */ - public boolean pastnextContains(PythonClass candidate) { + public boolean pastnextContains(AbstractPythonClass candidate) { for (int i = next + 1; i < mro.length; i++) { if (mro[i] == candidate) { return true; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java new file mode 100644 index 0000000000..385f0a4043 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java @@ -0,0 +1,324 @@ +package com.oracle.graal.python.builtins.objects.type; + +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DOC__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +import com.oracle.graal.python.PythonLanguage; +import com.oracle.graal.python.builtins.objects.PNone; +import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; +import com.oracle.graal.python.builtins.objects.object.PythonObject; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode; +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.object.Shape; +import com.oracle.truffle.api.utilities.CyclicAssumption; + +public abstract class ManagedPythonClass extends PythonObject implements AbstractPythonClass { + + private final String className; + + @CompilationFinal(dimensions = 1) private AbstractPythonClass[] baseClasses; + @CompilationFinal(dimensions = 1) private AbstractPythonClass[] methodResolutionOrder; + + /** + * This assumption will be invalidated whenever the mro changes. + */ + private final CyclicAssumption lookupStableAssumption; + /** + * These assumptions will be invalidated whenever the value of the given slot changes. All + * assumptions will be invalidated if the mro changes. + */ + private final Map> attributesInMROFinalAssumptions = new HashMap<>(); + + private final Set subClasses = Collections.newSetFromMap(new WeakHashMap()); + private final Shape instanceShape; + private final FlagsContainer flags; + + /** {@code true} if the MRO contains a native class. */ + private boolean needsNativeAllocation; + @CompilationFinal private Object sulongType; + + @TruffleBoundary + public ManagedPythonClass(LazyPythonClass typeClass, String name, Shape instanceShape, AbstractPythonClass... baseClasses) { + super(typeClass, PythonLanguage.freshShape() /* do not inherit layout from the TypeClass */); + this.className = name; + + if (baseClasses.length == 1 && baseClasses[0] == null) { + this.baseClasses = new AbstractPythonClass[]{}; + } else { + unsafeSetSuperClass(baseClasses); + } + + this.flags = new FlagsContainer(getSuperClass()); + this.lookupStableAssumption = new CyclicAssumption(className); + + // Compute MRO + computeMethodResolutionOrder(); + + setAttribute(__NAME__, getBaseName(name)); + setAttribute(__QUALNAME__, className); + setAttribute(__DOC__, PNone.NONE); + // provide our instances with a fresh shape tree + this.instanceShape = instanceShape; + } + + private static String getBaseName(String qname) { + int lastDot = qname.lastIndexOf('.'); + if (lastDot != -1) { + return qname.substring(lastDot + 1); + } + return qname; + } + + public Assumption getLookupStableAssumption() { + return lookupStableAssumption.getAssumption(); + } + + public Assumption createAttributeInMROFinalAssumption(String name) { + CompilerAsserts.neverPartOfCompilation(); + List attrAssumptions = attributesInMROFinalAssumptions.getOrDefault(name, null); + if (attrAssumptions == null) { + attrAssumptions = new ArrayList<>(); + attributesInMROFinalAssumptions.put(name, attrAssumptions); + } + + Assumption assumption = Truffle.getRuntime().createAssumption(name.toString()); + attrAssumptions.add(assumption); + return assumption; + } + + public void addAttributeInMROFinalAssumption(String name, Assumption assumption) { + CompilerAsserts.neverPartOfCompilation(); + List attrAssumptions = attributesInMROFinalAssumptions.getOrDefault(name, null); + if (attrAssumptions == null) { + attrAssumptions = new ArrayList<>(); + attributesInMROFinalAssumptions.put(name, attrAssumptions); + } + + attrAssumptions.add(assumption); + } + + @TruffleBoundary + public void invalidateAttributeInMROFinalAssumptions(String name) { + List assumptions = attributesInMROFinalAssumptions.getOrDefault(name, new ArrayList<>()); + if (!assumptions.isEmpty()) { + String message = className + "." + name; + for (Assumption assumption : assumptions) { + assumption.invalidate(message); + } + } + } + + /** + * This method needs to be called if the mro changes. (currently not used) + */ + public void lookupChanged() { + CompilerAsserts.neverPartOfCompilation(); + for (List list : attributesInMROFinalAssumptions.values()) { + for (Assumption assumption : list) { + assumption.invalidate(); + } + } + lookupStableAssumption.invalidate(); + for (AbstractPythonClass subclass : getSubClasses()) { + if (subclass != null) { + subclass.lookupChanged(); + } + } + } + + public Shape getInstanceShape() { + return instanceShape; + } + + AbstractPythonClass getSuperClass() { + return getBaseClasses().length > 0 ? getBaseClasses()[0] : null; + } + + AbstractPythonClass[] getMethodResolutionOrder() { + return methodResolutionOrder; + } + + String getName() { + return className; + } + + private void computeMethodResolutionOrder() { + CompilerAsserts.neverPartOfCompilation(); + + AbstractPythonClass[] currentMRO = null; + + if (getBaseClasses().length == 0) { + currentMRO = new AbstractPythonClass[]{this}; + } else if (getBaseClasses().length == 1) { + AbstractPythonClass[] baseMRO = GetMroNode.doSlowPath(getBaseClasses()[0]); + + if (baseMRO == null) { + currentMRO = new AbstractPythonClass[]{this}; + } else { + currentMRO = new AbstractPythonClass[baseMRO.length + 1]; + System.arraycopy(baseMRO, 0, currentMRO, 1, baseMRO.length); + currentMRO[0] = this; + } + } else { + MROMergeState[] toMerge = new MROMergeState[getBaseClasses().length + 1]; + + for (int i = 0; i < getBaseClasses().length; i++) { + toMerge[i] = new MROMergeState(); + toMerge[i].mro = GetMroNode.doSlowPath(getBaseClasses()[i]); + } + + toMerge[getBaseClasses().length] = new MROMergeState(); + toMerge[getBaseClasses().length].mro = getBaseClasses(); + ArrayList mro = new ArrayList<>(); + mro.add(this); + currentMRO = mergeMROs(toMerge, mro); + } + + for (AbstractPythonClass cls : currentMRO) { + if (cls instanceof PythonNativeClass) { + needsNativeAllocation = true; + break; + } + } + + methodResolutionOrder = currentMRO; + } + + PythonClass[] mergeMROs(MROMergeState[] toMerge, List mro) { + int idx; + scan: for (idx = 0; idx < toMerge.length; idx++) { + if (toMerge[idx].isMerged()) { + continue scan; + } + + AbstractPythonClass candidate = toMerge[idx].getCandidate(); + for (MROMergeState mergee : toMerge) { + if (mergee.pastnextContains(candidate)) { + continue scan; + } + } + + mro.add(candidate); + + for (MROMergeState element : toMerge) { + element.noteMerged(candidate); + } + + // restart scan + idx = -1; + } + + for (MROMergeState mergee : toMerge) { + if (!mergee.isMerged()) { + throw new IllegalStateException(); + } + } + + return mro.toArray(new PythonClass[mro.size()]); + } + + @Override + @TruffleBoundary + public void setAttribute(Object key, Object value) { + if (key instanceof String) { + invalidateAttributeInMROFinalAssumptions((String) key); + } + super.setAttribute(key, value); + } + + /** + * This method supports initialization and solves boot-order problems and should not normally be + * used. + */ + private void unsafeSetSuperClass(AbstractPythonClass... newBaseClasses) { + CompilerAsserts.neverPartOfCompilation(); + // TODO: if this is used outside bootstrapping, it needs to call + // computeMethodResolutionOrder for subclasses. + + assert getBaseClasses() == null || getBaseClasses().length == 0; + this.baseClasses = newBaseClasses; + + for (AbstractPythonClass base : getBaseClasses()) { + if (base != null) { + GetSubclassesNode.doSlowPath(base).add(this); + } + } + computeMethodResolutionOrder(); + } + + final Set getSubClasses() { + return subClasses; + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return String.format("", className); + } + + public AbstractPythonClass[] getBaseClasses() { + return baseClasses; + } + + public void setFlags(long flags) { + this.flags.setValue(flags); + } + + FlagsContainer getFlagsContainer() { + return flags; + } + + /** + * Flags are copied from the initial dominant base class. However, classes may already be + * created before the C API was initialized, i.e., flags were not set. + */ + static final class FlagsContainer { + AbstractPythonClass initialDominantBase; + long flags; + + public FlagsContainer(AbstractPythonClass superClass) { + this.initialDominantBase = superClass; + } + + private void setValue(long flags) { + if (initialDominantBase != null) { + initialDominantBase = null; + } + this.flags = flags; + } + } + + @Override + public PythonClassNativeWrapper getNativeWrapper() { + return (PythonClassNativeWrapper) super.getNativeWrapper(); + } + + public final Object getSulongType() { + return sulongType; + } + + @TruffleBoundary + public final void setSulongType(Object dynamicSulongType) { + this.sulongType = dynamicSulongType; + } + + public boolean needsNativeAllocation() { + return needsNativeAllocation; + } + +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java index b49d9385de..198d81df7e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -35,13 +35,12 @@ /** * A Python built-in class that is immutable. */ -public final class PythonBuiltinClass extends PythonClass { +public final class PythonBuiltinClass extends ManagedPythonClass { private final PythonBuiltinClassType type; - public PythonBuiltinClass(PythonBuiltinClassType builtinClass, PythonClass base) { + public PythonBuiltinClass(PythonBuiltinClassType builtinClass, AbstractPythonClass base) { super(PythonBuiltinClassType.PythonClass, builtinClass.getName(), builtinClass.getInstanceShape(), base); this.type = builtinClass; - } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java index 936cd56c52..5c83752a12 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java @@ -25,342 +25,15 @@ */ package com.oracle.graal.python.builtins.objects.type; -import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DOC__; -import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__; -import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; - -import com.oracle.graal.python.PythonLanguage; -import com.oracle.graal.python.builtins.objects.PNone; -import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; -import com.oracle.graal.python.builtins.objects.object.PythonObject; -import com.oracle.truffle.api.Assumption; -import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.object.Shape; -import com.oracle.truffle.api.utilities.CyclicAssumption; /** * Mutable class. */ -public class PythonClass extends PythonObject implements LazyPythonClass { - - private final String className; - - @CompilationFinal(dimensions = 1) private PythonClass[] baseClasses; - @CompilationFinal(dimensions = 1) private PythonClass[] methodResolutionOrder; - - /** - * This assumption will be invalidated whenever the mro changes. - */ - private final CyclicAssumption lookupStableAssumption; - /** - * These assumptions will be invalidated whenever the value of the given slot changes. All - * assumptions will be invalidated if the mro changes. - */ - private final Map> attributesInMROFinalAssumptions = new HashMap<>(); - - private final Set subClasses = Collections.newSetFromMap(new WeakHashMap()); - private final Shape instanceShape; - private final FlagsContainer flags; +public final class PythonClass extends ManagedPythonClass { - /** {@code true} if the MRO contains a native class. */ - private boolean needsNativeAllocation; - @CompilationFinal private Object sulongType; - - public final boolean isBuiltin() { - return this instanceof PythonBuiltinClass; + public PythonClass(LazyPythonClass typeClass, String name, Shape instanceShape, AbstractPythonClass[] baseClasses) { + super(typeClass, name, instanceShape, baseClasses); } - @TruffleBoundary - public PythonClass(LazyPythonClass typeClass, String name, Shape instanceShape, PythonClass... baseClasses) { - super(typeClass, PythonLanguage.freshShape() /* do not inherit layout from the TypeClass */); - this.className = name; - - if (baseClasses.length == 1 && baseClasses[0] == null) { - this.baseClasses = new PythonClass[]{}; - } else { - unsafeSetSuperClass(baseClasses); - } - - this.flags = new FlagsContainer(getSuperClass()); - this.lookupStableAssumption = new CyclicAssumption(className); - - // Compute MRO - computeMethodResolutionOrder(); - - setAttribute(__NAME__, getBaseName(name)); - setAttribute(__QUALNAME__, className); - setAttribute(__DOC__, PNone.NONE); - // provide our instances with a fresh shape tree - this.instanceShape = instanceShape; - } - - private static String getBaseName(String qname) { - int lastDot = qname.lastIndexOf('.'); - if (lastDot != -1) { - return qname.substring(lastDot + 1); - } - return qname; - } - - public Assumption getLookupStableAssumption() { - return lookupStableAssumption.getAssumption(); - } - - public Assumption createAttributeInMROFinalAssumption(String name) { - CompilerAsserts.neverPartOfCompilation(); - List attrAssumptions = attributesInMROFinalAssumptions.getOrDefault(name, null); - if (attrAssumptions == null) { - attrAssumptions = new ArrayList<>(); - attributesInMROFinalAssumptions.put(name, attrAssumptions); - } - - Assumption assumption = Truffle.getRuntime().createAssumption(name.toString()); - attrAssumptions.add(assumption); - return assumption; - } - - public void addAttributeInMROFinalAssumption(String name, Assumption assumption) { - CompilerAsserts.neverPartOfCompilation(); - List attrAssumptions = attributesInMROFinalAssumptions.getOrDefault(name, null); - if (attrAssumptions == null) { - attrAssumptions = new ArrayList<>(); - attributesInMROFinalAssumptions.put(name, attrAssumptions); - } - - attrAssumptions.add(assumption); - } - - @TruffleBoundary - public void invalidateAttributeInMROFinalAssumptions(String name) { - List assumptions = attributesInMROFinalAssumptions.getOrDefault(name, new ArrayList<>()); - if (!assumptions.isEmpty()) { - String message = className + "." + name; - for (Assumption assumption : assumptions) { - assumption.invalidate(message); - } - } - } - - /** - * This method needs to be called if the mro changes. (currently not used) - */ - public void lookupChanged() { - CompilerAsserts.neverPartOfCompilation(); - for (List list : attributesInMROFinalAssumptions.values()) { - for (Assumption assumption : list) { - assumption.invalidate(); - } - } - lookupStableAssumption.invalidate(); - for (PythonClass subclass : getSubClasses()) { - if (subclass != null) { - subclass.lookupChanged(); - } - } - } - - public Shape getInstanceShape() { - return instanceShape; - } - - PythonClass getSuperClass() { - return getBaseClasses().length > 0 ? getBaseClasses()[0] : null; - } - - PythonClass[] getMethodResolutionOrder() { - return methodResolutionOrder; - } - - String getName() { - return className; - } - - private void computeMethodResolutionOrder() { - PythonClass[] currentMRO = null; - - if (getBaseClasses().length == 0) { - currentMRO = new PythonClass[]{this}; - } else if (getBaseClasses().length == 1) { - PythonClass[] baseMRO = getBaseClasses()[0].getMethodResolutionOrder(); - - if (baseMRO == null) { - currentMRO = new PythonClass[]{this}; - } else { - currentMRO = new PythonClass[baseMRO.length + 1]; - System.arraycopy(baseMRO, 0, currentMRO, 1, baseMRO.length); - currentMRO[0] = this; - } - } else { - MROMergeState[] toMerge = new MROMergeState[getBaseClasses().length + 1]; - - for (int i = 0; i < getBaseClasses().length; i++) { - toMerge[i] = new MROMergeState(); - toMerge[i].mro = getBaseClasses()[i].getMethodResolutionOrder(); - } - - toMerge[getBaseClasses().length] = new MROMergeState(); - toMerge[getBaseClasses().length].mro = getBaseClasses(); - ArrayList mro = new ArrayList<>(); - mro.add(this); - currentMRO = mergeMROs(toMerge, mro); - } - - for (PythonClass cls : currentMRO) { - if (cls instanceof PythonNativeClass) { - needsNativeAllocation = true; - break; - } - } - - methodResolutionOrder = currentMRO; - } - - PythonClass[] mergeMROs(MROMergeState[] toMerge, List mro) { - int idx; - scan: for (idx = 0; idx < toMerge.length; idx++) { - if (toMerge[idx].isMerged()) { - continue scan; - } - - PythonClass candidate = toMerge[idx].getCandidate(); - for (MROMergeState mergee : toMerge) { - if (mergee.pastnextContains(candidate)) { - continue scan; - } - } - - mro.add(candidate); - - for (MROMergeState element : toMerge) { - element.noteMerged(candidate); - } - - // restart scan - idx = -1; - } - - for (MROMergeState mergee : toMerge) { - if (!mergee.isMerged()) { - throw new IllegalStateException(); - } - } - - return mro.toArray(new PythonClass[mro.size()]); - } - - @Override - @TruffleBoundary - public void setAttribute(Object key, Object value) { - if (key instanceof String) { - invalidateAttributeInMROFinalAssumptions((String) key); - } - super.setAttribute(key, value); - } - - /** - * This method supports initialization and solves boot-order problems and should not normally be - * used. - */ - private void unsafeSetSuperClass(PythonClass... newBaseClasses) { - // TODO: if this is used outside bootstrapping, it needs to call - // computeMethodResolutionOrder for subclasses. - - assert getBaseClasses() == null || getBaseClasses().length == 0; - this.baseClasses = newBaseClasses; - - for (PythonClass base : getBaseClasses()) { - if (base != null) { - base.subClasses.add(this); - } - } - computeMethodResolutionOrder(); - } - - final Set getSubClasses() { - return subClasses; - } - - @Override - public String toString() { - CompilerAsserts.neverPartOfCompilation(); - return String.format("", className); - } - - public PythonClass[] getBaseClasses() { - return baseClasses; - } - - public long getFlags() { - return flags.getValue(); - } - - public void setFlags(long flags) { - this.flags.setValue(flags); - } - - FlagsContainer getFlagsContainer() { - return flags; - } - - /** - * Flags are copied from the initial dominant base class. However, classes may already be - * created before the C API was initialized, i.e., flags were not set. - */ - static final class FlagsContainer { - PythonClass initialDominantBase; - long flags; - - public FlagsContainer(PythonClass superClass) { - this.initialDominantBase = superClass; - } - - @TruffleBoundary - private long getValue() { - // This method is only called from C code, i.e., the flags of the initial super class - // must be available. - if (initialDominantBase != null) { - assert this != initialDominantBase.flags; - flags = initialDominantBase.flags.getValue(); - initialDominantBase = null; - } - return flags; - } - - private void setValue(long flags) { - if (initialDominantBase != null) { - initialDominantBase = null; - } - this.flags = flags; - } - } - - @Override - public PythonClassNativeWrapper getNativeWrapper() { - return (PythonClassNativeWrapper) super.getNativeWrapper(); - } - - public final Object getSulongType() { - return sulongType; - } - - @TruffleBoundary - public final void setSulongType(Object dynamicSulongType) { - this.sulongType = dynamicSulongType; - } - - public boolean needsNativeAllocation() { - return needsNativeAllocation; - } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index fb8d11c6e5..ed35f60d6d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -65,6 +65,7 @@ import com.oracle.graal.python.builtins.objects.mappingproxy.PMappingproxy; import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.type.TypeBuiltinsFactory.CallNodeFactory; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.argument.positional.PositionalArgumentsNode; @@ -112,11 +113,11 @@ protected List> getNodeFa public abstract static class ReprNode extends PythonUnaryBuiltinNode { @Specialization - public String repr(PythonClass self, + public String repr(AbstractPythonClass self, @Cached("create()") ReadAttributeFromObjectNode readModuleNode, - @Cached("create(__GETATTRIBUTE__)") LookupAndCallBinaryNode readQualNameNode) { + @Cached("create()") ReadAttributeFromObjectNode readQualNameNode) { Object moduleName = readModuleNode.execute(self, __MODULE__); - Object qualName = readQualNameNode.executeObject(self, __QUALNAME__); + Object qualName = readQualNameNode.execute(self, __QUALNAME__); return concat(moduleName, qualName); } @@ -142,8 +143,9 @@ Object doit(PythonClass klass) { @GenerateNodeFactory public abstract static class MroNode extends PythonBuiltinNode { @Specialization - Object doit(PythonClass klass) { - PythonClass[] mro = klass.getMethodResolutionOrder(); + Object doit(PythonClass klass, + @Cached("create()") GetMroNode getMroNode) { + AbstractPythonClass[] mro = getMroNode.execute(klass); return factory().createList(Arrays.copyOf(mro, mro.length, Object[].class)); } @@ -161,6 +163,7 @@ public abstract static class CallNode extends PythonVarargsBuiltinNode { @Child private CallVarargsMethodNode dispatchInit = CallVarargsMethodNode.create(); @Child private LookupAttributeInMRONode lookupInit = LookupAttributeInMRONode.create(__INIT__); @Child private GetClassNode getClass = GetClassNode.create(); + @Child private TypeNodes.IsSameTypeNode isSameTypeNode; private final IsBuiltinClassProfile isClassClassProfile = IsBuiltinClassProfile.create(); @@ -206,8 +209,8 @@ private Object op(VirtualFrame frame, PythonClass self, Object[] arguments, PKey CompilerAsserts.partialEvaluationConstant(doCreateArgs); Object[] newArgs = doCreateArgs ? PositionalArgumentsNode.prependArgument(self, arguments, arguments.length) : arguments; Object newInstance = dispatchNew.execute(frame, newMethod, newArgs, keywords); - PythonClass newInstanceKlass = getClass.execute(newInstance); - if (newInstanceKlass == self) { + AbstractPythonClass newInstanceKlass = getClass.execute(newInstance); + if (isSameType(newInstanceKlass, self)) { if (arguments.length == 2 && isClassClassProfile.profileClass(self, PythonBuiltinClassType.PythonClass)) { // do not call init if we are creating a new instance of type and we are // passing keywords or more than one argument see: @@ -235,6 +238,14 @@ private Object op(VirtualFrame frame, PythonClass self, Object[] arguments, PKey throw raise(TypeError, "cannot create '%s' instances", self.getName()); } } + + private boolean isSameType(AbstractPythonClass left, AbstractPythonClass right) { + if (isSameTypeNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isSameTypeNode = insert(TypeNodes.IsSameTypeNode.create()); + } + return isSameTypeNode.execute(left, right); + } } @Builtin(name = __GETATTRIBUTE__, fixedNumOfPositionalArgs = 2) @@ -472,7 +483,7 @@ PList getSubclasses(PythonClass cls, } @TruffleBoundary - private static Object[] toArray(Set subclasses) { + private static Object[] toArray(Set subclasses) { return subclasses.toArray(); } } @@ -508,23 +519,25 @@ Object setName(PythonClass cls, Object value, static abstract class ModuleNode extends PythonBinaryBuiltinNode { @Specialization(guards = "isNoValue(value)") - @TruffleBoundary - Object getModule(PythonClass cls, @SuppressWarnings("unused") PNone value) { - if (cls instanceof PythonBuiltinClass) { - String module = ((PythonBuiltinClass) cls).getType().getPublicInModule(); - return module == null ? "builtins" : module; - } - Object module = cls.getAttribute(__MODULE__); + Object getModule(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { + String module = cls.getType().getPublicInModule(); + return module == null ? "builtins" : module; + } + + @Specialization(guards = "isNoValue(value)") + Object getModule(PythonClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create()") ReadAttributeFromObjectNode readAttrNode) { + Object module = readAttrNode.execute(cls, __MODULE__); if (module == PNone.NO_VALUE) { - throw raise(AttributeError, ""); + throw raise(AttributeError); } return module; } @Specialization(guards = "!isNoValue(value)") - @TruffleBoundary - Object setModule(PythonClass cls, Object value) { - cls.setAttribute(__MODULE__, value); + Object setModule(PythonClass cls, Object value, + @Cached("create()") WriteAttributeToObjectNode writeAttrNode) { + writeAttrNode.execute(cls, __MODULE__, value); return PNone.NONE; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 8f968282f5..576fba654d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -40,43 +40,108 @@ */ package com.oracle.graal.python.builtins.objects.type; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__; + import java.util.Set; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.PythonBuiltinClassType; +import com.oracle.graal.python.builtins.objects.cext.CExtNodes; +import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass.FlagsContainer; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetNameNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSubclassesNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSulongTypeNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSuperClassNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetTypeFlagsNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.IsSameTypeNodeGen; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.PNodeWithContext; +import com.oracle.graal.python.nodes.SpecialMethodNames; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.nodes.Node; public abstract class TypeNodes { public abstract static class GetTypeFlagsNode extends PNodeWithContext { - public abstract long execute(PythonClass clazz); + public abstract long execute(AbstractPythonClass clazz); @Specialization(guards = "isInitialized(clazz)") - long doInitialized(PythonClass clazz) { + long doInitialized(ManagedPythonClass clazz) { return clazz.getFlagsContainer().flags; } @Specialization - long doGeneric(PythonClass clazz) { + long doGeneric(ManagedPythonClass clazz) { if (!isInitialized(clazz)) { - return clazz.getFlags(); + return getValue(clazz.getFlagsContainer()); } return clazz.getFlagsContainer().flags; } - protected static boolean isInitialized(PythonClass clazz) { + @Specialization + long doNative(PythonNativeClass clazz, + @Cached("createReadNode()") Node readNode) { + return doNativeGeneric(clazz, readNode); + } + + @TruffleBoundary + private static long getValue(FlagsContainer fc) { + // This method is only called from C code, i.e., the flags of the initial super class + // must be available. + if (fc.initialDominantBase != null) { + fc.flags = doSlowPath(fc.initialDominantBase); + fc.initialDominantBase = null; + } + return fc.flags; + } + + @TruffleBoundary + public static long doSlowPath(AbstractPythonClass clazz) { + if (clazz instanceof ManagedPythonClass) { + ManagedPythonClass mclazz = (ManagedPythonClass) clazz; + if (isInitialized(mclazz)) { + return mclazz.getFlagsContainer().flags; + } else { + return getValue(mclazz.getFlagsContainer()); + } + } else if (clazz instanceof PythonNativeClass) { + return doNativeGeneric((PythonNativeClass) clazz, createReadNode()); + } + throw new IllegalStateException("unknown type"); + + } + + static long doNativeGeneric(PythonNativeClass clazz, Node readNode) { + try { + return (long) ForeignAccess.sendRead(readNode, (TruffleObject) clazz.getPtr(), NativeMemberNames.TP_FLAGS); + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + CompilerDirectives.transferToInterpreter(); + throw e.raise(); + } + } + + protected static boolean isInitialized(ManagedPythonClass clazz) { return clazz.getFlagsContainer().initialDominantBase == null; } + protected static Node createReadNode() { + return Message.READ.createNode(); + } + public static GetTypeFlagsNode create() { return GetTypeFlagsNodeGen.create(); } @@ -84,24 +149,26 @@ public static GetTypeFlagsNode create() { public abstract static class GetMroNode extends PNodeWithContext { - public abstract PythonClass[] execute(Object obj); + public abstract AbstractPythonClass[] execute(Object obj); @Specialization - PythonClass[] doPythonClass(PythonClass obj) { + AbstractPythonClass[] doPythonClass(PythonClass obj) { return obj.getMethodResolutionOrder(); } @Specialization - PythonClass[] doPythonClass(PythonBuiltinClassType obj) { + AbstractPythonClass[] doPythonClass(PythonBuiltinClassType obj) { return getBuiltinPythonClass(obj).getMethodResolutionOrder(); } @TruffleBoundary - public static PythonClass[] doSlowPath(Object obj) { - if (obj instanceof PythonClass) { - return ((PythonClass) obj).getMethodResolutionOrder(); + public static AbstractPythonClass[] doSlowPath(Object obj) { + if (obj instanceof ManagedPythonClass) { + return ((ManagedPythonClass) obj).getMethodResolutionOrder(); } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getMethodResolutionOrder(); + } else if (obj instanceof PythonNativeClass) { + // TODO implement } throw new IllegalStateException("unknown type " + obj.getClass().getName()); } @@ -116,7 +183,7 @@ public abstract static class GetNameNode extends PNodeWithContext { public abstract String execute(Object obj); @Specialization - String doPythonClass(PythonClass obj) { + String doPythonClass(ManagedPythonClass obj) { return obj.getName(); } @@ -127,14 +194,16 @@ String doPythonClass(PythonBuiltinClassType obj) { @TruffleBoundary public static String doSlowPath(Object obj) { - if (obj instanceof PythonClass) { - return ((PythonClass) obj).getName(); + if (obj instanceof ManagedPythonClass) { + return ((ManagedPythonClass) obj).getName(); } else if (obj instanceof PythonBuiltinClassType) { // TODO(fa): remove this special case if (obj == PythonBuiltinClassType.TruffleObject) { return BuiltinNames.FOREIGN; } return ((PythonBuiltinClassType) obj).getName(); + } else if (obj instanceof PythonNativeClass) { + // TODO implement } throw new IllegalStateException("unknown type " + obj.getClass().getName()); } @@ -150,7 +219,7 @@ public abstract static class GetSuperClassNode extends PNodeWithContext { public abstract LazyPythonClass execute(Object obj); @Specialization - LazyPythonClass doPythonClass(PythonClass obj) { + LazyPythonClass doPythonClass(ManagedPythonClass obj) { return obj.getSuperClass(); } @@ -161,10 +230,12 @@ LazyPythonClass doPythonClass(PythonBuiltinClassType obj) { @TruffleBoundary public static LazyPythonClass doSlowPath(Object obj) { - if (obj instanceof PythonClass) { - return ((PythonClass) obj).getSuperClass(); + if (obj instanceof ManagedPythonClass) { + return ((ManagedPythonClass) obj).getSuperClass(); } else if (obj instanceof PythonBuiltinClassType) { return ((PythonBuiltinClassType) obj).getBase(); + } else if (obj instanceof PythonNativeClass) { + // TODO implement } throw new IllegalStateException("unknown type " + obj.getClass().getName()); } @@ -177,24 +248,26 @@ public static GetSuperClassNode create() { public abstract static class GetSubclassesNode extends PNodeWithContext { - public abstract Set execute(Object obj); + public abstract Set execute(Object obj); @Specialization - Set doPythonClass(PythonClass obj) { + Set doPythonClass(ManagedPythonClass obj) { return obj.getSubClasses(); } @Specialization - Set doPythonClass(PythonBuiltinClassType obj) { + Set doPythonClass(PythonBuiltinClassType obj) { return getBuiltinPythonClass(obj).getSubClasses(); } @TruffleBoundary - public static Set doSlowPath(Object obj) { - if (obj instanceof PythonClass) { - return ((PythonClass) obj).getSubClasses(); + public static Set doSlowPath(Object obj) { + if (obj instanceof ManagedPythonClass) { + return ((ManagedPythonClass) obj).getSubClasses(); } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getSubClasses(); + } else if (obj instanceof PythonNativeClass) { + // TODO implement } throw new IllegalStateException("unknown type " + obj.getClass().getName()); } @@ -205,4 +278,80 @@ public static GetSubclassesNode create() { } + @ImportStatic(SpecialMethodNames.class) + public abstract static class IsSameTypeNode extends PNodeWithContext { + + public abstract boolean execute(Object left, Object right); + + @Specialization + boolean doManaged(ManagedPythonClass left, ManagedPythonClass right) { + return left == right; + } + + @Specialization + boolean doNative(PythonNativeClass left, PythonNativeClass right, + @Cached("create(__EQ__)") CExtNodes.PointerCompareNode pointerCompareNode) { + return pointerCompareNode.execute(left, right); + } + + @Fallback + boolean doOther(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") Object right) { + return false; + } + + @TruffleBoundary + public static boolean doSlowPath(Object left, Object right) { + if (left instanceof ManagedPythonClass && right instanceof ManagedPythonClass) { + return left == right; + } else if (left instanceof PythonNativeClass && right instanceof PythonNativeClass) { + return CExtNodes.PointerCompareNode.create(__EQ__).execute((PythonNativeClass) left, (PythonNativeClass) right); + } + return false; + } + + public static IsSameTypeNode create() { + return IsSameTypeNodeGen.create(); + } + + } + + /** accesses the Sulong type of a class; does no recursive resolving */ + public abstract static class GetSulongTypeNode extends Node { + + public abstract Object execute(AbstractPythonClass clazz); + + @Specialization + Object doInitialized(ManagedPythonClass clazz) { + return clazz.getSulongType(); + } + + @Specialization + Object doNative(@SuppressWarnings("unused") PythonNativeClass clazz) { + return null; + } + + @TruffleBoundary + public static Object getSlowPath(AbstractPythonClass clazz) { + if (clazz instanceof ManagedPythonClass) { + return ((ManagedPythonClass) clazz).getSulongType(); + } else if (clazz instanceof PythonNativeClass) { + return null; + } + throw new IllegalStateException("unknown type " + clazz.getClass().getName()); + } + + @TruffleBoundary + public static void setSlowPath(AbstractPythonClass clazz, Object sulongType) { + if (clazz instanceof ManagedPythonClass) { + ((ManagedPythonClass) clazz).setSulongType(sulongType); + } + throw new IllegalStateException("cannot set Sulong type for " + clazz.getClass().getName()); + } + + public static GetSulongTypeNode create() { + return GetSulongTypeNodeGen.create(); + } + + } + } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java index e5abd27674..7f481f767d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java @@ -65,9 +65,9 @@ import com.oracle.graal.python.builtins.objects.slice.PSlice; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.tuple.PTuple; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.runtime.sequence.PSequence; import com.oracle.graal.python.runtime.sequence.storage.BasicSequenceStorage; import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; @@ -117,7 +117,7 @@ public static boolean isCallable(Object value) { } public static boolean isClass(Object value) { - return value instanceof PythonClass; + return value instanceof AbstractPythonClass; } public static boolean isEmptyStorage(PSequence sequence) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java index fe96f49faf..e272add5ed 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java @@ -47,7 +47,8 @@ import com.oracle.graal.python.builtins.objects.exception.PBaseException; import com.oracle.graal.python.builtins.objects.function.PKeyword; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; import com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode; import com.oracle.graal.python.runtime.PythonContext; @@ -152,15 +153,15 @@ public final PException raiseOSError(VirtualFrame frame, Object[] args) { return raise(error); } - public final PythonClass getPythonClass(LazyPythonClass lazyClass, ConditionProfile profile) { - if (profile.profile(lazyClass instanceof PythonClass)) { - return (PythonClass) lazyClass; + public final ManagedPythonClass getPythonClass(LazyPythonClass lazyClass, ConditionProfile profile) { + if (profile.profile(lazyClass instanceof ManagedPythonClass)) { + return (ManagedPythonClass) lazyClass; } else { return getCore().lookupType((PythonBuiltinClassType) lazyClass); } } - public final PythonClass getBuiltinPythonClass(PythonBuiltinClassType type) { + public final PythonBuiltinClass getBuiltinPythonClass(PythonBuiltinClassType type) { return getCore().lookupType(type); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index e2c304ff78..aedd873ca8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -42,7 +42,10 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.PNone; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PNodeWithContext; @@ -54,6 +57,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.ControlFlowException; import com.oracle.truffle.api.nodes.ExplodeLoop; @ImportStatic(PythonOptions.class) @@ -86,8 +90,9 @@ protected Object lookup(PythonBuiltinClassType klass, Object key) { @Specialization(replaces = "lookupConstantMRO") protected Object lookup(PythonClass klass, Object key, + @Cached("create()") GetMroNode getMroNode, @Cached("create()") ReadAttributeFromObjectNode readAttrNode) { - return LookupAttributeInMRONode.lookupSlow(klass, key, readAttrNode); + return LookupAttributeInMRONode.lookupSlow(klass, key, getMroNode, readAttrNode); } } @@ -114,13 +119,13 @@ public static LookupAttributeInMRONode create(String key) { protected static Object findAttr(PythonCore core, PythonBuiltinClassType klass, Object key) { PythonBuiltinClassType current = klass; while (current != PythonBuiltinClassType.PythonObject) { - Object value = core.lookupType(current).getAttribute(key); + Object value = ReadAttributeFromDynamicObjectNode.doSlowPath(core.lookupType(current).getStorage(), key); if (value != PNone.NO_VALUE) { return value; } current = current.getBase(); } - return core.lookupType(current).getAttribute(key); + return ReadAttributeFromDynamicObjectNode.doSlowPath(core.lookupType(current).getStorage(), key); } @Specialization(guards = {"klass == cachedKlass"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)") @@ -146,26 +151,34 @@ final static class PythonClassAssumptionPair { } protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonClass klass) { - PythonClass[] mro = getMro(klass); + AbstractPythonClass[] mro = getMro(klass); Assumption attrAssumption = klass.createAttributeInMROFinalAssumption(key); for (int i = 0; i < mro.length; i++) { - PythonClass cls = mro[i]; - if (i > 0) { - assert cls != klass : "MRO chain is incorrect: '" + klass + "' was found at position " + i; - cls.addAttributeInMROFinalAssumption(key, attrAssumption); - } + AbstractPythonClass clsObj = mro[i]; + // TODO(fa): that's just a first approach and needs to be implemented properly + if (clsObj instanceof ManagedPythonClass) { + ManagedPythonClass cls = (ManagedPythonClass) clsObj; + if (i > 0) { + assert cls != klass : "MRO chain is incorrect: '" + klass + "' was found at position " + i; + cls.addAttributeInMROFinalAssumption(key, attrAssumption); + } - if (cls.getStorage().containsKey(key)) { - Object value = cls.getStorage().get(key); - if (value != PNone.NO_VALUE) { - return new PythonClassAssumptionPair(attrAssumption, value); + if (cls.getStorage().containsKey(key)) { + Object value = cls.getStorage().get(key); + if (value != PNone.NO_VALUE) { + return new PythonClassAssumptionPair(attrAssumption, value); + } } + } else { + assert clsObj instanceof PythonNativeClass; + return null; } } return new PythonClassAssumptionPair(attrAssumption, PNone.NO_VALUE); } - @Specialization(guards = {"klass == cachedKlass"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = {"cachedClassInMROInfo.assumption"}) + @Specialization(guards = {"klass == cachedKlass", "cachedClassInMROInfo != null"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = { + "cachedClassInMROInfo.assumption"}) protected Object lookupConstantMROCached(@SuppressWarnings("unused") PythonClass klass, @Cached("klass") @SuppressWarnings("unused") PythonClass cachedKlass, @Cached("findAttrClassAndAssumptionInMRO(cachedKlass)") PythonClassAssumptionPair cachedClassInMROInfo) { @@ -182,14 +195,14 @@ protected ReadAttributeFromObjectNode[] create(int size) { @Specialization(guards = {"klass == cachedKlass", "mroLength < 32"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = "lookupStable") @ExplodeLoop(kind = ExplodeLoop.LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN) - protected Object lookupConstantMRO(@SuppressWarnings("unused") PythonClass klass, - @Cached("klass") @SuppressWarnings("unused") PythonClass cachedKlass, + protected Object lookupConstantMRO(@SuppressWarnings("unused") ManagedPythonClass klass, + @Cached("klass") @SuppressWarnings("unused") ManagedPythonClass cachedKlass, @Cached("cachedKlass.getLookupStableAssumption()") @SuppressWarnings("unused") Assumption lookupStable, - @Cached(value = "getMro(cachedKlass)", dimensions = 1) PythonClass[] mro, + @Cached(value = "getMro(cachedKlass)", dimensions = 1) AbstractPythonClass[] mro, @Cached("mro.length") @SuppressWarnings("unused") int mroLength, @Cached("create(mroLength)") ReadAttributeFromObjectNode[] readAttrNodes) { for (int i = 0; i < mro.length; i++) { - PythonClass kls = mro[i]; + AbstractPythonClass kls = mro[i]; Object value = readAttrNodes[i].execute(kls, key); if (value != PNone.NO_VALUE) { return value; @@ -199,12 +212,13 @@ protected Object lookupConstantMRO(@SuppressWarnings("unused") PythonClass klass } @Specialization(replaces = {"lookupConstantMROCached", "lookupConstantMRO"}) - protected Object lookup(PythonClass klass, + protected Object lookup(ManagedPythonClass klass, + @Cached("create()") GetMroNode getMroNode, @Cached("create()") ReadAttributeFromObjectNode readAttrNode) { - return lookupSlow(klass, key, readAttrNode); + return lookupSlow(klass, key, getMroNode, readAttrNode); } - protected PythonClass[] getMro(PythonClass clazz) { + protected AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -212,10 +226,10 @@ protected PythonClass[] getMro(PythonClass clazz) { return getMroNode.execute(clazz); } - protected static Object lookupSlow(PythonClass klass, Object key, ReadAttributeFromObjectNode readAttrNode) { - PythonClass[] mro = GetMroNode.doSlowPath(klass); + protected static Object lookupSlow(ManagedPythonClass klass, Object key, GetMroNode getMroNode, ReadAttributeFromObjectNode readAttrNode) { + AbstractPythonClass[] mro = getMroNode.doSlowPath(klass); for (int i = 0; i < mro.length; i++) { - PythonClass kls = mro[i]; + AbstractPythonClass kls = mro[i]; Object value = readAttrNode.execute(kls, key); if (value != PNone.NO_VALUE) { return value; @@ -224,11 +238,11 @@ protected static Object lookupSlow(PythonClass klass, Object key, ReadAttributeF return PNone.NO_VALUE; } - public static Object lookupSlow(PythonClass klass, String key) { - PythonClass[] mro = GetMroNode.doSlowPath(klass); + public static Object lookupSlow(LazyPythonClass klass, String key) { + AbstractPythonClass[] mro = GetMroNode.doSlowPath(klass); for (int i = 0; i < mro.length; i++) { - PythonClass kls = mro[i]; - Object value = kls.getAttribute(key); + AbstractPythonClass kls = mro[i]; + Object value = ReadAttributeFromObjectNode.doSlowPath(kls, key); if (value != PNone.NO_VALUE) { return value; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ObjectAttributeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ObjectAttributeNode.java index 1fe974aca1..57cefdad5c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ObjectAttributeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ObjectAttributeNode.java @@ -60,7 +60,7 @@ public abstract class ObjectAttributeNode extends PNodeWithContext { @Child private GetDictStorageNode getStorageNode; - protected Object attrKey(Object key) { + protected static Object attrKey(Object key) { if (key instanceof PString) { return ((PString) key).getValue(); } else { @@ -76,7 +76,7 @@ protected HashingStorage getDictStorage(PHashingCollection c) { return getStorageNode.execute(c); } - protected boolean isDictUnsetOrSameAsStorage(PythonObject object) { + protected static boolean isDictUnsetOrSameAsStorage(PythonObject object) { return object.getDict() == null; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromDynamicObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromDynamicObjectNode.java index 3dd00af378..475b7d8208 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromDynamicObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromDynamicObjectNode.java @@ -145,11 +145,10 @@ protected Object updateShapeAndRead(DynamicObject dynamicObject, Object key, @Specialization(replaces = "readDirect") protected Object readIndirect(DynamicObject dynamicObject, Object key) { - Object value = dynamicObject.get(attrKey(key)); - if (value == null) { - return PNone.NO_VALUE; - } else { - return value; - } + return doSlowPath(dynamicObject, key); + } + + public static Object doSlowPath(DynamicObject dynamicObject, Object key) { + return dynamicObject.get(ObjectAttributeNode.attrKey(key), PNone.NO_VALUE); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java index 3cd1fe802e..5ee6b078be 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java @@ -41,8 +41,12 @@ package com.oracle.graal.python.nodes.attributes; import com.oracle.graal.python.builtins.objects.PNone; +import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetNativeDictNode; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetObjectDictNode; +import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeDictNode; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; +import com.oracle.graal.python.builtins.objects.common.HashingStorage; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; import com.oracle.graal.python.builtins.objects.common.PHashingCollection; import com.oracle.graal.python.builtins.objects.object.PythonObject; @@ -50,6 +54,7 @@ import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode; import com.oracle.graal.python.runtime.PythonOptions; import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; @@ -131,13 +136,21 @@ protected Node createReadMessageNode() { return Message.READ.createNode(); } - @Specialization(guards = { - "!isHiddenKey(key)", - "!isPythonObject(object)" - }) - protected Object readNative(PythonNativeObject object, Object key, + @Specialization(guards = {"!isHiddenKey(key)"}) + protected Object readNativeObject(PythonNativeObject object, Object key, @Cached("create()") GetObjectDictNode getNativeDict, @Cached("create()") HashingStorageNodes.GetItemNode getItemNode) { + return readNative(object, key, getNativeDict, getItemNode); + } + + @Specialization(guards = {"!isHiddenKey(key)"}) + protected Object readNativeClass(PythonNativeClass object, Object key, + @Cached("create()") GetTypeDictNode getNativeDict, + @Cached("create()") HashingStorageNodes.GetItemNode getItemNode) { + return readNative(object, key, getNativeDict, getItemNode); + } + + private Object readNative(Object object, Object key, GetNativeDictNode getNativeDict, HashingStorageNodes.GetItemNode getItemNode) { Object d = getNativeDict.execute(object); Object value = null; if (d instanceof PHashingCollection) { @@ -167,4 +180,37 @@ protected Object readForeign(TruffleObject object, Object key, protected PNone readUnboxed(Object object, Object key) { return PNone.NO_VALUE; } + + @TruffleBoundary + public static Object doSlowPath(Object object, Object key) { + if (object instanceof PythonObject) { + PythonObject po = (PythonObject) object; + if (ObjectAttributeNode.isDictUnsetOrSameAsStorage(po)) { + HashingStorage dictStorage = po.getDict().getDictStorage(); + Object value = dictStorage.getItem(key, HashingStorage.getSlowPathEquivalence(key)); + if (value == null) { + return PNone.NO_VALUE; + } else { + return value; + } + } else { + return ReadAttributeFromDynamicObjectNode.doSlowPath(po.getStorage(), key); + } + } else if (object instanceof PythonNativeObject || object instanceof PythonNativeClass) { + Object d = GetObjectDictNode.doSlowPath(object); + Object value = null; + if (d instanceof PHashingCollection) { + HashingStorage dictStorage = ((PHashingCollection) d).getDictStorage(); + value = dictStorage.getItem(key, HashingStorage.getSlowPathEquivalence(key)); + } + if (value == null) { + return PNone.NO_VALUE; + } else { + return value; + } + + } + return null; + + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallBinaryNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallBinaryNode.java index b8c21344bb..55516cc3ee 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallBinaryNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallBinaryNode.java @@ -45,7 +45,8 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PNotImplemented; import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode; @@ -286,18 +287,19 @@ Object callObject(Object left, Object right, @Cached("create(rname)") LookupAttributeInMRONode getattrR, @Cached("create()") GetClassNode getClass, @Cached("create()") GetClassNode getClassR, + @Cached("create()") TypeNodes.IsSameTypeNode isSameTypeNode, @Cached("create()") IsSubtypeNode isSubtype, @Cached("createBinaryProfile()") ConditionProfile notImplementedBranch) { Object result = PNotImplemented.NOT_IMPLEMENTED; - PythonClass leftClass = getClass.execute(left); + AbstractPythonClass leftClass = getClass.execute(left); Object leftCallable = getattr.execute(leftClass); - PythonClass rightClass = getClassR.execute(right); + AbstractPythonClass rightClass = getClassR.execute(right); Object rightCallable = getattrR.execute(rightClass); if (leftCallable == rightCallable) { rightCallable = PNone.NO_VALUE; } if (leftCallable != PNone.NO_VALUE) { - if (rightCallable != PNone.NO_VALUE && leftClass != rightClass && isSubtype.execute(rightClass, leftClass)) { + if (rightCallable != PNone.NO_VALUE && !isSameTypeNode.execute(leftClass, rightClass) && isSubtype.execute(rightClass, leftClass)) { result = ensureReverseDispatch().executeObject(rightCallable, right, left); if (result != PNotImplemented.NOT_IMPLEMENTED) { return result; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallTernaryNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallTernaryNode.java index d213bb39f2..b85cc5abeb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallTernaryNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallTernaryNode.java @@ -44,7 +44,8 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PNotImplemented; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; @@ -154,15 +155,16 @@ Object callObject( @Cached("create()") GetClassNode getClass, @Cached("create()") GetClassNode getClassR, @Cached("create()") IsSubtypeNode isSubtype, + @Cached("create()") IsSameTypeNode isSameTypeNode, @Cached("create()") BranchProfile notImplementedBranch) { - PythonClass leftClass = getClass.execute(v); - PythonClass rightClass = getClassR.execute(w); + AbstractPythonClass leftClass = getClass.execute(v); + AbstractPythonClass rightClass = getClassR.execute(w); Object result = PNotImplemented.NOT_IMPLEMENTED; Object leftCallable = getattr.execute(leftClass); Object rightCallable = PNone.NO_VALUE; - if (leftClass != rightClass) { + if (!isSameTypeNode.execute(leftClass, rightClass)) { rightCallable = getattrR.execute(rightClass); if (rightCallable == leftCallable) { rightCallable = PNone.NO_VALUE; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsFixedSubtypeMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsFixedSubtypeMRONode.java index fbbf04ec69..e2f88217d2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsFixedSubtypeMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsFixedSubtypeMRONode.java @@ -41,6 +41,7 @@ package com.oracle.graal.python.nodes.classes; import com.oracle.graal.python.builtins.PythonBuiltinClassType; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; @@ -96,7 +97,7 @@ protected boolean isSubtype(PythonClass derived, @Cached("create()") IsBuiltinClassProfile profile, @Cached("create()") GetMroNode getMroNode) { - for (PythonClass mro : getMroNode.execute(derived)) { + for (AbstractPythonClass mro : getMroNode.execute(derived)) { if (profile.profileClass(mro, clazz)) { return true; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeMRONode.java index 28738247a3..4e41e8582e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeMRONode.java @@ -41,9 +41,11 @@ package com.oracle.graal.python.nodes.classes; import com.oracle.graal.python.builtins.PythonBuiltinClassType; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; @@ -93,7 +95,7 @@ protected boolean isSubtype(PythonBuiltinClassType derived, PythonBuiltinClass c return isSubtype(derived, clazz.getType()); } - protected static boolean isBuiltinClass(PythonClass clazz) { + protected static boolean isBuiltinClass(AbstractPythonClass clazz) { return clazz instanceof PythonBuiltinClass; } @@ -111,7 +113,7 @@ protected static boolean isSubtype(@SuppressWarnings("unused") PythonBuiltinClas protected boolean isSubtype(PythonClass derived, PythonBuiltinClassType clazz, @Cached("create()") IsBuiltinClassProfile profile) { - for (PythonClass mro : getMro(derived)) { + for (AbstractPythonClass mro : getMro(derived)) { if (profile.profileClass(mro, clazz)) { return true; } @@ -121,9 +123,10 @@ protected boolean isSubtype(PythonClass derived, PythonBuiltinClassType clazz, } @Specialization - protected boolean isSubtype(PythonClass derived, PythonClass clazz) { - for (PythonClass mro : getMro(derived)) { - if (mro == clazz) { + protected boolean isSubtype(PythonClass derived, PythonClass clazz, + @Cached("create()") TypeNodes.IsSameTypeNode isSameTypeNode) { + for (AbstractPythonClass mro : getMro(derived)) { + if (isSameTypeNode.execute(mro, clazz)) { return true; } } @@ -131,7 +134,7 @@ protected boolean isSubtype(PythonClass derived, PythonClass clazz) { return false; } - private PythonClass[] getMro(PythonClass clazz) { + private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java index a0542f3e76..c53a7c9ddf 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java @@ -40,6 +40,7 @@ */ package com.oracle.graal.python.nodes.classes; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PNodeWithContext; @@ -76,7 +77,7 @@ public static IsSubtypeNode create() { boolean isSubtypeOfConstantType(@SuppressWarnings("unused") PythonClass derived, @SuppressWarnings("unused") PythonClass cls, @Cached("derived") PythonClass cachedDerived, @Cached("cls") PythonClass cachedCls) { - for (PythonClass n : getMro(cachedDerived)) { + for (AbstractPythonClass n : getMro(cachedDerived)) { if (n == cachedCls) { return true; } @@ -88,7 +89,7 @@ boolean isSubtypeOfConstantType(@SuppressWarnings("unused") PythonClass derived, @ExplodeLoop boolean isSubtypeOfVariableType(@SuppressWarnings("unused") PythonClass derived, PythonClass cls, @Cached("derived") PythonClass cachedDerived) { - for (PythonClass n : getMro(cachedDerived)) { + for (AbstractPythonClass n : getMro(cachedDerived)) { if (n == cls) { return true; } @@ -98,7 +99,7 @@ boolean isSubtypeOfVariableType(@SuppressWarnings("unused") PythonClass derived, @Specialization(replaces = {"isSubtypeOfConstantType", "isSubtypeOfVariableType"}) boolean issubTypeGeneric(PythonClass derived, PythonClass cls) { - for (PythonClass n : getMro(derived)) { + for (AbstractPythonClass n : getMro(derived)) { if (n == cls) { return true; } @@ -119,7 +120,7 @@ public boolean isSubclass(Object derived, Object cls) { return abstractIsSubclassNode.execute(derived, cls); } - private PythonClass[] getMro(PythonClass clazz) { + private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/TopLevelExceptionHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/TopLevelExceptionHandler.java index 3591eedfa5..43127cb00a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/TopLevelExceptionHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/TopLevelExceptionHandler.java @@ -54,7 +54,7 @@ import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.module.PythonModule; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.argument.CreateArgumentsNode; import com.oracle.graal.python.nodes.call.CallNode; @@ -143,7 +143,7 @@ private void printExc(PException e) { } PBaseException value = e.getExceptionObject(); - PythonClass type = value.getPythonClass(); + AbstractPythonClass type = value.getPythonClass(); PTraceback tb = value.getTraceback(core.factory()); PythonModule sys = core.lookupBuiltinModule("sys"); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java index 8563b3cea7..c67384605e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java @@ -50,7 +50,8 @@ import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr; import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptor; import com.oracle.graal.python.builtins.objects.object.PythonObject; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.truffle.PythonTypes; @@ -78,145 +79,145 @@ public static GetClassNode create() { return GetClassNodeGen.create(); } - public abstract PythonClass execute(boolean object); + public abstract PythonBuiltinClass execute(boolean object); - public abstract PythonClass execute(int object); + public abstract PythonBuiltinClass execute(int object); - public abstract PythonClass execute(long object); + public abstract PythonBuiltinClass execute(long object); - public abstract PythonClass execute(double object); + public abstract PythonBuiltinClass execute(double object); - public final PythonClass execute(Object object) { + public final AbstractPythonClass execute(Object object) { return executeGetClass(classProfile.profile(object)); } - protected abstract PythonClass executeGetClass(Object object); + protected abstract AbstractPythonClass executeGetClass(Object object); @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") GetSetDescriptor object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") GetSetDescriptor object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @Specialization - protected PythonClass getIt(@SuppressWarnings("unused") GetSetDescriptor object) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") GetSetDescriptor object) { return getCore().lookupType(PythonBuiltinClassType.GetSetDescriptor); } @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") PNone object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") PNone object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @Specialization - protected PythonClass getIt(@SuppressWarnings("unused") PNone object) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") PNone object) { return getCore().lookupType(PythonBuiltinClassType.PNone); } @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") PNotImplemented object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") PNotImplemented object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @SuppressWarnings("unused") @Specialization - protected PythonClass getIt(PNotImplemented object) { + protected PythonBuiltinClass getIt(PNotImplemented object) { return getCore().lookupType(PythonBuiltinClassType.PNotImplemented); } @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") PEllipsis object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") PEllipsis object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @SuppressWarnings("unused") @Specialization - protected PythonClass getIt(PEllipsis object) { + protected PythonBuiltinClass getIt(PEllipsis object) { return getCore().lookupType(PythonBuiltinClassType.PEllipsis); } @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") boolean object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") boolean object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @SuppressWarnings("unused") @Specialization - protected PythonClass getIt(boolean object) { + protected PythonBuiltinClass getIt(boolean object) { return getCore().lookupType(PythonBuiltinClassType.Boolean); } @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") int object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") int object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @SuppressWarnings("unused") @Specialization - protected PythonClass getIt(int object) { + protected PythonBuiltinClass getIt(int object) { return getCore().lookupType(PythonBuiltinClassType.PInt); } @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") long object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") long object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @SuppressWarnings("unused") @Specialization - protected PythonClass getIt(long object) { + protected PythonBuiltinClass getIt(long object) { return getCore().lookupType(PythonBuiltinClassType.PInt); } @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") double object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") double object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @SuppressWarnings("unused") @Specialization - protected PythonClass getIt(double object) { + protected PythonBuiltinClass getIt(double object) { return getCore().lookupType(PythonBuiltinClassType.PFloat); } @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") String object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") String object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @SuppressWarnings("unused") @Specialization - protected PythonClass getIt(String object) { + protected PythonBuiltinClass getIt(String object) { return getCore().lookupType(PythonBuiltinClassType.PString); } @Specialization - protected PythonClass getIt(PythonNativeObject object, + protected AbstractPythonClass getIt(PythonNativeObject object, @Cached("create()") GetNativeClassNode getNativeClassNode) { return getNativeClassNode.execute(object); } @Specialization(assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") PythonNativeVoidPtr object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") PythonNativeVoidPtr object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @Specialization - protected PythonClass getIt(@SuppressWarnings("unused") PythonNativeVoidPtr object) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") PythonNativeVoidPtr object) { return getCore().lookupType(PythonBuiltinClassType.PInt); } @Specialization - protected PythonClass getPythonClassGeneric(PythonObject object, + protected AbstractPythonClass getPythonClassGeneric(PythonObject object, @Cached("create()") GetLazyClassNode getLazyClass, @Cached("createIdentityProfile()") ValueProfile profile, @Cached("createBinaryProfile()") ConditionProfile getClassProfile) { @@ -224,19 +225,19 @@ protected PythonClass getPythonClassGeneric(PythonObject object, } @Specialization(guards = "isForeignObject(object)", assumptions = "singleContextAssumption()") - protected PythonClass getIt(@SuppressWarnings("unused") TruffleObject object, - @Cached("getIt(object)") PythonClass klass) { + protected PythonBuiltinClass getIt(@SuppressWarnings("unused") TruffleObject object, + @Cached("getIt(object)") PythonBuiltinClass klass) { return klass; } @SuppressWarnings("unused") @Specialization(guards = "isForeignObject(object)") - protected PythonClass getIt(TruffleObject object) { + protected PythonBuiltinClass getIt(TruffleObject object) { return getCore().lookupType(PythonBuiltinClassType.TruffleObject); } @TruffleBoundary - public static PythonClass getItSlowPath(Object o) { + public static AbstractPythonClass getItSlowPath(Object o) { PythonCore core = PythonLanguage.getContextRef().get().getCore(); if (PGuards.isForeignObject(o)) { return core.lookupType(PythonBuiltinClassType.TruffleObject); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/IsBuiltinClassProfile.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/IsBuiltinClassProfile.java index 74c5bcc27e..fa8f1e81db 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/IsBuiltinClassProfile.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/IsBuiltinClassProfile.java @@ -42,9 +42,9 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.object.PythonObject; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -203,7 +203,7 @@ public boolean profileClass(LazyPythonClass clazz, PythonBuiltinClassType type) } } - public boolean profileClass(PythonClass clazz, PythonBuiltinClassType type) { + public boolean profileClass(AbstractPythonClass clazz, PythonBuiltinClassType type) { if (clazz instanceof PythonBuiltinClass) { if (!isBuiltinClass) { CompilerDirectives.transferToInterpreterAndInvalidate(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java index f944062d9e..ee0f78a2f6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java @@ -27,6 +27,7 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.tuple.PTuple; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; @@ -152,8 +153,8 @@ private boolean matchesExceptionCached(VirtualFrame frame, LazyPythonClass lazyC } } else { // non-builtin class: look through MRO - PythonClass[] mro = getMro((PythonClass) lazyClass); - for (PythonClass current : mro) { + AbstractPythonClass[] mro = getMro((PythonClass) lazyClass); + for (AbstractPythonClass current : mro) { if (isClassProfile.profileClass(current, cachedError)) { matches = true; break; @@ -216,8 +217,8 @@ private boolean matches(Object expectedType, PythonClass clazz) { if (equalsProfile.profile(expectedType == clazz)) { return true; } - PythonClass[] mro = getMro(clazz); - for (PythonClass current : mro) { + AbstractPythonClass[] mro = getMro(clazz); + for (AbstractPythonClass current : mro) { if (expectedType == current) { return true; } @@ -275,7 +276,7 @@ public boolean isInstrumentable() { return getSourceSection() != null; } - private PythonClass[] getMro(PythonClass clazz) { + private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java index d8b7c63f43..47b3a49f50 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java @@ -31,6 +31,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.exception.PBaseException; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; @@ -44,7 +45,6 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; -import com.oracle.truffle.api.dsl.NodeChildren; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -86,7 +86,7 @@ private void checkBaseClass(PythonClass pythonClass) { if (simpleBaseCheckProfile.profileClass(pythonClass, BaseException)) { return; } - for (PythonClass klass : getMro(pythonClass)) { + for (AbstractPythonClass klass : getMro(pythonClass)) { if (iterativeBaseCheckProfile.profileClass(klass, BaseException)) { return; } @@ -115,7 +115,7 @@ public void doRaise(Object exception, Object cause) { throw raise(TypeError, "exceptions must derive from BaseException"); } - private PythonClass[] getMro(PythonClass clazz) { + private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java index b648295914..3727b4dbc5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java @@ -32,7 +32,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.exception.PBaseException; import com.oracle.graal.python.builtins.objects.function.PKeyword; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode; import com.oracle.graal.python.nodes.call.CallNode; import com.oracle.graal.python.nodes.expression.CastToBooleanNode; @@ -150,7 +150,7 @@ protected PException doEnter(VirtualFrame frame, Object withObject, Object enter protected void handleException(VirtualFrame frame, Object withObject, Object exitCallable, PException e) { e.getExceptionObject().reifyException(); PBaseException value = e.getExceptionObject(); - PythonClass type = getClassNode.execute(value); + AbstractPythonClass type = getClassNode.execute(value); Object trace = e.getExceptionObject().getTraceback(factory()); Object returnValue = exitDispatch.execute(frame, exitCallable, new Object[]{withObject, type, value, trace}, PKeyword.EMPTY_KEYWORDS); // If exit handler returns 'true', suppress diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/SetItemNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/SetItemNode.java index cb99ae9b0b..f71d6867b6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/SetItemNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/SetItemNode.java @@ -28,7 +28,7 @@ import static com.oracle.graal.python.nodes.SpecialMethodNames.__SETITEM__; import com.oracle.graal.python.builtins.objects.object.PythonObject; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.TypeBuiltins.GetattributeNode; import com.oracle.graal.python.nodes.call.special.CallTernaryMethodNode; import com.oracle.graal.python.nodes.expression.ExpressionNode; @@ -110,7 +110,7 @@ public void doSpecialObject(PythonObject primary, int index, Object value, @Cached("create()") GetattributeNode getSetitemNode, @Cached("create()") GetClassNode getClassNode, @Cached("create()") CallTernaryMethodNode callNode) { - PythonClass primaryClass = getClassNode.execute(primary); + AbstractPythonClass primaryClass = getClassNode.execute(primary); Object setItemMethod = getSetitemNode.execute(primaryClass, __SETITEM__); callNode.execute(setItemMethod, primary, index, value); } @@ -120,7 +120,7 @@ public void doSpecialObject1(Object primary, Object index, Object value, @Cached("create()") GetattributeNode getSetitemNode, @Cached("create()") GetClassNode getClassNode, @Cached("create()") CallTernaryMethodNode callNode) { - PythonClass primaryClass = getClassNode.execute(primary); + AbstractPythonClass primaryClass = getClassNode.execute(primary); Object setItemMethod = getSetitemNode.execute(primaryClass, __SETITEM__); callNode.execute(setItemMethod, primary, index, value); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java index 0890abb593..d421bea1e3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java @@ -66,6 +66,7 @@ import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; 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.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; @@ -320,13 +321,17 @@ public Object execute(Object obj, boolean includeInternal) { PythonAbstractObject object = (PythonAbstractObject) obj; HashSet keys = new HashSet<>(); - PythonClass klass = getClass.execute(object); - for (PythonObject o : getMro(klass)) { - addKeysFromObject(keys, o, includeInternal); + AbstractPythonClass klass = getClass.execute(object); + for (AbstractPythonClass o : getMro(klass)) { + // TODO PythonNativeClass + if (o instanceof PythonObject) { + addKeysFromObject(keys, (PythonObject) o, includeInternal); + } } if (object instanceof PythonObject) { addKeysFromObject(keys, (PythonObject) object, includeInternal); } + // TODO PythonNativeObject if (includeInternal) { // we use the internal flag to also return dictionary keys for mappings if (isMapping.execute(object)) { @@ -351,7 +356,7 @@ public Object execute(Object obj, boolean includeInternal) { return factory.createTuple(keys.toArray(new String[keys.size()])); } - private PythonClass[] getMro(PythonClass clazz) { + private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -791,8 +796,8 @@ public int access(Object object, Object fieldName) { int info = KeyInfo.NONE; Object attr = PNone.NO_VALUE; - PythonClass klass = getClassNode.execute(object); - for (PythonClass c : getMro(klass)) { + AbstractPythonClass klass = getClassNode.execute(object); + for (AbstractPythonClass c : getMro(klass)) { attr = readNode.execute(c, fieldName); if (attr != PNone.NO_VALUE) { owner = c; @@ -855,7 +860,7 @@ public int access(Object object, Object fieldName) { return info; } - private PythonClass[] getMro(PythonClass clazz) { + private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index 8697b853cb..0d98768e94 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -107,6 +107,7 @@ import com.oracle.graal.python.builtins.objects.thread.PThread; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.zipimporter.PZipImporter; @@ -213,7 +214,7 @@ public PythonNativeVoidPtr createNativeVoidPtr(TruffleObject obj) { return trace(new PythonNativeVoidPtr(obj)); } - public SuperObject createSuperObject(PythonClass self) { + public SuperObject createSuperObject(AbstractPythonClass self) { return trace(new SuperObject(self)); } @@ -353,12 +354,12 @@ public PythonModule createPythonModule(PythonClass cls, String name) { return trace(new PythonModule(cls, name)); } - public PythonClass createPythonClass(LazyPythonClass metaclass, String name, PythonClass[] bases) { + public PythonClass createPythonClass(LazyPythonClass metaclass, String name, AbstractPythonClass[] bases) { return trace(new PythonClass(metaclass, name, PythonLanguage.freshShape(), bases)); } - public PythonNativeClass createNativeClassWrapper(Object object, PythonClass metaClass, String name, PythonClass[] pythonClasses) { - return trace(new PythonNativeClass(object, metaClass, name, pythonClasses)); + public PythonNativeClass createNativeClassWrapper(Object ptr) { + return trace(new PythonNativeClass(ptr)); } public PMemoryView createMemoryView(LazyPythonClass metaclass, Object value) { From e320170851a3a15db321d6ff44e1ad17658809a3 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 17 Jan 2019 15:56:13 +0100 Subject: [PATCH 056/202] Comment out 'PyType_Ready' to avoid compiler errors. --- .../builtins/modules/TruffleCextBuiltins.java | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 65df3c2f74..f6399e470e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -570,36 +570,38 @@ Object run(Object typestruct, PythonObjectNativeWrapper metaClass, PythonObjectN @Specialization Object run(Object typestruct, PythonClass metaClass, PTuple baseClasses, PDict nativeMembers) { - Object[] array = baseClasses.getArray(); - PythonClass[] bases = new PythonClass[array.length]; - for (int i = 0; i < array.length; i++) { - bases[i] = (PythonClass) array[i]; - } - - if (castToIntNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castToIntNode = insert(CastToIndexNode.create()); - } - - // 'tp_name' contains the fully-qualified name, i.e., 'module.A.B...' - String fqname = getStringItem(nativeMembers, TP_NAME); - String doc = getStringItem(nativeMembers, TP_DOC); - // the qualified name (i.e. without module name) like 'A.B...' - String qualName = getQualName(fqname); - PythonNativeClass cclass = factory().createNativeClassWrapper(typestruct, metaClass, qualName, bases); - writeAttrNode.execute(cclass, SpecialAttributeNames.__DOC__, doc); - - long basicsize = castToIntNode.execute(getLongItem(nativeMembers, TP_BASICSIZE)); - long itemsize = castToIntNode.execute(getLongItem(nativeMembers, TP_ITEMSIZE)); - writeAttrNode.execute(cclass, __BASICSIZE__, basicsize); - writeAttrNode.execute(cclass, __ITEMSIZE__, itemsize); - computeAndSetDictoffset(getLongItem(nativeMembers, TP_DICTOFFSET), cclass, basicsize, itemsize); - - String moduleName = getModuleName(fqname); - if (moduleName != null) { - writeAttrNode.execute(cclass, SpecialAttributeNames.__MODULE__, moduleName); - } - return new PythonClassInitNativeWrapper(cclass); +// Object[] array = baseClasses.getArray(); +// PythonClass[] bases = new PythonClass[array.length]; +// for (int i = 0; i < array.length; i++) { +// bases[i] = (PythonClass) array[i]; +// } +// +// if (castToIntNode == null) { +// CompilerDirectives.transferToInterpreterAndInvalidate(); +// castToIntNode = insert(CastToIndexNode.create()); +// } +// +// // 'tp_name' contains the fully-qualified name, i.e., 'module.A.B...' +// String fqname = getStringItem(nativeMembers, TP_NAME); +// String doc = getStringItem(nativeMembers, TP_DOC); +// // the qualified name (i.e. without module name) like 'A.B...' +// String qualName = getQualName(fqname); +// PythonNativeClass cclass = factory().createNativeClassWrapper(typestruct, metaClass, qualName, +// bases); +// writeAttrNode.execute(cclass, SpecialAttributeNames.__DOC__, doc); +// +// long basicsize = castToIntNode.execute(getLongItem(nativeMembers, TP_BASICSIZE)); +// long itemsize = castToIntNode.execute(getLongItem(nativeMembers, TP_ITEMSIZE)); +// writeAttrNode.execute(cclass, __BASICSIZE__, basicsize); +// writeAttrNode.execute(cclass, __ITEMSIZE__, itemsize); +// computeAndSetDictoffset(getLongItem(nativeMembers, TP_DICTOFFSET), cclass, basicsize, itemsize); +// +// String moduleName = getModuleName(fqname); +// if (moduleName != null) { +// writeAttrNode.execute(cclass, SpecialAttributeNames.__MODULE__, moduleName); +// } +// return new PythonClassInitNativeWrapper(cclass); + return null; } // may also update '__basicsize__' if necessary From c59d025f09dee7a72b895d81ba6d4546c197fda2 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 18 Jan 2019 13:28:33 +0100 Subject: [PATCH 057/202] Generalize nodes for 'AbstractPythonClass'. --- .../com.oracle.graal.python.cext/src/capi.c | 9 +- .../oracle/graal/python/PythonLanguage.java | 10 +- .../builtins/modules/ArrayModuleBuiltins.java | 22 +-- .../modules/BinasciiModuleBuiltins.java | 8 +- .../builtins/modules/BuiltinConstructors.java | 172 +++++++++--------- .../builtins/modules/BuiltinFunctions.java | 2 +- .../builtins/modules/PosixModuleBuiltins.java | 5 +- .../modules/RandomModuleBuiltins.java | 4 +- .../modules/SocketModuleBuiltins.java | 12 +- .../modules/ThreadModuleBuiltins.java | 8 +- .../builtins/modules/TruffleCextBuiltins.java | 33 ++-- .../modules/WeakRefModuleBuiltins.java | 6 +- .../modules/ZipImportModuleBuiltins.java | 6 +- .../builtins/objects/cext/CExtNodes.java | 85 ++++++--- .../objects/cext/NativeCAPISymbols.java | 32 ++++ .../objects/cext/NativeMemberNames.java | 1 + .../builtins/objects/cext/NativeWrappers.java | 12 +- .../builtins/objects/cext/PThreadStateMR.java | 6 +- .../objects/cext/PyNumberMethodsWrapper.java | 8 +- .../cext/PyNumberMethodsWrapperMR.java | 8 +- .../cext/PySequenceMethodsWrapper.java | 8 +- .../cext/PySequenceMethodsWrapperMR.java | 4 +- .../cext/PythonObjectNativeWrapperMR.java | 48 ++--- .../objects/common/SequenceStorageNodes.java | 83 +++++++++ .../objects/enumerate/PEnumerate.java | 4 +- .../objects/floats/FloatBuiltins.java | 8 +- .../objects/generator/GeneratorBuiltins.java | 12 +- .../GetSetDescriptorTypeBuiltins.java | 21 ++- .../builtins/objects/ints/IntBuiltins.java | 32 ++-- .../builtins/objects/iterator/PZip.java | 4 +- .../objects/object/ObjectBuiltins.java | 9 +- .../builtins/objects/object/PythonObject.java | 7 +- .../builtins/objects/random/PRandom.java | 4 +- .../reversed/PSequenceReverseIterator.java | 4 +- .../reversed/PStringReverseIterator.java | 4 +- .../objects/superobject/SuperBuiltins.java | 5 +- .../objects/superobject/SuperObject.java | 3 +- .../objects/type/ManagedPythonClass.java | 4 +- .../builtins/objects/type/TypeBuiltins.java | 67 +++++-- .../builtins/objects/type/TypeNodes.java | 63 ++++++- .../attributes/LookupAttributeInMRONode.java | 10 +- .../ReadAttributeFromObjectNode.java | 11 +- .../WriteAttributeToObjectNode.java | 8 +- .../python/nodes/classes/IsSubtypeNode.java | 28 ++- .../python/nodes/object/GetClassNode.java | 12 +- .../python/nodes/object/GetLazyClassNode.java | 22 ++- .../python/nodes/statement/ExceptNode.java | 33 +++- .../python/nodes/statement/RaiseNode.java | 14 +- .../interop/PythonMessageResolution.java | 2 +- .../runtime/object/PythonObjectFactory.java | 46 ++--- 50 files changed, 663 insertions(+), 366 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/capi.c b/graalpython/com.oracle.graal.python.cext/src/capi.c index 6d04cd42b9..02170cc0a0 100644 --- a/graalpython/com.oracle.graal.python.cext/src/capi.c +++ b/graalpython/com.oracle.graal.python.cext/src/capi.c @@ -281,8 +281,13 @@ void* get_ob_type(PyObject* obj) { } /** to be used from Java code only; reads native 'tp_dict' field */ -void* get_tp_dict(PyTypeObject* obj) { - return obj->tp_dict; +PyObject* get_tp_dict(PyTypeObject* obj) { + return native_to_java(obj->tp_dict); +} + +/** to be used from Java code only; reads native 'tp_dict' field */ +PyObject* get_tp_bases(PyTypeObject* obj) { + return native_to_java(obj->tp_bases); } /** to be used from Java code only; returns the type ID for a byte array */ diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index e9747bbee3..0cd17a7299 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -48,9 +48,10 @@ import com.oracle.graal.python.builtins.objects.method.PMethod; 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.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.NodeFactory; +import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode; import com.oracle.graal.python.nodes.call.InvokeNode; import com.oracle.graal.python.nodes.control.TopLevelExceptionHandler; import com.oracle.graal.python.nodes.expression.ExpressionNode; @@ -396,9 +397,10 @@ protected SourceSection findSourceLocation(PythonContext context, Object value) return callable.getCallTarget().getRootNode().getSourceSection(); } else if (value instanceof PCode) { return ((PCode) value).getRootNode().getSourceSection(); - } else if (value instanceof PythonClass) { - for (String k : ((PythonClass) value).getAttributeNames()) { - SourceSection attrSourceLocation = findSourceLocation(context, ((PythonClass) value).getAttribute(k)); + } else if (value instanceof ManagedPythonClass) { + for (String k : ((ManagedPythonClass) value).getAttributeNames()) { + Object attrValue = ReadAttributeFromDynamicObjectNode.doSlowPath(((ManagedPythonClass) value).getStorage(), k); + SourceSection attrSourceLocation = findSourceLocation(context, attrValue); if (attrSourceLocation != null) { return attrSourceLocation; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java index c4e4797465..df83aa6937 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java @@ -40,7 +40,7 @@ import com.oracle.graal.python.builtins.objects.common.SequenceNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.CastToByteNode; import com.oracle.graal.python.builtins.objects.range.PRange; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.control.GetIteratorNode; import com.oracle.graal.python.nodes.control.GetNextNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; @@ -68,7 +68,7 @@ protected List> getNodeFa abstract static class PythonArrayNode extends PythonBuiltinNode { @Specialization(guards = "isNoValue(initializer)") - PArray array(PythonClass cls, String typeCode, @SuppressWarnings("unused") PNone initializer) { + PArray array(LazyPythonClass cls, String typeCode, @SuppressWarnings("unused") PNone initializer) { /** * TODO @param typeCode should be a char, not a string */ @@ -76,7 +76,7 @@ PArray array(PythonClass cls, String typeCode, @SuppressWarnings("unused") PNone } @Specialization - PArray arrayWithRangeInitializer(PythonClass cls, String typeCode, PRange range) { + PArray arrayWithRangeInitializer(LazyPythonClass cls, String typeCode, PRange range) { if (!typeCode.equals("i")) { typeError(typeCode, range); } @@ -96,7 +96,7 @@ PArray arrayWithRangeInitializer(PythonClass cls, String typeCode, PRange range) } @Specialization - PArray arrayWithSequenceInitializer(PythonClass cls, String typeCode, String str) { + PArray arrayWithSequenceInitializer(LazyPythonClass cls, String typeCode, String str) { if (!typeCode.equals("c")) { typeError(typeCode, str); } @@ -121,7 +121,7 @@ protected boolean isDoubleArray(String typeCode) { } @Specialization(guards = "isByteArray(typeCode)") - PArray arrayByteInitializer(PythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer, + PArray arrayByteInitializer(LazyPythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer, @Cached("createCast()") CastToByteNode castToByteNode, @Cached("create()") GetIteratorNode getIterator, @Cached("create()") GetNextNode next, @@ -146,7 +146,7 @@ PArray arrayByteInitializer(PythonClass cls, @SuppressWarnings("unused") String } @Specialization(guards = "isIntArray(typeCode)") - PArray arrayIntInitializer(PythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer, + PArray arrayIntInitializer(LazyPythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer, @Cached("create()") GetIteratorNode getIterator, @Cached("create()") GetNextNode next, @Cached("create()") IsBuiltinClassProfile errorProfile, @@ -175,7 +175,7 @@ PArray arrayIntInitializer(PythonClass cls, @SuppressWarnings("unused") String t } @Specialization(guards = "isLongArray(typeCode)") - PArray arrayLongInitializer(PythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer, + PArray arrayLongInitializer(LazyPythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer, @Cached("create()") GetIteratorNode getIterator, @Cached("create()") GetNextNode next, @Cached("create()") IsBuiltinClassProfile errorProfile, @@ -204,7 +204,7 @@ PArray arrayLongInitializer(PythonClass cls, @SuppressWarnings("unused") String } @Specialization(guards = "isDoubleArray(typeCode)") - PArray arrayDoubleInitializer(PythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer, + PArray arrayDoubleInitializer(LazyPythonClass cls, @SuppressWarnings("unused") String typeCode, PSequence initializer, @Cached("create()") GetIteratorNode getIterator, @Cached("create()") GetNextNode next, @Cached("create()") IsBuiltinClassProfile errorProfile, @@ -236,7 +236,7 @@ PArray arrayDoubleInitializer(PythonClass cls, @SuppressWarnings("unused") Strin @Specialization @TruffleBoundary - PArray arrayWithObjectInitializer(@SuppressWarnings("unused") PythonClass cls, @SuppressWarnings("unused") String typeCode, Object initializer) { + PArray arrayWithObjectInitializer(@SuppressWarnings("unused") LazyPythonClass cls, @SuppressWarnings("unused") String typeCode, Object initializer) { if (!(isIntArray(typeCode) || isByteArray(typeCode) || isDoubleArray(typeCode))) { // TODO implement support for typecodes: b, B, u, h, H, i, I, l, L, q, Q, f or d throw raise(ValueError, "bad typecode (must be i, d, b, or l)"); @@ -245,7 +245,7 @@ PArray arrayWithObjectInitializer(@SuppressWarnings("unused") PythonClass cls, @ } @Specialization(guards = "!isString(typeCode)") - PArray noArray(@SuppressWarnings("unused") PythonClass cls, Object typeCode, @SuppressWarnings("unused") Object initializer) { + PArray noArray(@SuppressWarnings("unused") LazyPythonClass cls, Object typeCode, @SuppressWarnings("unused") Object initializer) { throw raise(TypeError, "array() argument 1 must be a unicode character, not %p", typeCode); } @@ -254,7 +254,7 @@ private static long longValue(Number n) { return n.longValue(); } - private PArray makeEmptyArray(PythonClass cls, char type) { + private PArray makeEmptyArray(LazyPythonClass cls, char type) { switch (type) { case 'c': case 'b': diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java index fc9d59806a..6304e64f89 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java @@ -60,7 +60,7 @@ import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView; import com.oracle.graal.python.builtins.objects.module.PythonModule; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; @@ -136,7 +136,7 @@ private byte[] b64decode(byte[] data) { static abstract class A2bHexNode extends PythonBinaryBuiltinNode { private ReadAttributeFromObjectNode getAttrNode; - private PException raise(PythonClass klass, String string) { + private PException raise(LazyPythonClass klass, String string) { return raise(factory().createBaseException(klass, string, new Object[0])); } @@ -159,11 +159,11 @@ PBytes a2b(PythonModule self, String data) { } private PException oddLengthError(PythonModule self) { - return raise((PythonClass) getAttrNode().execute(self, ERROR), "Odd-length string"); + return raise((LazyPythonClass) getAttrNode().execute(self, ERROR), "Odd-length string"); } private PException nonHexError(PythonModule self) { - return raise((PythonClass) getAttrNode().execute(self, ERROR), "Non-hexadecimal digit found"); + return raise((LazyPythonClass) getAttrNode().execute(self, ERROR), "Non-hexadecimal digit found"); } private ReadAttributeFromObjectNode getAttrNode() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index e838f32b84..39d2b41bc5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -116,6 +116,7 @@ import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; @@ -198,29 +199,29 @@ protected abstract static class CreateByteOrByteArrayNode extends PythonBuiltinN private final IsBuiltinClassProfile isClassProfile = IsBuiltinClassProfile.create(); @SuppressWarnings("unused") - protected Object create(PythonClass cls, byte[] barr) { + protected Object create(LazyPythonClass cls, byte[] barr) { throw new AssertionError("should not reach"); } @Specialization(guards = {"isNoValue(source)", "isNoValue(encoding)", "isNoValue(errors)"}) - public Object bytearray(PythonClass cls, @SuppressWarnings("unused") PNone source, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors) { + public Object bytearray(LazyPythonClass cls, @SuppressWarnings("unused") PNone source, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors) { return create(cls, new byte[0]); } @Specialization(guards = {"isInt(capObj)", "isNoValue(encoding)", "isNoValue(errors)"}) - public Object bytearray(PythonClass cls, Object capObj, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors) { + public Object bytearray(LazyPythonClass cls, Object capObj, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors) { int cap = getCastToIndexNode().execute(capObj); return create(cls, BytesUtils.fromSize(getCore(), cap)); } @Specialization(guards = "isNoValue(errors)") - public Object fromString(PythonClass cls, String source, String encoding, @SuppressWarnings("unused") PNone errors) { + public Object fromString(LazyPythonClass cls, String source, String encoding, @SuppressWarnings("unused") PNone errors) { return create(cls, BytesUtils.fromStringAndEncoding(getCore(), source, encoding)); } @Specialization(guards = {"isNoValue(encoding)", "isNoValue(errors)"}) @SuppressWarnings("unused") - public Object fromString(PythonClass cls, String source, PNone encoding, PNone errors) { + public Object fromString(LazyPythonClass cls, String source, PNone encoding, PNone errors) { throw raise(PythonErrorType.TypeError, "string argument without an encoding"); } @@ -229,7 +230,7 @@ protected boolean isSimpleBytes(PBytes iterable) { } @Specialization(guards = {"isSimpleBytes(iterable)", "isNoValue(encoding)", "isNoValue(errors)"}) - public Object bytearray(PythonClass cls, PBytes iterable, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors) { + public Object bytearray(LazyPythonClass cls, PBytes iterable, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors) { return create(cls, (byte[]) ((ByteSequenceStorage) iterable.getSequenceStorage()).getCopyOfInternalArrayObject()); } @@ -238,12 +239,12 @@ protected boolean isSimpleBytes(PByteArray iterable) { } @Specialization(guards = {"isSimpleBytes(iterable)", "isNoValue(encoding)", "isNoValue(errors)"}) - public Object bytearray(PythonClass cls, PByteArray iterable, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors) { + public Object bytearray(LazyPythonClass cls, PByteArray iterable, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors) { return create(cls, (byte[]) ((ByteSequenceStorage) iterable.getSequenceStorage()).getCopyOfInternalArrayObject()); } @Specialization(guards = {"!isInt(iterable)", "!isNoValue(iterable)", "isNoValue(encoding)", "isNoValue(errors)"}) - public Object bytearray(PythonClass cls, Object iterable, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors, + public Object bytearray(LazyPythonClass cls, Object iterable, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors, @Cached("create()") GetIteratorNode getIteratorNode, @Cached("create()") GetNextNode getNextNode, @Cached("create()") IsBuiltinClassProfile stopIterationProfile, @@ -293,7 +294,7 @@ protected CastToIndexNode getCastToIndexNode() { @GenerateNodeFactory public abstract static class BytesNode extends CreateByteOrByteArrayNode { @Override - protected Object create(PythonClass cls, byte[] barr) { + protected Object create(LazyPythonClass cls, byte[] barr) { return factory().createBytes(cls, barr); } } @@ -304,7 +305,7 @@ protected Object create(PythonClass cls, byte[] barr) { @TypeSystemReference(PythonArithmeticTypes.class) public abstract static class ByteArrayNode extends CreateByteOrByteArrayNode { @Override - protected Object create(PythonClass cls, byte[] barr) { + protected Object create(LazyPythonClass cls, byte[] barr) { return factory().createByteArray(cls, barr); } } @@ -367,7 +368,7 @@ PComplex complexFromObjectObject(Object cls, String real, Object imaginary) { if (!(imaginary instanceof PNone)) { throw raise(TypeError, "complex() can't take second arg if first is a string"); } - return convertStringToComplex(real, (PythonClass) cls); + return convertStringToComplex(real, (LazyPythonClass) cls); } @Specialization @@ -399,7 +400,7 @@ protected static boolean isExactComplexType(GetLazyClassNode getClassNode, PComp // Taken from Jython PyString's __complex__() method @TruffleBoundary(transferToInterpreterOnException = false) - private PComplex convertStringToComplex(String str, PythonClass cls) { + private PComplex convertStringToComplex(String str, LazyPythonClass cls) { boolean gotRe = false; boolean gotIm = false; boolean done = false; @@ -546,7 +547,7 @@ public static int endDouble(String string, int s) { public abstract static class DictionaryNode extends PythonBuiltinNode { @Specialization @SuppressWarnings("unused") - public PDict dictEmpty(PythonClass cls, Object[] args, PKeyword[] keywordArgs) { + public PDict dictEmpty(LazyPythonClass cls, Object[] args, PKeyword[] keywordArgs) { return factory().createDict(cls); } } @@ -557,25 +558,25 @@ public PDict dictEmpty(PythonClass cls, Object[] args, PKeyword[] keywordArgs) { public abstract static class EnumerateNode extends PythonBuiltinNode { @Specialization - public PEnumerate enumerate(PythonClass cls, Object iterable, @SuppressWarnings("unused") PNone keywordArg, + public PEnumerate enumerate(LazyPythonClass cls, Object iterable, @SuppressWarnings("unused") PNone keywordArg, @Cached("create()") GetIteratorNode getIterator) { return factory().createEnumerate(cls, getIterator.executeWith(iterable), 0); } @Specialization - public PEnumerate enumerate(PythonClass cls, Object iterable, int start, + public PEnumerate enumerate(LazyPythonClass cls, Object iterable, int start, @Cached("create()") GetIteratorNode getIterator) { return factory().createEnumerate(cls, getIterator.executeWith(iterable), start); } @Specialization - public PEnumerate enumerate(PythonClass cls, Object iterable, long start, + public PEnumerate enumerate(LazyPythonClass cls, Object iterable, long start, @Cached("create()") GetIteratorNode getIterator) { return factory().createEnumerate(cls, getIterator.executeWith(iterable), start); } @Specialization(guards = "!isInteger(start)") - public void enumerate(@SuppressWarnings("unused") PythonClass cls, @SuppressWarnings("unused") Object iterable, Object start) { + public void enumerate(@SuppressWarnings("unused") LazyPythonClass cls, @SuppressWarnings("unused") Object iterable, Object start) { raise(TypeError, "%p object cannot be interpreted as an integer", start); } } @@ -586,7 +587,7 @@ public void enumerate(@SuppressWarnings("unused") PythonClass cls, @SuppressWarn public abstract static class ReversedNode extends PythonBuiltinNode { @Specialization - public PythonObject reversed(@SuppressWarnings("unused") PythonClass cls, PRange range, + public PythonObject reversed(@SuppressWarnings("unused") LazyPythonClass cls, PRange range, @Cached("createBinaryProfile()") ConditionProfile stepOneProfile, @Cached("createBinaryProfile()") ConditionProfile stepMinusOneProfile) { int stop; @@ -611,17 +612,17 @@ public PythonObject reversed(@SuppressWarnings("unused") PythonClass cls, PRange } @Specialization - public PythonObject reversed(PythonClass cls, PString value) { + public PythonObject reversed(LazyPythonClass cls, PString value) { return factory().createStringReverseIterator(cls, value.getValue()); } @Specialization - public PythonObject reversed(PythonClass cls, String value) { + public PythonObject reversed(LazyPythonClass cls, String value) { return factory().createStringReverseIterator(cls, value); } @Specialization(guards = {"!isString(sequence)", "!isPRange(sequence)"}) - public Object reversed(PythonClass cls, Object sequence, + public Object reversed(LazyPythonClass cls, Object sequence, @Cached("create()") GetLazyClassNode getClassNode, @Cached("create(__REVERSED__)") LookupAttributeInMRONode reversedNode, @Cached("create()") CallUnaryMethodNode callReversedNode, @@ -848,13 +849,13 @@ public abstract static class FrozenSetNode extends PythonBuiltinNode { @Child private HashingCollectionNodes.SetItemNode setItemNode; @Specialization(guards = "isNoValue(arg)") - public PFrozenSet frozensetEmpty(PythonClass cls, @SuppressWarnings("unused") PNone arg) { + public PFrozenSet frozensetEmpty(LazyPythonClass cls, @SuppressWarnings("unused") PNone arg) { return factory().createFrozenSet(cls); } @Specialization @TruffleBoundary - public PFrozenSet frozenset(PythonClass cls, String arg) { + public PFrozenSet frozenset(LazyPythonClass cls, String arg) { PFrozenSet frozenSet = factory().createFrozenSet(cls); for (int i = 0; i < arg.length(); i++) { getSetItemNode().execute(frozenSet, String.valueOf(arg.charAt(i)), PNone.NO_VALUE); @@ -864,7 +865,7 @@ public PFrozenSet frozenset(PythonClass cls, String arg) { @Specialization(guards = "!isNoValue(iterable)") @TruffleBoundary - public PFrozenSet frozensetIterable(PythonClass cls, Object iterable, + public PFrozenSet frozensetIterable(LazyPythonClass cls, Object iterable, @Cached("create()") GetIteratorNode getIterator, @Cached("create()") GetNextNode next, @Cached("create()") IsBuiltinClassProfile errorProfile) { @@ -1315,7 +1316,7 @@ public boolean bool(Object cls, Object obj, public abstract static class ListNode extends PythonBinaryBuiltinNode { @Specialization - protected PList constructList(PythonClass cls, @SuppressWarnings("unused") Object value) { + protected PList constructList(LazyPythonClass cls, @SuppressWarnings("unused") Object value) { return factory().createList(cls); } @@ -1341,17 +1342,17 @@ public final Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeywo @Specialization Object doDirectConstruct(@SuppressWarnings("unused") PNone ignored, Object[] arguments, @SuppressWarnings("unused") PKeyword[] kwargs) { - return factory().createPythonObject((PythonClass) arguments[0]); + return factory().createPythonObject((LazyPythonClass) arguments[0]); } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf", "!self.needsNativeAllocation()"}) - Object doObjectDirect(@SuppressWarnings("unused") PythonClass self, Object[] varargs, PKeyword[] kwargs, - @Cached("self") PythonClass cachedSelf) { + Object doObjectDirect(@SuppressWarnings("unused") ManagedPythonClass self, Object[] varargs, PKeyword[] kwargs, + @Cached("self") ManagedPythonClass cachedSelf) { return doObjectIndirect(cachedSelf, varargs, kwargs); } @Specialization(guards = "!self.needsNativeAllocation()", replaces = "doObjectDirect") - Object doObjectIndirect(PythonClass self, Object[] varargs, PKeyword[] kwargs) { + Object doObjectIndirect(ManagedPythonClass self, Object[] varargs, PKeyword[] kwargs) { if (varargs.length > 0 || kwargs.length > 0) { // TODO: tfel: this should throw an error only if init isn't overridden } @@ -1359,7 +1360,7 @@ Object doObjectIndirect(PythonClass self, Object[] varargs, PKeyword[] kwargs) { } @Specialization(guards = "self.needsNativeAllocation()") - Object doNativeObjectIndirect(PythonClass self, Object[] varargs, PKeyword[] kwargs, + Object doNativeObjectIndirect(ManagedPythonClass self, Object[] varargs, PKeyword[] kwargs, @Cached("create()") GetMroNode getMroNode) { if (varargs.length > 0 || kwargs.length > 0) { // TODO: tfel: this should throw an error only if init isn't overridden @@ -1368,6 +1369,14 @@ Object doNativeObjectIndirect(PythonClass self, Object[] varargs, PKeyword[] kwa return callNativeGenericNewNode(nativeBaseClass, varargs, kwargs); } + @Specialization + Object doNativeObjectIndirect(PythonNativeClass self, Object[] varargs, PKeyword[] kwargs) { + if (varargs.length > 0 || kwargs.length > 0) { + // TODO: tfel: this should throw an error only if init isn't overridden + } + return callNativeGenericNewNode(self, varargs, kwargs); + } + private static PythonNativeClass findFirstNativeBaseClass(AbstractPythonClass[] methodResolutionOrder) { for (AbstractPythonClass cls : methodResolutionOrder) { if (cls instanceof PythonNativeClass) { @@ -1529,7 +1538,7 @@ public static boolean caseStartStop(long start, long stop, Object step) { public abstract static class SetNode extends PythonBuiltinNode { @Specialization - protected PSet constructSet(PythonClass cls, Object value, + protected PSet constructSet(LazyPythonClass cls, Object value, @Cached("create()") SetNodes.ConstructSetNode constructSetNode) { return constructSetNode.execute(cls, value); } @@ -1553,7 +1562,7 @@ public abstract static class StrNode extends PythonBuiltinNode { @CompilationFinal private ConditionProfile isStringProfile; @CompilationFinal private ConditionProfile isPStringProfile; - private Object asPString(PythonClass cls, String str) { + private Object asPString(LazyPythonClass cls, String str) { if (isPrimitiveProfile.profileClass(cls, PythonBuiltinClassType.PString)) { return str; } else { @@ -1565,18 +1574,18 @@ private Object asPString(PythonClass cls, String str) { @SuppressWarnings("unused") @Specialization - public Object str(PythonClass strClass, PNone arg, PNone encoding, PNone errors) { + public Object str(LazyPythonClass strClass, PNone arg, PNone encoding, PNone errors) { return asPString(strClass, ""); } @SuppressWarnings("unused") @Specialization - public Object str(PythonClass strClass, double arg, PNone encoding, PNone errors) { + public Object str(LazyPythonClass strClass, double arg, PNone encoding, PNone errors) { return asPString(strClass, PFloat.doubleToString(arg)); } @Specialization(guards = {"!isNoValue(obj)", "!isNone(obj)"}) - public Object str(PythonClass strClass, Object obj, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors, + public Object str(LazyPythonClass strClass, Object obj, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors, @Cached("create(__STR__)") LookupAndCallUnaryNode callNode) { Object result = callNode.executeObject(obj); if (getIsStringProfile().profile(result instanceof String)) { @@ -1588,7 +1597,7 @@ public Object str(PythonClass strClass, Object obj, @SuppressWarnings("unused") } @Specialization(guards = "!isNoValue(encoding)") - public Object doBytesLike(PythonClass strClass, PIBytesLike obj, Object encoding, Object errors) { + public Object doBytesLike(LazyPythonClass strClass, PIBytesLike obj, Object encoding, Object errors) { Object result = getCallDecodeNode().execute(obj, encoding, errors); if (getIsStringProfile().profile(result instanceof String)) { return asPString(strClass, (String) result); @@ -1599,7 +1608,7 @@ public Object doBytesLike(PythonClass strClass, PIBytesLike obj, Object encoding } @Specialization(guards = "!isNoValue(encoding)") - public Object doMemoryView(PythonClass strClass, PMemoryView obj, Object encoding, Object errors, + public Object doMemoryView(LazyPythonClass strClass, PMemoryView obj, Object encoding, Object errors, @Cached("createBinaryProfile()") ConditionProfile isBytesProfile, @Cached("create(TOBYTES)") LookupAndCallUnaryNode callToBytes) { Object result = callToBytes.executeObject(obj); @@ -1640,7 +1649,7 @@ private ConditionProfile getIsPStringProfile() { public abstract static class TupleNode extends PythonBinaryBuiltinNode { @Specialization - protected PTuple constructTuple(PythonClass cls, Object value, + protected PTuple constructTuple(LazyPythonClass cls, Object value, @Cached("create()") TupleNodes.ConstructTupleNode constructTupleNode) { return constructTupleNode.execute(cls, value); } @@ -1657,7 +1666,7 @@ public PTuple tupleObject(@SuppressWarnings("unused") Object cls, Object arg) { @GenerateNodeFactory public abstract static class ZipNode extends PythonBuiltinNode { @Specialization - public PZip zip(PythonClass cls, Object[] args, + public PZip zip(LazyPythonClass cls, Object[] args, @Cached("create()") GetIteratorNode getIterator) { Object[] iterables = new Object[args.length]; for (int i = 0; i < args.length; i++) { @@ -1676,22 +1685,22 @@ public abstract static class FunctionNode extends PythonBuiltinNode { @Child private GetNameNode getNameNode; @Specialization - public PFunction function(PythonClass cls, PCode code, PDict globals, String name, @SuppressWarnings("unused") PNone defaultArgs, @SuppressWarnings("unused") PNone closure) { + public PFunction function(LazyPythonClass cls, PCode code, PDict globals, String name, @SuppressWarnings("unused") PNone defaultArgs, @SuppressWarnings("unused") PNone closure) { return factory().createFunction(name, getTypeName(cls), code.getArity(), code.getRootCallTarget(), globals, null); } @Specialization - public PFunction function(PythonClass cls, PCode code, PDict globals, String name, @SuppressWarnings("unused") PNone defaultArgs, PTuple closure) { + public PFunction function(LazyPythonClass cls, PCode code, PDict globals, String name, @SuppressWarnings("unused") PNone defaultArgs, PTuple closure) { return factory().createFunction(name, getTypeName(cls), code.getArity(), code.getRootCallTarget(), globals, (PCell[]) closure.getArray()); } @Specialization - public PFunction function(PythonClass cls, PCode code, PDict globals, String name, PTuple defaultArgs, @SuppressWarnings("unused") PNone closure) { + public PFunction function(LazyPythonClass cls, PCode code, PDict globals, String name, PTuple defaultArgs, @SuppressWarnings("unused") PNone closure) { return factory().createFunction(name, getTypeName(cls), code.getArity(), code.getRootCallTarget(), globals, defaultArgs.getArray(), null); } @Specialization - public PFunction function(PythonClass cls, PCode code, PDict globals, String name, PTuple defaultArgs, PTuple closure) { + public PFunction function(LazyPythonClass cls, PCode code, PDict globals, String name, PTuple defaultArgs, PTuple closure) { return factory().createFunction(name, getTypeName(cls), code.getArity(), code.getRootCallTarget(), globals, defaultArgs.getArray(), (PCell[]) closure.getArray()); } @@ -1752,7 +1761,7 @@ public Object type(Object cls, Object obj, PNone bases, PNone dict, PKeyword[] k } @Specialization - public Object type(VirtualFrame frame, PythonClass cls, String name, PTuple bases, PDict namespace, PKeyword[] kwds, + public Object type(VirtualFrame frame, AbstractPythonClass cls, String name, PTuple bases, PDict namespace, PKeyword[] kwds, @Cached("create()") GetClassNode getMetaclassNode, @Cached("create(__NEW__)") LookupInheritedAttributeNode getNewFuncNode, @Cached("create()") CallDispatchNode callNewFuncNode, @@ -1818,10 +1827,10 @@ private Object typeMetaclass(String name, PTuple bases, PDict namespace, Abstrac basesArray = new AbstractPythonClass[array.length]; for (int i = 0; i < array.length; i++) { // TODO: deal with non-class bases - if (!(array[i] instanceof PythonClass)) { + if (!(array[i] instanceof AbstractPythonClass)) { throw raise(NotImplementedError, "creating a class with non-class bases"); } else { - basesArray[i] = (PythonClass) array[i]; + basesArray[i] = (AbstractPythonClass) array[i]; } } } @@ -2013,7 +2022,7 @@ private ReadCallerFrameNode getReadCallerFrameNode() { return readCallerFrameNode; } - private void addNativeSlots(PythonClass pythonClass, PTuple slots) { + private void addNativeSlots(ManagedPythonClass pythonClass, PTuple slots) { if (callAddNativeSlotsNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); callAddNativeSlotsNode = insert(CExtNodes.PCallCapiFunction.create(NativeCAPISymbols.FUN_ADD_NATIVE_SLOTS)); @@ -2029,7 +2038,7 @@ private CastToListNode getCastToListNode() { return castToList; } - private boolean addDictIfNative(PythonClass pythonClass) { + private boolean addDictIfNative(ManagedPythonClass pythonClass) { boolean addedNewDict = false; if (pythonClass.needsNativeAllocation()) { for (Object cls : getMro(pythonClass)) { @@ -2057,7 +2066,7 @@ private boolean addDictIfNative(PythonClass pythonClass) { return addedNewDict; } - private AbstractPythonClass[] getMro(PythonClass pythonClass) { + private AbstractPythonClass[] getMro(AbstractPythonClass pythonClass) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -2065,7 +2074,7 @@ private AbstractPythonClass[] getMro(PythonClass pythonClass) { return getMroNode.execute(pythonClass); } - private AbstractPythonClass calculate_metaclass(PythonClass cls, PTuple bases, GetClassNode getMetaclassNode) { + private AbstractPythonClass calculate_metaclass(AbstractPythonClass cls, PTuple bases, GetClassNode getMetaclassNode) { AbstractPythonClass winner = cls; for (Object base : bases.getArray()) { AbstractPythonClass typ = getMetaclassNode.execute(base); @@ -2106,7 +2115,7 @@ public Object typeGeneric(VirtualFrame frame, Object cls, Object name, Object ba throw raise(TypeError, "type() argument 2 must be tuple, not %p", name); } else if (!(dict instanceof PDict)) { throw raise(TypeError, "type() argument 3 must be dict, not %p", name); - } else if (!(cls instanceof PythonClass)) { + } else if (!(cls instanceof LazyPythonClass)) { // TODO: this is actually allowed, deal with it throw raise(NotImplementedError, "creating a class with non-class metaclass"); } @@ -2157,17 +2166,16 @@ private CastToStringNode ensureCastToStringNode() { @Builtin(name = MODULE, minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3, constructsClass = PythonBuiltinClassType.PythonModule, isPublic = false) @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) - @SuppressWarnings("unused") public abstract static class ModuleNode extends PythonBuiltinNode { @Child WriteAttributeToObjectNode writeFile = WriteAttributeToObjectNode.create(); @Specialization - public PythonModule module(PythonClass cls, String name, PNone path) { + public PythonModule module(LazyPythonClass cls, String name, @SuppressWarnings("unused") PNone path) { return factory().createPythonModule(cls, name); } @Specialization - public PythonModule module(PythonClass cls, String name, String path) { + public PythonModule module(LazyPythonClass cls, String name, String path) { PythonModule module = factory().createPythonModule(cls, name); writeFile.execute(module, __FILE__, path); return module; @@ -2322,12 +2330,12 @@ public Object generator(Object args, Object kwargs) { @GenerateNodeFactory public abstract static class MethodTypeNode extends PythonTernaryBuiltinNode { @Specialization - Object method(PythonClass cls, Object self, PFunction func) { + Object method(LazyPythonClass cls, Object self, PFunction func) { return factory().createMethod(cls, self, func); } @Specialization(guards = "isPythonBuiltinClass(cls)") - Object methodGeneric(@SuppressWarnings("unused") PythonClass cls, Object self, PBuiltinFunction func) { + Object methodGeneric(@SuppressWarnings("unused") LazyPythonClass cls, Object self, PBuiltinFunction func) { return factory().createBuiltinMethod(self, func); } } @@ -2336,7 +2344,7 @@ Object methodGeneric(@SuppressWarnings("unused") PythonClass cls, Object self, P @GenerateNodeFactory public abstract static class BuiltinMethodTypeNode extends PythonBuiltinNode { @Specialization - Object method(PythonClass cls, Object self, PBuiltinFunction func) { + Object method(LazyPythonClass cls, Object self, PBuiltinFunction func) { return factory().createBuiltinMethod(cls, self, func); } } @@ -2363,7 +2371,7 @@ Object call() { @GenerateNodeFactory public abstract static class CodeTypeNode extends PythonBuiltinNode { @Specialization - Object call(PythonClass cls, int argcount, int kwonlyargcount, + Object call(LazyPythonClass cls, int argcount, int kwonlyargcount, int nlocals, int stacksize, int flags, String codestring, PTuple constants, PTuple names, PTuple varnames, Object filename, Object name, @@ -2378,7 +2386,7 @@ Object call(PythonClass cls, int argcount, int kwonlyargcount, } @Specialization - Object call(PythonClass cls, int argcount, int kwonlyargcount, + Object call(LazyPythonClass cls, int argcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PBytes codestring, PTuple constants, PTuple names, PTuple varnames, Object filename, Object name, @@ -2437,7 +2445,7 @@ Object call() { public abstract static class BaseExceptionNode extends PythonBuiltinNode { @SuppressWarnings("unused") @Specialization - Object call(PythonClass cls, Object[] varargs, PKeyword[] kwargs) { + Object call(LazyPythonClass cls, Object[] varargs, PKeyword[] kwargs) { return factory().createBaseException(cls, factory().createTuple(varargs)); } } @@ -2448,25 +2456,24 @@ public abstract static class MappingproxyNode extends PythonBuiltinNode { @Child private IsSequenceNode isMappingNode; @Specialization - Object doMapping(PythonClass klass, PHashingCollection obj) { + Object doMapping(LazyPythonClass klass, PHashingCollection obj) { return factory().createMappingproxy(klass, obj.getDictStorage()); } @Specialization(guards = {"isMapping(obj)", "!isBuiltinMapping(obj)"}) - Object doMapping(PythonClass klass, PythonObject obj, + Object doMapping(LazyPythonClass klass, PythonObject obj, @Cached("create()") HashingStorageNodes.InitNode initNode) { return factory().createMappingproxy(klass, initNode.execute(obj, PKeyword.EMPTY_KEYWORDS)); } @Specialization(guards = "isNoValue(none)") @SuppressWarnings("unused") - Object doMissing(PythonClass klass, PNone none) { + Object doMissing(LazyPythonClass klass, PNone none) { throw raise(TypeError, "mappingproxy() missing required argument 'mapping' (pos 1)"); } @Specialization(guards = {"!isMapping(obj)", "!isNoValue(obj)"}) - @SuppressWarnings("unused") - Object doInvalid(PythonClass klass, Object obj) { + Object doInvalid(@SuppressWarnings("unused") LazyPythonClass klass, Object obj) { throw raise(TypeError, "mappingproxy() argument must be a mapping, not %p", obj); } @@ -2486,7 +2493,6 @@ protected boolean isMapping(Object o) { @Builtin(name = "getset_descriptor", constructsClass = PythonBuiltinClassType.GetSetDescriptor, isPublic = false, fixedNumOfPositionalArgs = 1, keywordArguments = {"fget", "fset", "name", "owner"}) @GenerateNodeFactory - @SuppressWarnings("unused") public abstract static class GetSetDescriptorNode extends PythonBuiltinNode { private void denyInstantiationAfterInitialization() { if (getCore().isInitialized()) { @@ -2496,21 +2502,22 @@ private void denyInstantiationAfterInitialization() { @Specialization(guards = {"!isNoValue(get)", "!isNoValue(set)"}) @TruffleBoundary - Object call(PythonClass getSetClass, Object get, Object set, String name, PythonClass owner) { + Object call(@SuppressWarnings("unused") LazyPythonClass getSetClass, Object get, Object set, String name, AbstractPythonClass owner) { denyInstantiationAfterInitialization(); return factory().createGetSetDescriptor(get, set, name, owner); } @Specialization(guards = {"!isNoValue(get)", "isNoValue(set)"}) @TruffleBoundary - Object call(PythonClass getSetClass, Object get, PNone set, String name, PythonClass owner) { + Object call(@SuppressWarnings("unused") LazyPythonClass getSetClass, Object get, @SuppressWarnings("unused") PNone set, String name, AbstractPythonClass owner) { denyInstantiationAfterInitialization(); return factory().createGetSetDescriptor(get, null, name, owner); } @Specialization(guards = {"isNoValue(get)", "isNoValue(set)"}) @TruffleBoundary - Object call(PythonClass getSetClass, PNone get, PNone set, String name, PythonClass owner) { + @SuppressWarnings("unused") + Object call(LazyPythonClass getSetClass, PNone get, PNone set, String name, AbstractPythonClass owner) { denyInstantiationAfterInitialization(); return factory().createGetSetDescriptor(null, null, name, owner); } @@ -2520,37 +2527,38 @@ Object call(PythonClass getSetClass, PNone get, PNone set, String name, PythonCl // slice(start, stop[, step]) @Builtin(name = "slice", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 4, constructsClass = PythonBuiltinClassType.PSlice) @GenerateNodeFactory - @SuppressWarnings("unused") public abstract static class CreateSliceNode extends PythonBuiltinNode { @Specialization(guards = {"isNoValue(second)", "isNoValue(third)"}) - Object sliceStop(PythonClass cls, int first, PNone second, PNone third) { + @SuppressWarnings("unused") + Object sliceStop(LazyPythonClass cls, int first, PNone second, PNone third) { return factory().createSlice(MISSING_INDEX, first, MISSING_INDEX); } @Specialization(guards = "isNoValue(third)") - Object sliceStart(PythonClass cls, int first, int second, PNone third) { + Object sliceStart(@SuppressWarnings("unused") LazyPythonClass cls, int first, int second, @SuppressWarnings("unused") PNone third) { return factory().createSlice(first, second, MISSING_INDEX); } @Specialization - Object slice(PythonClass cls, int first, int second, int third) { + Object slice(@SuppressWarnings("unused") LazyPythonClass cls, int first, int second, int third) { return factory().createSlice(first, second, third); } @Specialization(guards = "isNoValue(third)") - Object slice(PythonClass cls, Object first, Object second, PNone third, + Object slice(@SuppressWarnings("unused") LazyPythonClass cls, Object first, Object second, @SuppressWarnings("unused") PNone third, @Cached("create()") SliceLiteralNode sliceNode) { return sliceNode.execute(first, second, MISSING_INDEX); } @Specialization(guards = {"isNoValue(second)", "isNoValue(third)"}) - Object slice(PythonClass cls, Object first, PNone second, PNone third, + @SuppressWarnings("unused") + Object slice(LazyPythonClass cls, Object first, PNone second, PNone third, @Cached("create()") SliceLiteralNode sliceNode) { return sliceNode.execute(MISSING_INDEX, first, MISSING_INDEX); } @Specialization(guards = {"!isNoValue(stop)", "!isNoValue(step)"}) - Object slice(PythonClass cls, Object start, Object stop, Object step, + Object slice(@SuppressWarnings("unused") LazyPythonClass cls, Object start, Object stop, Object step, @Cached("create()") SliceLiteralNode sliceNode) { return sliceNode.execute(start, stop, step); } @@ -2563,12 +2571,12 @@ public abstract static class BufferNode extends PythonBuiltinNode { @Child private LookupInheritedAttributeNode getSetItemNode; @Specialization(guards = "isNoValue(readOnly)") - protected PBuffer construct(PythonClass cls, Object delegate, @SuppressWarnings("unused") PNone readOnly) { + protected PBuffer construct(LazyPythonClass cls, Object delegate, @SuppressWarnings("unused") PNone readOnly) { return factory().createBuffer(cls, delegate, !hasSetItem(delegate)); } @Specialization - protected PBuffer construct(PythonClass cls, Object delegate, boolean readOnly) { + protected PBuffer construct(LazyPythonClass cls, Object delegate, boolean readOnly) { return factory().createBuffer(cls, delegate, readOnly); } @@ -2591,7 +2599,7 @@ public boolean hasSetItem(Object object) { @GenerateNodeFactory public abstract static class MemoryViewNode extends PythonBuiltinNode { @Specialization - public PMemoryView doGeneric(PythonClass cls, Object value) { + public PMemoryView doGeneric(LazyPythonClass cls, Object value) { return factory().createMemoryView(cls, value); } } @@ -2601,7 +2609,7 @@ public PMemoryView doGeneric(PythonClass cls, Object value) { @GenerateNodeFactory public abstract static class SuperInitNode extends PythonTernaryBuiltinNode { @Specialization - Object doObjectIndirect(PythonClass self, @SuppressWarnings("unused") Object type, @SuppressWarnings("unused") Object object) { + Object doObjectIndirect(LazyPythonClass self, @SuppressWarnings("unused") Object type, @SuppressWarnings("unused") Object object) { return factory().createSuperObject(self); } } @@ -2629,7 +2637,7 @@ Object doObjectIndirect(PythonClass self, @SuppressWarnings("unused") Object typ @GenerateNodeFactory public abstract static class ClassmethodNode extends PythonBinaryBuiltinNode { @Specialization - Object doObjectIndirect(PythonClass self, @SuppressWarnings("unused") Object callable) { + Object doObjectIndirect(LazyPythonClass self, @SuppressWarnings("unused") Object callable) { return factory().createClassmethod(self); } } @@ -2638,7 +2646,7 @@ Object doObjectIndirect(PythonClass self, @SuppressWarnings("unused") Object cal @GenerateNodeFactory public abstract static class StaticmethodNode extends PythonBinaryBuiltinNode { @Specialization - Object doObjectIndirect(PythonClass self, @SuppressWarnings("unused") Object callable) { + Object doObjectIndirect(LazyPythonClass self, @SuppressWarnings("unused") Object callable) { return factory().createStaticmethod(self); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index d74742725e..372c719143 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -1038,7 +1038,7 @@ private boolean isInstanceCheckInternal(Object instance, Object cls) { public abstract boolean executeWith(Object instance, Object cls); @Specialization - public boolean isInstance(Object instance, PythonClass cls, + public boolean isInstance(Object instance, AbstractPythonClass cls, @Cached("create()") TypeNodes.IsSameTypeNode isSameTypeNode, @Cached("create()") IsSubtypeNode isSubtypeNode) { AbstractPythonClass instanceClass = getClassNode.execute(instance); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index c68a48dff6..1f2ae5401e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -99,6 +99,7 @@ import com.oracle.graal.python.builtins.objects.module.PythonModule; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.tuple.PTuple; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; @@ -642,7 +643,7 @@ public abstract static class ScandirIterNode extends PythonBinaryBuiltinNode { private final BranchProfile gotException = BranchProfile.create(); @Specialization - Object doit(PythonClass cls, String path) { + Object doit(LazyPythonClass cls, String path) { try { TruffleFile file = getContext().getEnv().getTruffleFile(path); return factory().createScandirIterator(cls, path, file.newDirectoryStream()); @@ -660,7 +661,7 @@ public abstract static class DirEntryNode extends PythonTernaryBuiltinNode { private final BranchProfile gotException = BranchProfile.create(); @Specialization - Object doit(PythonClass cls, String name, String path) { + Object doit(LazyPythonClass cls, String name, String path) { try { TruffleFile dir = getContext().getEnv().getTruffleFile(path); TruffleFile file = dir.resolve(name); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/RandomModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/RandomModuleBuiltins.java index 293efc4ffd..420f8fc236 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/RandomModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/RandomModuleBuiltins.java @@ -32,7 +32,7 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.random.PRandom; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; @@ -55,7 +55,7 @@ abstract static class PRandomNode extends PythonBuiltinNode { @Child LookupAndCallBinaryNode setSeed = LookupAndCallBinaryNode.create("seed"); @Specialization - PRandom random(PythonClass cls, Object seed) { + PRandom random(LazyPythonClass cls, Object seed) { PRandom random = factory().createRandom(cls); setSeed.executeObject(random, seed); return random; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SocketModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SocketModuleBuiltins.java index f274c6674c..e9b3466c51 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SocketModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SocketModuleBuiltins.java @@ -50,7 +50,7 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.socket.PSocket; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.runtime.exception.PythonErrorType; @@ -71,27 +71,27 @@ protected List> getNodeFa @GenerateNodeFactory public abstract static class SocketNode extends PythonBuiltinNode { @Specialization(guards = {"isNoValue(family)", "isNoValue(type)", "isNoValue(proto)", "isNoValue(fileno)"}) - Object socket(PythonClass cls, @SuppressWarnings("unused") PNone family, @SuppressWarnings("unused") PNone type, @SuppressWarnings("unused") PNone proto, + Object socket(LazyPythonClass cls, @SuppressWarnings("unused") PNone family, @SuppressWarnings("unused") PNone type, @SuppressWarnings("unused") PNone proto, @SuppressWarnings("unused") PNone fileno) { return createSocketInternal(cls, PSocket.AF_INET, PSocket.SOCK_STREAM, 0); } @Specialization(guards = {"isNoValue(type)", "isNoValue(proto)", "isNoValue(fileno)"}) - Object socket(PythonClass cls, int family, @SuppressWarnings("unused") PNone type, @SuppressWarnings("unused") PNone proto, @SuppressWarnings("unused") PNone fileno) { + Object socket(LazyPythonClass cls, int family, @SuppressWarnings("unused") PNone type, @SuppressWarnings("unused") PNone proto, @SuppressWarnings("unused") PNone fileno) { return createSocketInternal(cls, family, PSocket.SOCK_STREAM, 0); } @Specialization(guards = {"isNoValue(proto)", "isNoValue(fileno)"}) - Object socket(PythonClass cls, int family, int type, @SuppressWarnings("unused") PNone proto, @SuppressWarnings("unused") PNone fileno) { + Object socket(LazyPythonClass cls, int family, int type, @SuppressWarnings("unused") PNone proto, @SuppressWarnings("unused") PNone fileno) { return createSocketInternal(cls, family, type, 0); } @Specialization(guards = {"isNoValue(fileno)"}) - Object socket(PythonClass cls, int family, int type, int proto, @SuppressWarnings("unused") PNone fileno) { + Object socket(LazyPythonClass cls, int family, int type, int proto, @SuppressWarnings("unused") PNone fileno) { return createSocketInternal(cls, family, type, proto); } - private Object createSocketInternal(PythonClass cls, int family, int type, int proto) { + private Object createSocketInternal(LazyPythonClass cls, int family, int type, int proto) { if (getContext().getEnv().isNativeAccessAllowed()) { return factory().createSocket(cls, family, type, proto); } else { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java index 091d84ad4e..9b044c226e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java @@ -54,7 +54,7 @@ import com.oracle.graal.python.builtins.objects.thread.PLock; import com.oracle.graal.python.builtins.objects.thread.PRLock; import com.oracle.graal.python.builtins.objects.thread.PThread; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.argument.keywords.ExecuteKeywordStarargsNode; import com.oracle.graal.python.nodes.argument.positional.ExecutePositionalStarargsNode; import com.oracle.graal.python.nodes.call.CallNode; @@ -91,7 +91,7 @@ abstract static class GetTimeoutMaxConstNode extends PythonBuiltinNode { @GenerateNodeFactory abstract static class ConstructLockNode extends PythonUnaryBuiltinNode { @Specialization - PLock construct(PythonClass cls) { + PLock construct(LazyPythonClass cls) { return factory().createLock(cls); } } @@ -100,7 +100,7 @@ PLock construct(PythonClass cls) { @GenerateNodeFactory abstract static class ConstructRLockNode extends PythonUnaryBuiltinNode { @Specialization - PRLock construct(PythonClass cls) { + PRLock construct(LazyPythonClass cls) { return factory().createRLock(cls); } } @@ -157,7 +157,7 @@ long getStackSize(long stackSize) { @GenerateNodeFactory abstract static class StartNewThreadNode extends PythonBuiltinNode { @Specialization - long start(VirtualFrame frame, PythonClass cls, Object callable, Object args, Object kwargs, + long start(VirtualFrame frame, LazyPythonClass cls, Object callable, Object args, Object kwargs, @Cached("create()") CallNode callNode, @Cached("create()") ExecutePositionalStarargsNode getArgsNode, @Cached("create()") ExecuteKeywordStarargsNode getKwArgsNode) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index f6399e470e..9c21b0f495 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -42,14 +42,8 @@ import static com.oracle.graal.python.builtins.PythonBuiltinClassType.IndexError; import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError; -import static com.oracle.graal.python.builtins.objects.cext.NativeMemberNames.TP_BASICSIZE; -import static com.oracle.graal.python.builtins.objects.cext.NativeMemberNames.TP_DICTOFFSET; -import static com.oracle.graal.python.builtins.objects.cext.NativeMemberNames.TP_DOC; -import static com.oracle.graal.python.builtins.objects.cext.NativeMemberNames.TP_ITEMSIZE; -import static com.oracle.graal.python.builtins.objects.cext.NativeMemberNames.TP_NAME; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASICSIZE__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICTOFFSET__; -import static com.oracle.graal.python.nodes.SpecialAttributeNames.__ITEMSIZE__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__; import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError; @@ -63,7 +57,6 @@ import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; import java.util.List; -import java.util.Set; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.Builtin; @@ -105,7 +98,6 @@ import com.oracle.graal.python.builtins.objects.code.PCode; import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; -import com.oracle.graal.python.builtins.objects.common.PHashingCollection; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.CastToByteNode; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NormalizeIndexNode; @@ -130,9 +122,10 @@ import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; -import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; @@ -326,7 +319,7 @@ Object runWithoutCWrapper(PBuiltinFunction descriptor, Object self) { abstract static class CreateFunctionNode extends PythonBuiltinNode { @Specialization(guards = "isNoValue(cwrapper)") @TruffleBoundary - PBuiltinFunction runWithoutCWrapper(String name, TruffleObject callable, @SuppressWarnings("unused") PNone cwrapper, PythonClass type) { + PBuiltinFunction runWithoutCWrapper(String name, TruffleObject callable, @SuppressWarnings("unused") PNone cwrapper, LazyPythonClass type) { CompilerDirectives.transferToInterpreter(); RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(new ExternalFunctionNode(getRootNode().getLanguage(PythonLanguage.class), name, null, callable)); return factory().createBuiltinFunction(name, type, createArity(name), callTarget); @@ -350,7 +343,7 @@ PBuiltinFunction runWithoutCWrapper(String name, TruffleObject callable, Truffle @Specialization(guards = "!isNoValue(cwrapper)") @TruffleBoundary - PBuiltinFunction run(String name, TruffleObject callable, TruffleObject cwrapper, PythonClass type) { + PBuiltinFunction run(String name, TruffleObject callable, TruffleObject cwrapper, LazyPythonClass type) { CompilerDirectives.transferToInterpreter(); RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(new ExternalFunctionNode(getRootNode().getLanguage(PythonLanguage.class), name, cwrapper, callable)); return factory().createBuiltinFunction(name, type, createArity(name), callTarget); @@ -372,7 +365,7 @@ Object run(PNone typ, PNone val, PNone tb) { } @Specialization - Object run(@SuppressWarnings("unused") PythonClass typ, PBaseException val, @SuppressWarnings("unused") PTraceback tb) { + Object run(@SuppressWarnings("unused") LazyPythonClass typ, PBaseException val, @SuppressWarnings("unused") PTraceback tb) { val.reifyException(); if (val.getException() != null) { getContext().setCurrentException(val.getException()); @@ -432,7 +425,7 @@ Object run(PNone typ, PNone val, PNone tb) { } @Specialization - Object run(@SuppressWarnings("unused") PythonClass typ, PBaseException val, @SuppressWarnings("unused") PTraceback tb) { + Object run(@SuppressWarnings("unused") LazyPythonClass typ, PBaseException val, @SuppressWarnings("unused") PTraceback tb) { val.reifyException(); if (val.getException() != null) { getContext().setCaughtException(val.getException()); @@ -454,7 +447,7 @@ abstract static class PyErrDisplay extends PythonBuiltinNode { @Specialization @SuppressWarnings("unused") - Object run(PythonClass typ, PBaseException val, PTraceback tb) { + Object run(LazyPythonClass typ, PBaseException val, PTraceback tb) { if (val.getException() != null) { ExceptionUtils.printPythonLikeStackTrace(val.getException()); } @@ -698,7 +691,7 @@ abstract static class PyTruffle_Type_SlotsNode extends NativeBuiltin { * */ @Specialization - Object slots(Object module, PythonClass pythonClass, + Object slots(Object module, LazyPythonClass pythonClass, @Cached("create(__SLOTS__)") LookupAttributeInMRONode lookupSlotsNode) { Object execute = lookupSlotsNode.execute(pythonClass); if (execute != PNone.NO_VALUE) { @@ -1508,7 +1501,7 @@ abstract static class PyTruffle_Set_SulongType extends NativeBuiltin { @Specialization Object doPythonObject(PythonClassNativeWrapper klass, Object ptr) { - ((PythonClass) klass.getPythonObject()).setSulongType(ptr); + ((ManagedPythonClass) klass.getPythonObject()).setSulongType(ptr); return ptr; } } @@ -1525,7 +1518,7 @@ Object doNativeWrapper(PythonClassNativeWrapper nativeWrapper, Object getBufferP } @Specialization - Object doPythonObject(PythonClass obj, Object getBufferProc, Object releaseBufferProc) { + Object doPythonObject(ManagedPythonClass obj, Object getBufferProc, Object releaseBufferProc) { return doNativeWrapper(obj.getNativeWrapper(), getBufferProc, releaseBufferProc); } } @@ -1597,17 +1590,17 @@ Object doUnpackLongOvf(Object start, Object stop, Object step, Object lengthObj, @GenerateNodeFactory public abstract static class GetSetDescriptorNode extends PythonBuiltinNode { @Specialization(guards = {"!isNoValue(get)", "!isNoValue(set)"}) - Object call(Object get, Object set, String name, PythonClass owner) { + Object call(Object get, Object set, String name, LazyPythonClass owner) { return factory().createGetSetDescriptor(get, set, name, owner); } @Specialization(guards = {"!isNoValue(get)", "isNoValue(set)"}) - Object call(Object get, @SuppressWarnings("unused") PNone set, String name, PythonClass owner) { + Object call(Object get, @SuppressWarnings("unused") PNone set, String name, LazyPythonClass owner) { return factory().createGetSetDescriptor(get, null, name, owner); } @Specialization(guards = {"isNoValue(get)", "!isNoValue(set)"}) - Object call(@SuppressWarnings("unused") PNone get, Object set, String name, PythonClass owner) { + Object call(@SuppressWarnings("unused") PNone get, Object set, String name, LazyPythonClass owner) { return factory().createGetSetDescriptor(null, set, name, owner); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java index 86b6d19992..26c20072ce 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java @@ -54,8 +54,8 @@ import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.referencetype.PReferenceType; import com.oracle.graal.python.builtins.objects.referencetype.PReferenceType.WeakRefStorage; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.runtime.AsyncHandler; @@ -126,12 +126,12 @@ public abstract static class ReferenceTypeNode extends PythonBuiltinNode { @Child ReadAttributeFromObjectNode readQueue = ReadAttributeFromObjectNode.create(); @Specialization - public PReferenceType refType(PythonClass cls, Object object, PNone none) { + public PReferenceType refType(LazyPythonClass cls, Object object, PNone none) { return factory().createReferenceType(cls, object, null, getWeakReferenceQueue()); } @Specialization - public PReferenceType refType(PythonClass cls, Object object, Object callback) { + public PReferenceType refType(LazyPythonClass cls, Object object, Object callback) { return factory().createReferenceType(cls, object, callback, getWeakReferenceQueue()); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZipImportModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZipImportModuleBuiltins.java index b51028380b..345d3d8515 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZipImportModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZipImportModuleBuiltins.java @@ -40,15 +40,15 @@ */ package com.oracle.graal.python.builtins.modules; -import com.oracle.graal.python.builtins.Builtin; import java.util.List; +import com.oracle.graal.python.builtins.Builtin; import com.oracle.graal.python.builtins.CoreFunctions; import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.module.PythonModule; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.zipimporter.PZipImporter; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; @@ -92,7 +92,7 @@ public void initialize(PythonCore core) { public abstract static class ZipImporterNode extends PythonBinaryBuiltinNode { @Specialization - public PZipImporter createNew(PythonClass cls, @SuppressWarnings("unused") Object path, + public PZipImporter createNew(LazyPythonClass cls, @SuppressWarnings("unused") Object path, @Cached("create()") ReadAttributeFromObjectNode readNode) { PythonModule module = getCore().lookupBuiltinModule(ZIPIMPORT_MODULE_NAME); return factory().createZipImporter(cls, (PDict) readNode.execute(module, ZIP_DIRECTORY_CACHE_NAME)); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index fc9527f12b..88d7762d02 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -76,7 +76,6 @@ import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.PGuards; @@ -848,17 +847,17 @@ public static FromCharPointerNode create() { public abstract static class GetNativeClassNode extends CExtBaseNode { - @Child PCallNativeNode callGetObTypeNode; - @Child ToJavaNode toJavaNode; + @Child private PCallCapiFunction callGetObTypeNode; + @Child private ToJavaNode toJavaNode; @CompilationFinal private TruffleObject func; - public abstract PythonClass execute(PythonNativeObject object); + public abstract PythonNativeClass execute(PythonAbstractObject object); @Specialization(guards = "object == cachedObject", limit = "1") - PythonClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeObject object, + PythonNativeClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeObject object, @SuppressWarnings("unused") @Cached("object") PythonNativeObject cachedObject, - @Cached("getNativeClass(cachedObject)") PythonClass cachedClass) { + @Cached("getNativeClass(cachedObject)") PythonNativeClass cachedClass) { // TODO: (tfel) is this really something we can do? It's so rare for this class to // change that it shouldn't be worth the effort, but in native code, anything can // happen. OTOH, CPython also has caches that can become invalid when someone just goes @@ -867,10 +866,36 @@ PythonClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeObject } @Specialization - PythonClass getNativeClass(PythonNativeObject object) { + PythonNativeClass getNativeClass(PythonNativeObject object) { // do not convert wrap 'object.object' since that is really the native pointer object - Object[] args = new Object[]{object.object}; - return (PythonClass) getToJavaNode().execute(getCallGetObTypeNode().execute(getObTypeFunction(), args)); + return (PythonNativeClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.object)); + } + + @Specialization(guards = "object == cachedObject", limit = "1") + PythonNativeClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeClass object, + @SuppressWarnings("unused") @Cached("object") PythonNativeClass cachedObject, + @Cached("getNativeClass(cachedObject)") PythonNativeClass cachedClass) { + // TODO: (tfel) is this really something we can do? It's so rare for this class to + // change that it shouldn't be worth the effort, but in native code, anything can + // happen. OTOH, CPython also has caches that can become invalid when someone just goes + // and changes the ob_type of an object. + return cachedClass; + } + + @Specialization + PythonNativeClass getNativeClass(PythonNativeClass object) { + // do not convert wrap 'object.object' since that is really the native pointer object + return (PythonNativeClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.getPtr())); + } + + @TruffleBoundary + public static PythonNativeClass doSlowPath(PythonNativeObject object) { + return (PythonNativeClass) ToJavaNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.object), true); + } + + @TruffleBoundary + public static PythonNativeClass doSlowPath(PythonNativeClass object) { + return (PythonNativeClass) ToJavaNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.getPtr()), true); } private ToJavaNode getToJavaNode() { @@ -881,20 +906,13 @@ private ToJavaNode getToJavaNode() { return toJavaNode; } - private PCallNativeNode getCallGetObTypeNode() { + private PCallCapiFunction getCallGetObTypeNode() { if (callGetObTypeNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - callGetObTypeNode = insert(PCallNativeNode.create()); - } - return callGetObTypeNode; - } + callGetObTypeNode = insert(PCallCapiFunction.create(NativeCAPISymbols.FUN_GET_OB_TYPE)); - TruffleObject getObTypeFunction() { - if (func == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - func = importCAPISymbol(NativeCAPISymbols.FUN_GET_OB_TYPE); } - return func; + return callGetObTypeNode; } public static GetNativeClassNode create() { @@ -1618,29 +1636,40 @@ public static GetObjectDictNode create() { } } - public static class GetTypeDictNode extends GetNativeDictNode { + public static class GetTypeMemberNode extends GetNativeDictNode { @Child private ToSulongNode toSulong; - @Child private ToJavaNode toJava; + @Child private AsPythonObjectNode toJava; @Child private PCallCapiFunction callGetTpDictNode; + private GetTypeMemberNode(String memberName) { + String getterFuncName = "get_" + memberName; + if (!NativeCAPISymbols.isValid(getterFuncName)) { + throw new IllegalArgumentException("invalid native member getter function " + getterFuncName); + } + callGetTpDictNode = PCallCapiFunction.create(getterFuncName); + } + @Override public Object execute(Object self) { - if (callGetTpDictNode == null) { + if (toSulong == null || toJava == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - callGetTpDictNode = PCallCapiFunction.create(NativeCAPISymbols.FUN_PY_OBJECT_GENERIC_GET_DICT); toSulong = insert(ToSulongNode.create()); - toJava = insert(ToJavaNode.create()); + toJava = insert(AsPythonObjectNode.create()); } return toJava.execute(callGetTpDictNode.call(toSulong.execute(self))); } @TruffleBoundary - public static Object doSlowPath(Object self) { - return ToJavaNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_PY_OBJECT_GENERIC_GET_DICT, ToSulongNode.doSlowPath(self)), true); + public static Object doSlowPath(Object self, String memberName) { + String getterFuncName = "get_" + memberName; + if (!NativeCAPISymbols.isValid(getterFuncName)) { + throw new IllegalArgumentException("invalid native member getter function " + getterFuncName); + } + return AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(getterFuncName, ToSulongNode.doSlowPath(self))); } - public static GetTypeDictNode create() { - return new GetTypeDictNode(); + public static GetTypeMemberNode create(String typeMember) { + return new GetTypeMemberNode(typeMember); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java index bdb61ef8ff..ad8c0d521c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java @@ -40,6 +40,12 @@ */ package com.oracle.graal.python.builtins.objects.cext; +import java.lang.reflect.Field; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.ExplodeLoop.LoopExplosionKind; + public abstract class NativeCAPISymbols { public static final String FUN_NATIVE_POINTER_TO_JAVA = "native_pointer_to_java"; @@ -54,6 +60,8 @@ public abstract class NativeCAPISymbols { public static final String FUN_PY_TRUFFLE_CSTR_TO_STRING = "PyTruffle_CstrToString"; public static final String FUN_PY_FLOAT_AS_DOUBLE = "truffle_read_ob_fval"; public static final String FUN_GET_OB_TYPE = "get_ob_type"; + public static final String FUN_GET_TP_DICT = "get_tp_dict"; + public static final String FUN_GET_TP_BASES = "get_tp_bases"; public static final String FUN_DEREF_HANDLE = "truffle_deref_handle_for_managed"; public static final String FUN_GET_BYTE_ARRAY_TYPE_ID = "get_byte_array_typeid"; public static final String FUN_GET_PTR_ARRAY_TYPE_ID = "get_ptr_array_typeid"; @@ -68,4 +76,28 @@ public abstract class NativeCAPISymbols { public static final String FUN_GET_THREAD_STATE_TYPE_ID = "get_thread_state_typeid"; public static final String FUN_ADD_NATIVE_SLOTS = "PyTruffle_Type_AddSlots"; + @CompilationFinal(dimensions = 1) public static final String[] values; + static { + Field[] declaredFields = NativeCAPISymbols.class.getDeclaredFields(); + values = new String[declaredFields.length - 1]; // omit the values field + for (int i = 0; i < declaredFields.length; i++) { + Field s = declaredFields[i]; + if (s.getType() == String.class) { + try { + values[i] = (String) s.get(NativeMemberNames.class); + } catch (IllegalArgumentException | IllegalAccessException e) { + } + } + } + } + + @ExplodeLoop(kind = LoopExplosionKind.FULL_UNROLL) + public static boolean isValid(String name) { + for (int i = 0; i < values.length; i++) { + if (values[i].equals(name)) { + return true; + } + } + return false; + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java index c08bded4fb..89ac910702 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java @@ -56,6 +56,7 @@ public final class NativeMemberNames { public static final String TP_FLAGS = "tp_flags"; public static final String TP_NAME = "tp_name"; public static final String TP_BASE = "tp_base"; + public static final String TP_BASES = "tp_bases"; public static final String TP_BASICSIZE = "tp_basicsize"; public static final String TP_ITEMSIZE = "tp_itemsize"; public static final String TP_DICTOFFSET = "tp_dictoffset"; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java index 01d5dae606..608a5137a5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java @@ -278,8 +278,8 @@ public static PrimitiveNativeWrapper createDouble(double val) { } /** - * Used to wrap {@link PythonClass} when used in native code. This wrapper mimics the correct - * shape of the corresponding native type {@code struct _typeobject}. + * Used to wrap {@link ManagedPythonClass} when used in native code. This wrapper mimics the + * correct shape of the corresponding native type {@code struct _typeobject}. */ public static class PythonClassNativeWrapper extends PythonObjectNativeWrapper { private final CStringWrapper nameWrapper; @@ -328,13 +328,13 @@ public String toString() { } /** - * Used to wrap {@link PythonClass} just for the time when a natively defined type is processed - * in {@code PyType_Ready} and we need to pass the mirroring managed class to native to marry - * these two objects. + * Used to wrap {@link ManagedPythonClass} just for the time when a natively defined type is + * processed in {@code PyType_Ready} and we need to pass the mirroring managed class to native + * to marry these two objects. */ public static class PythonClassInitNativeWrapper extends PythonObjectNativeWrapper { - public PythonClassInitNativeWrapper(PythonClass object) { + public PythonClassInitNativeWrapper(ManagedPythonClass object) { super(object); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java index 5c99887c0e..3f75ecb740 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java @@ -56,7 +56,7 @@ import com.oracle.graal.python.builtins.objects.exception.PBaseException; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.object.GetClassNode; @@ -256,7 +256,7 @@ PNone doResetCaughtException(@SuppressWarnings("unused") String key, @SuppressWa } @Specialization(guards = "eq(key, CUR_EXC_TYPE)") - PythonClass doCurExcType(@SuppressWarnings("unused") String key, PythonClass value) { + LazyPythonClass doCurExcType(@SuppressWarnings("unused") String key, LazyPythonClass value) { setCurrentException(factory().createBaseException(value)); return value; } @@ -274,7 +274,7 @@ PTraceback doCurExcTraceback(@SuppressWarnings("unused") String key, PTraceback } @Specialization(guards = "eq(key, EXC_TYPE)") - PythonClass doExcType(@SuppressWarnings("unused") String key, PythonClass value) { + LazyPythonClass doExcType(@SuppressWarnings("unused") String key, LazyPythonClass value) { setCaughtException(factory().createBaseException(value)); return value; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java index f52f341e08..32e0d3724d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java @@ -41,7 +41,7 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonNativeWrapper; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.TruffleObject; @@ -50,7 +50,7 @@ */ public class PyNumberMethodsWrapper extends PythonNativeWrapper { - public PyNumberMethodsWrapper(PythonClass delegate) { + public PyNumberMethodsWrapper(ManagedPythonClass delegate) { super(delegate); } @@ -63,7 +63,7 @@ public ForeignAccess getForeignAccess() { return PyNumberMethodsWrapperMRForeign.ACCESS; } - public PythonClass getPythonClass() { - return (PythonClass) getDelegate(); + public ManagedPythonClass getPythonClass() { + return (ManagedPythonClass) getDelegate(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java index f6287d5232..7bb867be77 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java @@ -57,7 +57,7 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToSulongNode; import com.oracle.graal.python.builtins.objects.cext.PyNumberMethodsWrapperMRFactory.ReadMethodNodeGen; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.truffle.api.CompilerDirectives; @@ -78,7 +78,7 @@ abstract static class ReadNode extends Node { public Object access(PyNumberMethodsWrapper object, String key) { // translate key to attribute name - PythonClass delegate = object.getPythonClass(); + ManagedPythonClass delegate = object.getPythonClass(); return getToSulongNode().execute(readMethodNode.execute(delegate, key)); } @@ -93,10 +93,10 @@ private ToSulongNode getToSulongNode() { abstract static class ReadMethodNode extends PNodeWithContext { - public abstract Object execute(PythonClass clazz, String key); + public abstract Object execute(ManagedPythonClass clazz, String key); @Specialization(limit = "99", guards = {"eq(cachedKey, key)"}) - Object getMethod(PythonClass clazz, @SuppressWarnings("unused") String key, + Object getMethod(ManagedPythonClass clazz, @SuppressWarnings("unused") String key, @Cached("key") @SuppressWarnings("unused") String cachedKey, @Cached("createLookupNode(cachedKey)") LookupAttributeInMRONode lookupNode) { if (lookupNode != null) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java index a86335bb83..e5c654d713 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java @@ -41,7 +41,7 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonNativeWrapper; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.TruffleObject; @@ -50,7 +50,7 @@ */ public class PySequenceMethodsWrapper extends PythonNativeWrapper { - public PySequenceMethodsWrapper(PythonClass delegate) { + public PySequenceMethodsWrapper(ManagedPythonClass delegate) { super(delegate); } @@ -63,7 +63,7 @@ public ForeignAccess getForeignAccess() { return PySequenceMethodsWrapperMRForeign.ACCESS; } - public PythonClass getPythonClass() { - return (PythonClass) getDelegate(); + public ManagedPythonClass getPythonClass() { + return (ManagedPythonClass) getDelegate(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java index 9167fe052b..df052987f2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java @@ -41,7 +41,7 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToSulongNode; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.truffle.api.CompilerDirectives; @@ -60,7 +60,7 @@ abstract static class ReadNode extends Node { @Child private ToSulongNode toSulongNode; public Object access(PySequenceMethodsWrapper object, String key) { - PythonClass delegate = object.getPythonClass(); + ManagedPythonClass delegate = object.getPythonClass(); Object result; switch (key) { case NativeMemberNames.SQ_REPEAT: diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index be44e0a63d..f6c29d8653 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -411,19 +411,19 @@ Object doObFval(Object object, @SuppressWarnings("unused") String key, } @Specialization(guards = "eq(TP_FLAGS, key)") - long doTpFlags(PythonClass object, @SuppressWarnings("unused") String key, + long doTpFlags(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create()") GetTypeFlagsNode getTypeFlagsNode) { return getTypeFlagsNode.execute(object); } @Specialization(guards = "eq(TP_NAME, key)") - Object doTpName(PythonClass object, @SuppressWarnings("unused") String key) { + Object doTpName(ManagedPythonClass object, @SuppressWarnings("unused") String key) { // return a C string wrapper that really allocates 'char*' on TO_NATIVE return object.getNativeWrapper().getNameWrapper(); } @Specialization(guards = "eq(TP_BASE, key)") - Object doTpBase(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpBase(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create()") GetSuperClassNode getSuperClassNode, @Cached("createBinaryProfile()") ConditionProfile profile) { LazyPythonClass superClass = getSuperClassNode.execute(object); @@ -434,20 +434,20 @@ Object doTpBase(PythonClass object, @SuppressWarnings("unused") String key, } @Specialization(guards = "eq(TP_ALLOC, key)") - Object doTpAlloc(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpAlloc(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__ALLOC__)") LookupAttributeInMRONode getAllocNode) { Object result = getAllocNode.execute(object); return getToSulongNode().execute(result); } @Specialization(guards = "eq(TP_AS_NUMBER, key)") - Object doTpAsNumber(PythonClass object, @SuppressWarnings("unused") String key) { + Object doTpAsNumber(ManagedPythonClass object, @SuppressWarnings("unused") String key) { // TODO check for type and return 'NULL' return new PyNumberMethodsWrapper(object); } @Specialization(guards = "eq(TP_AS_BUFFER, key)") - Object doTpAsBuffer(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpAsBuffer(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create()") IsSubtypeNode isSubtype, @Cached("create()") BranchProfile notBytes, @Cached("create()") BranchProfile notBytearray, @@ -479,7 +479,7 @@ Object doTpAsBuffer(PythonClass object, @SuppressWarnings("unused") String key, } @Specialization(guards = "eq(TP_AS_SEQUENCE, key)") - Object doTpAsSequence(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpAsSequence(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__LEN__)") LookupAttributeInMRONode getAttrNode) { if (getAttrNode.execute(object) != PNone.NO_VALUE) { return new PySequenceMethodsWrapper(object); @@ -489,25 +489,25 @@ Object doTpAsSequence(PythonClass object, @SuppressWarnings("unused") String key } @Specialization(guards = "eq(TP_NEW, key)") - Object doTpNew(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpNew(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__NEW__)") LookupAttributeInMRONode getAttrNode) { return ManagedMethodWrappers.createKeywords(getAttrNode.execute(object)); } @Specialization(guards = "eq(TP_HASH, key)") - Object doTpHash(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpHash(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__HASH__)") LookupAttributeInMRONode getHashNode) { return getToSulongNode().execute(getHashNode.execute(object)); } @Specialization(guards = "eq(TP_BASICSIZE, key)") - Object doTpBasicsize(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpBasicsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__BASICSIZE__)") LookupAttributeInMRONode getAttrNode) { return getAttrNode.execute(object); } @Specialization(guards = "eq(TP_ITEMSIZE, key)") - Object doTpItemsize(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpItemsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__ITEMSIZE__)") LookupAttributeInMRONode getAttrNode) { return getAttrNode.execute(object); } @@ -525,44 +525,44 @@ Object doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") Str } @Specialization(guards = "eq(TP_RICHCOMPARE, key)") - Object doTpRichcompare(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpRichcompare(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(RICHCMP)") LookupAttributeInMRONode getCmpNode) { return getToSulongNode().execute(getCmpNode.execute(object)); } @Specialization(guards = "eq(TP_SUBCLASSES, key)") - Object doTpSubclasses(@SuppressWarnings("unused") PythonClass object, @SuppressWarnings("unused") String key, + Object doTpSubclasses(@SuppressWarnings("unused") ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) { // TODO create dict view on subclasses set return PythonObjectNativeWrapper.wrap(factory().createDict(), noWrapperProfile); } @Specialization(guards = "eq(TP_GETATTR, key)") - Object doTpGetattr(@SuppressWarnings("unused") PythonClass object, @SuppressWarnings("unused") String key) { + Object doTpGetattr(@SuppressWarnings("unused") ManagedPythonClass object, @SuppressWarnings("unused") String key) { // we do not provide 'tp_getattr'; code will usually then use 'tp_getattro' return getToSulongNode().execute(PNone.NO_VALUE); } @Specialization(guards = "eq(TP_SETATTR, key)") - Object doTpSetattr(@SuppressWarnings("unused") PythonClass object, @SuppressWarnings("unused") String key) { + Object doTpSetattr(@SuppressWarnings("unused") ManagedPythonClass object, @SuppressWarnings("unused") String key) { // we do not provide 'tp_setattr'; code will usually then use 'tp_setattro' return getToSulongNode().execute(PNone.NO_VALUE); } @Specialization(guards = "eq(TP_GETATTRO, key)") - Object doTpGetattro(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpGetattro(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__GETATTRIBUTE__)") LookupAttributeInMRONode lookupAttrNode) { return PyProcsWrapper.createGetAttrWrapper(lookupAttrNode.execute(object)); } @Specialization(guards = "eq(TP_SETATTRO, key)") - Object doTpSetattro(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpSetattro(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__SETATTR__)") LookupAttributeInMRONode lookupAttrNode) { return PyProcsWrapper.createSetAttrWrapper(lookupAttrNode.execute(object)); } @Specialization(guards = "eq(TP_ITERNEXT, key)") - Object doTpIternext(PythonClass object, @SuppressWarnings("unused") String key, + Object doTpIternext(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__NEXT__)") LookupAttributeInMRONode lookupAttrNode) { return getToSulongNode().execute(lookupAttrNode.execute(object)); } @@ -866,19 +866,19 @@ abstract static class WriteNativeMemberNode extends PNodeWithContext { abstract Object execute(Object receiver, String key, Object value); @Specialization(guards = "eq(OB_TYPE, key)") - Object doObType(PythonObject object, @SuppressWarnings("unused") String key, @SuppressWarnings("unused") PythonClass value, + Object doObType(PythonObject object, @SuppressWarnings("unused") String key, @SuppressWarnings("unused") ManagedPythonClass value, @Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) { // At this point, we do not support changing the type of an object. return PythonObjectNativeWrapper.wrap(object, noWrapperProfile); } @Specialization(guards = "eq(TP_FLAGS, key)") - long doTpFlags(PythonClass object, @SuppressWarnings("unused") String key, long flags) { + long doTpFlags(ManagedPythonClass object, @SuppressWarnings("unused") String key, long flags) { object.setFlags(flags); return flags; } - @Specialization(guards = {"eq(TP_BASICSIZE, key)", "isPythonBuiltinClass(object)"}) + @Specialization(guards = "eq(TP_BASICSIZE, key)") @TruffleBoundary long doTpBasicsize(PythonBuiltinClass object, @SuppressWarnings("unused") String key, long basicsize) { // We have to use the 'setAttributeUnsafe' because this properly cannot be modified by @@ -887,7 +887,7 @@ long doTpBasicsize(PythonBuiltinClass object, @SuppressWarnings("unused") String return basicsize; } - @Specialization(guards = {"eq(TP_BASICSIZE, key)", "isPythonUserClass(object)"}) + @Specialization(guards = "eq(TP_BASICSIZE, key)") @TruffleBoundary long doTpBasicsize(PythonClass object, @SuppressWarnings("unused") String key, long basicsize) { // Do deliberately not use "SetAttributeNode" because we want to directly set the @@ -898,7 +898,7 @@ long doTpBasicsize(PythonClass object, @SuppressWarnings("unused") String key, l @Specialization(guards = "eq(TP_SUBCLASSES, key)") @TruffleBoundary - Object doTpSubclasses(PythonClass object, @SuppressWarnings("unused") String key, PythonObjectNativeWrapper value) { + Object doTpSubclasses(ManagedPythonClass object, @SuppressWarnings("unused") String key, PythonObjectNativeWrapper value) { // TODO more type checking; do fast path PDict dict = (PDict) value.getPythonObject(); for (Object item : dict.items()) { @@ -916,7 +916,7 @@ Object doMdDef(PythonObject object, @SuppressWarnings("unused") String key, Obje } @Specialization(guards = "eq(TP_DICT, key)") - Object doTpDict(PythonClass object, @SuppressWarnings("unused") String key, Object nativeValue, + Object doTpDict(ManagedPythonClass object, @SuppressWarnings("unused") String key, Object nativeValue, @Cached("create()") CExtNodes.AsPythonObjectNode asPythonObjectNode, @Cached("create()") HashingStorageNodes.GetItemNode getItem, @Cached("create()") WriteAttributeToObjectNode writeAttrNode, diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java index 51f6c8e6cf..64670b2abe 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java @@ -82,10 +82,12 @@ import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.SetLenNodeGen; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.SetStorageSliceNodeGen; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.StorageToNativeNodeGen; +import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.ToArrayNodeGen; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.ToByteArrayNodeGen; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.VerifyNativeItemNodeGen; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.list.PList; +import com.oracle.graal.python.builtins.objects.range.PRange; import com.oracle.graal.python.builtins.objects.slice.PSlice; import com.oracle.graal.python.builtins.objects.slice.PSlice.SliceInfo; import com.oracle.graal.python.builtins.objects.str.PString; @@ -3045,4 +3047,85 @@ public static ItemIndexNode create() { return ItemIndexNodeGen.create(); } } + + public abstract static class ToArrayNode extends SequenceStorageBaseNode { + + @Child private GetItemScalarNode getItemNode; + + private final boolean exact; + + public ToArrayNode(boolean exact) { + this.exact = exact; + } + + public abstract Object[] execute(SequenceStorage s); + + @Specialization + Object[] doObjectSequenceStorage(ObjectSequenceStorage s) { + Object[] barr = s.getInternalArray(); + if (exact) { + return exactCopy(barr, s.length()); + } + return barr; + } + + @Specialization + Object[] doTypedSequenceStorage(TypedSequenceStorage s) { + Object[] internalArray = s.getInternalArray(); + assert internalArray.length == s.length(); + return internalArray; + } + + @Specialization + Object[] doNativeObject(NativeSequenceStorage s) { + Object[] barr = new Object[s.length()]; + for (int i = 0; i < barr.length; i++) { + barr[i] = getGetItemNode().execute(s, i); + } + return barr; + } + + @Specialization + Object[] doEmptySequenceStorage(EmptySequenceStorage s) { + return s.getInternalArray(); + } + + @Specialization + Object[] doRangeSequenceStorage(RangeSequenceStorage s) { + int length = s.length(); + PRange range = s.getRange(); + Object[] result = new Object[length]; + for (int i = 0, cur = range.getStart(); i < result.length; i++, cur += range.getStep()) { + result[i] = cur; + } + return result; + } + + @Fallback + Object[] doFallback(@SuppressWarnings("unused") SequenceStorage s) { + throw raise(TypeError, "unsupported sequence type"); + } + + @TruffleBoundary + private static T[] exactCopy(T[] barr, int len) { + return Arrays.copyOf(barr, len); + } + + protected GetItemScalarNode getGetItemNode() { + if (getItemNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getItemNode = insert(GetItemScalarNode.create()); + } + return getItemNode; + } + + public static ToArrayNode create() { + return ToArrayNodeGen.create(true); + } + + public static ToArrayNode create(boolean exact) { + return ToArrayNodeGen.create(exact); + } + } + } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/enumerate/PEnumerate.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/enumerate/PEnumerate.java index b985f4931a..2689e275b5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/enumerate/PEnumerate.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/enumerate/PEnumerate.java @@ -26,14 +26,14 @@ package com.oracle.graal.python.builtins.objects.enumerate; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; public final class PEnumerate extends PythonBuiltinObject { private final Object iterator; private long index; - public PEnumerate(PythonClass clazz, Object iterator, long start) { + public PEnumerate(LazyPythonClass clazz, Object iterator, long start) { super(clazz); this.iterator = iterator; this.index = start; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java index c27ec945b8..98bd45c058 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java @@ -73,7 +73,6 @@ import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.nodes.call.special.LookupAndCallVarargsNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; @@ -596,13 +595,12 @@ private double fromHex(String arg) { } @Specialization(guards = "isPythonBuiltinClass(cl)") - @SuppressWarnings("unused") - public double fromhexFloat(PythonClass cl, String arg) { + public double fromhexFloat(@SuppressWarnings("unused") LazyPythonClass cl, String arg) { return fromHex(arg); } @Specialization(guards = "!isPythonBuiltinClass(cl)") - public Object fromhexO(PythonClass cl, String arg, + public Object fromhexO(LazyPythonClass cl, String arg, @Cached("create(__CALL__)") LookupAndCallVarargsNode constr) { double value = fromHex(arg); return constr.execute(null, cl, new Object[]{cl, value}); @@ -1256,7 +1254,7 @@ protected boolean isValidTypeStr(String typeStr) { } @Specialization(guards = "isValidTypeStr(typeStr)") - String getFormat(@SuppressWarnings("unused") PythonClass cls, @SuppressWarnings("unused") String typeStr) { + String getFormat(@SuppressWarnings("unused") LazyPythonClass cls, @SuppressWarnings("unused") String typeStr) { return getDetectedEndianess(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/GeneratorBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/GeneratorBuiltins.java index 90bd3b8449..694cdf4444 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/GeneratorBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/GeneratorBuiltins.java @@ -43,7 +43,7 @@ import com.oracle.graal.python.builtins.objects.function.PArguments; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.call.special.LookupAndCallVarargsNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; @@ -51,9 +51,9 @@ import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; @@ -154,7 +154,7 @@ public Object send(PGenerator self, Object value) { @GenerateNodeFactory abstract static class ThrowNode extends PythonBuiltinNode { @Specialization - Object sendThrow(VirtualFrame frame, PGenerator self, PythonClass typ, @SuppressWarnings("unused") PNone val, @SuppressWarnings("unused") PNone tb, + Object sendThrow(VirtualFrame frame, PGenerator self, LazyPythonClass typ, @SuppressWarnings("unused") PNone val, @SuppressWarnings("unused") PNone tb, @Cached("create(__CALL__)") LookupAndCallVarargsNode callTyp) { Object instance = callTyp.execute(frame, typ, new Object[0]); if (instance instanceof PBaseException) { @@ -167,7 +167,7 @@ Object sendThrow(VirtualFrame frame, PGenerator self, PythonClass typ, @Suppress } @Specialization - Object sendThrow(VirtualFrame frame, PGenerator self, PythonClass typ, PTuple val, @SuppressWarnings("unused") PNone tb, + Object sendThrow(VirtualFrame frame, PGenerator self, LazyPythonClass typ, PTuple val, @SuppressWarnings("unused") PNone tb, @Cached("create(__CALL__)") LookupAndCallVarargsNode callTyp) { Object instance = callTyp.execute(frame, typ, val.getArray()); if (instance instanceof PBaseException) { @@ -180,7 +180,7 @@ Object sendThrow(VirtualFrame frame, PGenerator self, PythonClass typ, PTuple va } @Specialization(guards = {"!isPNone(val)", "!isPTuple(val)"}) - Object sendThrow(VirtualFrame frame, PGenerator self, PythonClass typ, Object val, @SuppressWarnings("unused") PNone tb, + Object sendThrow(VirtualFrame frame, PGenerator self, LazyPythonClass typ, Object val, @SuppressWarnings("unused") PNone tb, @Cached("create(__CALL__)") LookupAndCallVarargsNode callTyp) { Object instance = callTyp.execute(frame, typ, new Object[]{val}); if (instance instanceof PBaseException) { @@ -200,7 +200,7 @@ Object sendThrow(PGenerator self, PBaseException instance, @SuppressWarnings("un } @Specialization - Object sendThrow(PGenerator self, @SuppressWarnings("unused") PythonClass typ, PBaseException instance, PTraceback tb) { + Object sendThrow(PGenerator self, @SuppressWarnings("unused") LazyPythonClass typ, PBaseException instance, PTraceback tb) { PException pException = PException.fromObject(instance, this); instance.setTraceback(tb); PArguments.setSpecialArgument(self.getArguments(), pException); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java index 2f636ed4a8..ca4b28cea3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java @@ -55,9 +55,9 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; @@ -98,6 +98,7 @@ abstract static class GetSetNode extends PythonTernaryBuiltinNode { @Child private GetMroNode getMroNode; @Child private GetNameNode getNameNode; + @Child private IsSameTypeNode isSameTypeNode; private final IsBuiltinClassProfile isNoneBuiltinClassProfile = IsBuiltinClassProfile.create(); private final ConditionProfile isBuiltinProfile = ConditionProfile.createBinaryProfile(); @@ -105,7 +106,7 @@ abstract static class GetSetNode extends PythonTernaryBuiltinNode { private final BranchProfile errorBranch = BranchProfile.create(); // https://github.com/python/cpython/blob/e8b19656396381407ad91473af5da8b0d4346e88/Objects/descrobject.c#L70 - protected boolean descr_check(LazyPythonClass descrType, String name, Object obj, AbstractPythonClass type) { + protected boolean descr_check(LazyPythonClass descrType, String name, Object obj, LazyPythonClass type) { if (PGuards.isNone(obj)) { if (!isNoneBuiltinClassProfile.profileClass(type, PythonBuiltinClassType.PNone)) { return true; @@ -120,7 +121,7 @@ protected boolean descr_check(LazyPythonClass descrType, String name, Object obj } } else { for (AbstractPythonClass o : getMro(type)) { - if (o == descrType) { + if (isSameType(o, descrType)) { return false; } } @@ -129,7 +130,7 @@ protected boolean descr_check(LazyPythonClass descrType, String name, Object obj throw raise(TypeError, "descriptor '%s' for '%s' objects doesn't apply to '%s' object", name, getTypeName(descrType), getTypeName(type)); } - private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { + private AbstractPythonClass[] getMro(LazyPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -144,6 +145,14 @@ protected Object getTypeName(LazyPythonClass descrType) { } return getNameNode.execute(descrType); } + + private boolean isSameType(Object left, Object right) { + if (isSameTypeNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isSameTypeNode = insert(IsSameTypeNode.create()); + } + return isSameTypeNode.execute(left, right); + } } @Builtin(name = __GET__, fixedNumOfPositionalArgs = 3) @@ -153,7 +162,7 @@ abstract static class GetSetGetNode extends GetSetNode { // https://github.com/python/cpython/blob/e8b19656396381407ad91473af5da8b0d4346e88/Objects/descrobject.c#L149 @Specialization - Object get(GetSetDescriptor descr, Object obj, PythonClass type, + Object get(GetSetDescriptor descr, Object obj, LazyPythonClass type, @Cached("create()") CallUnaryMethodNode callNode) { if (descr_check(descr.getType(), descr.getName(), obj, type)) { return descr; @@ -167,7 +176,7 @@ Object get(GetSetDescriptor descr, Object obj, PythonClass type, } @Specialization - Object getSlot(HiddenKeyDescriptor descr, Object obj, PythonClass type, + Object getSlot(HiddenKeyDescriptor descr, Object obj, LazyPythonClass type, @Cached("create()") ReadAttributeFromObjectNode readNode, @Cached("createBinaryProfile()") ConditionProfile profile) { if (descr_check(descr.getType(), descr.getKey().getName(), obj, type)) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java index b76e7fc4fd..80efbf463d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java @@ -1972,7 +1972,7 @@ private boolean isBigEndian(String order) { throw raise(PythonErrorType.ValueError, "byteorder must be either 'little' or 'big'"); } - private Object createIntObject(PythonClass cl, BigInteger number) { + private Object createIntObject(LazyPythonClass cl, BigInteger number) { if (PGuards.isPythonBuiltinClass(cl)) { return factory().createInt(number); } @@ -1983,87 +1983,87 @@ private Object createIntObject(PythonClass cl, BigInteger number) { return constructNode.execute(null, cl, new Object[]{cl, factory().createInt(number)}); } - private Object compute(PythonClass cl, byte[] bytes, String byteorder, boolean signed) { + private Object compute(LazyPythonClass cl, byte[] bytes, String byteorder, boolean signed) { BigInteger bi = createBigInteger(bytes, isBigEndian(byteorder), signed); return createIntObject(cl, bi); } // from PBytes @Specialization - public Object fromPBytes(PythonClass cl, PBytes bytes, String byteorder, Object[] args, boolean signed) { + public Object fromPBytes(LazyPythonClass cl, PBytes bytes, String byteorder, Object[] args, boolean signed) { return compute(cl, getToBytesNode().execute(bytes), byteorder, signed); } @Specialization - public Object fromPBytes(PythonClass cl, PBytes bytes, String byteorder, Object[] args, PNone signed) { + public Object fromPBytes(LazyPythonClass cl, PBytes bytes, String byteorder, Object[] args, PNone signed) { return fromPBytes(cl, bytes, byteorder, args, false); } // from PByteArray @Specialization - public Object fromPByteArray(PythonClass cl, PByteArray bytes, String byteorder, Object[] args, boolean signed) { + public Object fromPByteArray(LazyPythonClass cl, PByteArray bytes, String byteorder, Object[] args, boolean signed) { return compute(cl, getToBytesNode().execute(bytes), byteorder, signed); } @Specialization - public Object fromPByteArray(PythonClass cl, PByteArray bytes, String byteorder, Object[] args, PNone signed) { + public Object fromPByteArray(LazyPythonClass cl, PByteArray bytes, String byteorder, Object[] args, PNone signed) { return fromPByteArray(cl, bytes, byteorder, args, false); } // from PArray @Specialization - public Object fromPArray(PythonClass cl, PArray array, String byteorder, Object[] args, boolean signed, + public Object fromPArray(LazyPythonClass cl, PArray array, String byteorder, Object[] args, boolean signed, @Cached("create()") BytesNodes.FromSequenceStorageNode fromSequenceStorageNode) { return compute(cl, fromSequenceStorageNode.execute(array.getSequenceStorage()), byteorder, signed); } @Specialization - public Object fromPArray(PythonClass cl, PArray array, String byteorder, Object[] args, PNone signed, + public Object fromPArray(LazyPythonClass cl, PArray array, String byteorder, Object[] args, PNone signed, @Cached("create()") BytesNodes.FromSequenceStorageNode fromSequenceStorageNode) { return fromPArray(cl, array, byteorder, args, false, fromSequenceStorageNode); } // from PMemoryView @Specialization - public Object fromPMemoryView(PythonClass cl, PMemoryView view, String byteorder, Object[] args, boolean signed) { + public Object fromPMemoryView(LazyPythonClass cl, PMemoryView view, String byteorder, Object[] args, boolean signed) { return compute(cl, getToBytesNode().execute(view), byteorder, signed); } @Specialization - public Object fromPMemoryView(PythonClass cl, PMemoryView view, String byteorder, Object[] args, PNone signed) { + public Object fromPMemoryView(LazyPythonClass cl, PMemoryView view, String byteorder, Object[] args, PNone signed) { return fromPMemoryView(cl, view, byteorder, args, false); } // from PList, only if it is not extended @Specialization(guards = "cannotBeOverridden(getClass(list))") - public Object fromPList(PythonClass cl, PList list, String byteorder, Object[] args, boolean signed) { + public Object fromPList(LazyPythonClass cl, PList list, String byteorder, Object[] args, boolean signed) { return compute(cl, getFromSequenceNode().execute(list), byteorder, signed); } @Specialization(guards = "cannotBeOverridden(getClass(list))") - public Object fromPList(PythonClass cl, PList list, String byteorder, Object[] args, PNone signed) { + public Object fromPList(LazyPythonClass cl, PList list, String byteorder, Object[] args, PNone signed) { return fromPList(cl, list, byteorder, args, false); } // from PTuple, only if it is not extended @Specialization(guards = "cannotBeOverridden(getClass(tuple))") - public Object fromPTuple(PythonClass cl, PTuple tuple, String byteorder, Object[] args, boolean signed) { + public Object fromPTuple(LazyPythonClass cl, PTuple tuple, String byteorder, Object[] args, boolean signed) { return compute(cl, getFromSequenceNode().execute(tuple), byteorder, signed); } @Specialization(guards = "cannotBeOverridden(getClass(tuple))") - public Object fromPTuple(PythonClass cl, PTuple tuple, String byteorder, Object[] args, PNone signed) { + public Object fromPTuple(LazyPythonClass cl, PTuple tuple, String byteorder, Object[] args, PNone signed) { return fromPTuple(cl, tuple, byteorder, args, false); } // rest objects @Specialization - public Object fromObject(PythonClass cl, PythonObject object, String byteorder, Object[] args, PNone signed) { + public Object fromObject(LazyPythonClass cl, PythonObject object, String byteorder, Object[] args, PNone signed) { return fromObject(cl, object, byteorder, args, false); } @Specialization - public Object fromObject(PythonClass cl, PythonObject object, String byteorder, Object[] args, boolean signed) { + public Object fromObject(LazyPythonClass cl, PythonObject object, String byteorder, Object[] args, boolean signed) { if (callBytesNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); callBytesNode = insert(LookupAndCallUnaryNode.create(SpecialMethodNames.__BYTES__)); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PZip.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PZip.java index 2cede89bb4..dc163a55ed 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PZip.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PZip.java @@ -26,13 +26,13 @@ package com.oracle.graal.python.builtins.objects.iterator; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; public final class PZip extends PythonBuiltinObject { private final Object[] iterators; - public PZip(PythonClass clazz, Object[] iterators) { + public PZip(LazyPythonClass clazz, Object[] iterators) { super(clazz); this.iterators = iterators; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java index b6db837434..172f16e88f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java @@ -69,7 +69,6 @@ import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; @@ -126,12 +125,12 @@ AbstractPythonClass getClass(Object self, @SuppressWarnings("unused") PNone valu } @Specialization - PythonClass setClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") PythonBuiltinClass klass) { + LazyPythonClass setClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") PythonBuiltinClass klass) { throw raise(TypeError, ERROR_MESSAGE); } @Specialization - PythonClass setClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") PythonNativeClass klass) { + LazyPythonClass setClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") PythonNativeClass klass) { throw raise(TypeError, ERROR_MESSAGE); } @@ -187,12 +186,12 @@ private LookupAttributeInMRONode getLookupSlotsInOther() { } @Specialization(guards = "!isPythonObject(self)") - PythonClass getClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") PythonClass value) { + LazyPythonClass getClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") AbstractPythonClass value) { throw raise(TypeError, ERROR_MESSAGE); } @Fallback - PythonClass getClass(@SuppressWarnings("unused") Object self, Object value) { + LazyPythonClass getClass(@SuppressWarnings("unused") Object self, Object value) { throw raise(TypeError, "__class__ must be set to a class, not '%p' object", value); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java index be4ecd733e..1acd01357e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java @@ -37,7 +37,6 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; @@ -68,7 +67,7 @@ public PythonObject(LazyPythonClass pythonClass, Shape instanceShape) { CompilerDirectives.transferToInterpreter(); // special case for base type class assert this instanceof PythonBuiltinClass; - this.pythonClass = (PythonClass) this; + this.pythonClass = (PythonBuiltinClass) this; } else { this.pythonClass = pythonClass; } @@ -78,8 +77,8 @@ public PythonObject(LazyPythonClass pythonClass, Shape instanceShape) { public final AbstractPythonClass getPythonClass() { CompilerAsserts.neverPartOfCompilation(); assert pythonClass != null; - if (pythonClass instanceof PythonClass) { - return (PythonClass) pythonClass; + if (pythonClass instanceof AbstractPythonClass) { + return (AbstractPythonClass) pythonClass; } else { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) pythonClass); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/PRandom.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/PRandom.java index 2d120cb8b5..0c4813b785 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/PRandom.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/PRandom.java @@ -43,7 +43,7 @@ import java.util.Random; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; public class PRandom extends PythonBuiltinObject { @@ -59,7 +59,7 @@ long getSeed() { private PythonRandom javaRandom; - public PRandom(PythonClass cls) { + public PRandom(LazyPythonClass cls) { super(cls); resetJavaRandom(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PSequenceReverseIterator.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PSequenceReverseIterator.java index 9ff6e895f4..f716c66a9e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PSequenceReverseIterator.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PSequenceReverseIterator.java @@ -26,14 +26,14 @@ package com.oracle.graal.python.builtins.objects.reversed; import com.oracle.graal.python.builtins.objects.iterator.PBuiltinIterator; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; public final class PSequenceReverseIterator extends PBuiltinIterator { private final Object sequence; int index; - public PSequenceReverseIterator(PythonClass clazz, Object sequence, int lengthHint) { + public PSequenceReverseIterator(LazyPythonClass clazz, Object sequence, int lengthHint) { super(clazz); this.sequence = sequence; this.index = lengthHint - 1; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PStringReverseIterator.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PStringReverseIterator.java index 4a5d749bb1..1e1006294d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PStringReverseIterator.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PStringReverseIterator.java @@ -26,14 +26,14 @@ package com.oracle.graal.python.builtins.objects.reversed; import com.oracle.graal.python.builtins.objects.iterator.PBuiltinIterator; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; public final class PStringReverseIterator extends PBuiltinIterator { final String value; int index; - public PStringReverseIterator(PythonClass clazz, String value) { + public PStringReverseIterator(LazyPythonClass clazz, String value) { super(clazz); this.value = value; this.index = value.length() - 1; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java index b53a6b8e2b..9cda6258c1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java @@ -60,7 +60,6 @@ import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetTypeNodeGen; import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.SuperInitNodeFactory; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; @@ -357,9 +356,9 @@ private AbstractPythonClass supercheck(Object cls, Object object) { } else { try { Object classObject = getGetAttr().executeObject(object, SpecialAttributeNames.__CLASS__); - if (classObject instanceof PythonClass) { + if (classObject instanceof AbstractPythonClass) { if (getIsSubtype().execute(classObject, cls)) { - return (PythonClass) classObject; + return (AbstractPythonClass) classObject; } } } catch (PException e) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java index fee34815eb..e18389e6af 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java @@ -42,6 +42,7 @@ import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.Truffle; @@ -51,7 +52,7 @@ public class SuperObject extends PythonBuiltinObject { private AbstractPythonClass objecttype; private Object object; - public SuperObject(AbstractPythonClass cls) { + public SuperObject(LazyPythonClass cls) { super(cls); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java index 385f0a4043..0159211d4d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java @@ -199,7 +199,7 @@ private void computeMethodResolutionOrder() { methodResolutionOrder = currentMRO; } - PythonClass[] mergeMROs(MROMergeState[] toMerge, List mro) { + AbstractPythonClass[] mergeMROs(MROMergeState[] toMerge, List mro) { int idx; scan: for (idx = 0; idx < toMerge.length; idx++) { if (toMerge[idx].isMerged()) { @@ -229,7 +229,7 @@ PythonClass[] mergeMROs(MROMergeState[] toMerge, List mro) } } - return mro.toArray(new PythonClass[mro.size()]); + return mro.toArray(new AbstractPythonClass[mro.size()]); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index ed35f60d6d..92dd3ddf4c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -57,6 +57,9 @@ 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.CExtNodes; +import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage; import com.oracle.graal.python.builtins.objects.common.PHashingCollection; import com.oracle.graal.python.builtins.objects.dict.PDict; @@ -94,6 +97,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; @@ -134,8 +138,9 @@ private String concat(Object moduleName, Object qualName) { @GenerateNodeFactory abstract static class MroAttrNode extends PythonBuiltinNode { @Specialization - Object doit(PythonClass klass) { - return factory().createTuple(klass.getMethodResolutionOrder()); + Object doit(LazyPythonClass klass, + @Cached("create()") TypeNodes.GetMroNode getMroNode) { + return factory().createTuple(getMroNode.execute(klass)); } } @@ -164,6 +169,7 @@ public abstract static class CallNode extends PythonVarargsBuiltinNode { @Child private LookupAttributeInMRONode lookupInit = LookupAttributeInMRONode.create(__INIT__); @Child private GetClassNode getClass = GetClassNode.create(); @Child private TypeNodes.IsSameTypeNode isSameTypeNode; + @Child private TypeNodes.GetNameNode getNameNode; private final IsBuiltinClassProfile isClassClassProfile = IsBuiltinClassProfile.create(); @@ -176,34 +182,34 @@ public final Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeywo return execute(frame, PNone.NO_VALUE, arguments, keywords); } - protected PythonClass first(Object[] ary) { - return (PythonClass) ary[0]; + protected AbstractPythonClass first(Object[] ary) { + return (AbstractPythonClass) ary[0]; } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"first(arguments) == cachedSelf"}) protected Object doItUnboxed(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords, - @Cached("first(arguments)") PythonClass cachedSelf) { + @Cached("first(arguments)") AbstractPythonClass cachedSelf) { return op(frame, cachedSelf, arguments, keywords, false); } @Specialization(replaces = "doItUnboxed") protected Object doItUnboxedIndirect(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords) { - PythonClass self = (PythonClass) arguments[0]; + AbstractPythonClass self = (AbstractPythonClass) arguments[0]; return op(frame, self, arguments, keywords, false); } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf"}) - protected Object doIt(VirtualFrame frame, @SuppressWarnings("unused") PythonClass self, Object[] arguments, PKeyword[] keywords, - @Cached("self") PythonClass cachedSelf) { + protected Object doIt(VirtualFrame frame, @SuppressWarnings("unused") AbstractPythonClass self, Object[] arguments, PKeyword[] keywords, + @Cached("self") AbstractPythonClass cachedSelf) { return op(frame, cachedSelf, arguments, keywords, true); } @Specialization(replaces = "doIt") - protected Object doItIndirect(VirtualFrame frame, PythonClass self, Object[] arguments, PKeyword[] keywords) { + protected Object doItIndirect(VirtualFrame frame, AbstractPythonClass self, Object[] arguments, PKeyword[] keywords) { return op(frame, self, arguments, keywords, true); } - private Object op(VirtualFrame frame, PythonClass self, Object[] arguments, PKeyword[] keywords, boolean doCreateArgs) { + private Object op(VirtualFrame frame, AbstractPythonClass self, Object[] arguments, PKeyword[] keywords, boolean doCreateArgs) { Object newMethod = lookupNew.execute(self); if (newMethod != PNone.NO_VALUE) { CompilerAsserts.partialEvaluationConstant(doCreateArgs); @@ -235,7 +241,7 @@ private Object op(VirtualFrame frame, PythonClass self, Object[] arguments, PKey } return newInstance; } else { - throw raise(TypeError, "cannot create '%s' instances", self.getName()); + throw raise(TypeError, "cannot create '%s' instances", getTypeName(self)); } } @@ -246,6 +252,14 @@ private boolean isSameType(AbstractPythonClass left, AbstractPythonClass right) } return isSameTypeNode.execute(left, right); } + + private String getTypeName(AbstractPythonClass clazz) { + if (getNameNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getNameNode = insert(TypeNodes.GetNameNode.create()); + } + return getNameNode.execute(clazz); + } } @Builtin(name = __GETATTRIBUTE__, fixedNumOfPositionalArgs = 2) @@ -271,9 +285,10 @@ public static GetattributeNode create() { @Child private CallTernaryMethodNode invokeGet; @Child private CallTernaryMethodNode invokeValueGet; @Child private LookupAttributeInMRONode.Dynamic lookupAsClass; + @Child private TypeNodes.GetNameNode getNameNode; @Specialization - protected Object doIt(PythonClass object, Object key) { + protected Object doIt(LazyPythonClass object, Object key) { LazyPythonClass type = getObjectClassNode.execute(object); Object descr = lookup.execute(type, key); Object get = null; @@ -325,7 +340,7 @@ protected Object doIt(PythonClass object, Object key) { } } errorProfile.enter(); - throw raise(AttributeError, "type object '%s' has no attribute %s", object.getName(), key); + throw raise(AttributeError, "type object '%s' has no attribute %s", getTypeName(object), key); } private Object readAttribute(Object object, Object key) { @@ -333,7 +348,7 @@ private Object readAttribute(Object object, Object key) { CompilerDirectives.transferToInterpreterAndInvalidate(); lookupAsClass = insert(LookupAttributeInMRONode.Dynamic.create()); } - return lookupAsClass.execute((PythonClass) object, key); + return lookupAsClass.execute((LazyPythonClass) object, key); } private Object lookupDelete(LazyPythonClass dataDescClass) { @@ -375,6 +390,14 @@ private LazyPythonClass getDataClass(Object descr) { } return getDataClassNode.execute(descr); } + + private String getTypeName(Object clazz) { + if (getNameNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getNameNode = insert(TypeNodes.GetNameNode.create()); + } + return getNameNode.execute(clazz); + } } @Builtin(name = __PREPARE__, takesVarArgs = true, takesVarKeywordArgs = true) @@ -391,16 +414,18 @@ Object doIt(Object args, Object kwargs) { @GenerateNodeFactory static abstract class BasesNode extends PythonBuiltinNode { @Specialization - Object bases(PythonClass self) { - return factory().createTuple(self.getBaseClasses()); + Object bases(LazyPythonClass self, + @Cached("create()") TypeNodes.GetBaseClassesNode getBaseClassesNode) { + return factory().createTuple(getBaseClassesNode.execute(self)); } } @Builtin(name = __DICT__, fixedNumOfPositionalArgs = 1, isGetter = true) @GenerateNodeFactory + @ImportStatic(NativeMemberNames.class) static abstract class DictNode extends PythonUnaryBuiltinNode { @Specialization - Object dict(PythonClass self) { + Object doManaged(ManagedPythonClass self) { PHashingCollection dict = self.getDict(); if (dict == null) { dict = factory().createMappingproxy(self); @@ -412,6 +437,12 @@ Object dict(PythonClass self) { assert dict instanceof PMappingproxy; return dict; } + + @Specialization + Object doNative(PythonNativeClass self, + @Cached("create(TP_DICT)") CExtNodes.GetTypeMemberNode getTpDictNode) { + return getTpDictNode.execute(self); + } } @Builtin(name = __INSTANCECHECK__, fixedNumOfPositionalArgs = 2) @@ -466,7 +497,7 @@ static abstract class SubclassCheckNode extends PythonBinaryBuiltinNode { @Child private IsSubtypeNode isSubtypeNode = IsSubtypeNode.create(); @Specialization - boolean instanceCheck(PythonClass cls, Object derived) { + boolean instanceCheck(LazyPythonClass cls, Object derived) { return cls == derived || isSubtypeNode.execute(derived, cls); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 576fba654d..01e44a8283 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -47,9 +47,13 @@ import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.cext.CExtNodes; +import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; +import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; +import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass.FlagsContainer; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetBaseClassesNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetNameNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSubclassesNodeGen; @@ -72,6 +76,7 @@ import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ValueProfile; public abstract class TypeNodes { @@ -152,7 +157,7 @@ public abstract static class GetMroNode extends PNodeWithContext { public abstract AbstractPythonClass[] execute(Object obj); @Specialization - AbstractPythonClass[] doPythonClass(PythonClass obj) { + AbstractPythonClass[] doPythonClass(ManagedPythonClass obj) { return obj.getMethodResolutionOrder(); } @@ -278,6 +283,62 @@ public static GetSubclassesNode create() { } + @ImportStatic(NativeMemberNames.class) + public abstract static class GetBaseClassesNode extends PNodeWithContext { + + // TODO(fa): this should not return a Java array; maybe a SequenceStorage would fit + public abstract AbstractPythonClass[] execute(Object obj); + + @Specialization + AbstractPythonClass[] doPythonClass(ManagedPythonClass obj) { + return obj.getBaseClasses(); + } + + @Specialization + AbstractPythonClass[] doPythonClass(PythonBuiltinClassType obj) { + return getBuiltinPythonClass(obj).getBaseClasses(); + } + + @Specialization + AbstractPythonClass[] doNative(PythonNativeClass obj, + @Cached("create(TP_BASES)") GetTypeMemberNode getTpBasesNode, + @Cached("createClassProfile()") ValueProfile resultTypeProfile, + @Cached("createToArray()") SequenceStorageNodes.ToArrayNode toArrayNode) { + Object result = resultTypeProfile.profile(getTpBasesNode.execute(obj)); + if (result instanceof PTuple) { + Object[] values = toArrayNode.execute(((PTuple) result).getSequenceStorage()); + try { + return (AbstractPythonClass[]) values; + } catch (ClassCastException e) { + throw raise(PythonBuiltinClassType.SystemError, "unsupported object in 'tp_bases'"); + } + } + throw raise(PythonBuiltinClassType.SystemError, "type does not provide bases"); + } + + @TruffleBoundary + public static AbstractPythonClass[] doSlowPath(Object obj) { + if (obj instanceof ManagedPythonClass) { + return ((ManagedPythonClass) obj).getBaseClasses(); + } else if (obj instanceof PythonBuiltinClassType) { + return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getBaseClasses(); + } else if (obj instanceof PythonNativeClass) { + // TODO implement + throw new UnsupportedOperationException("not yet implemented"); + } + throw new IllegalStateException("unknown type " + obj.getClass().getName()); + } + + protected static SequenceStorageNodes.ToArrayNode createToArray() { + return SequenceStorageNodes.ToArrayNode.create(false); + } + + public static GetBaseClassesNode create() { + return GetBaseClassesNodeGen.create(); + } + + } + @ImportStatic(SpecialMethodNames.class) public abstract static class IsSameTypeNode extends PNodeWithContext { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index aedd873ca8..6ecc118723 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -46,7 +46,6 @@ import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.runtime.PythonCore; @@ -57,7 +56,6 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.nodes.ControlFlowException; import com.oracle.truffle.api.nodes.ExplodeLoop; @ImportStatic(PythonOptions.class) @@ -89,7 +87,7 @@ protected Object lookup(PythonBuiltinClassType klass, Object key) { } @Specialization(replaces = "lookupConstantMRO") - protected Object lookup(PythonClass klass, Object key, + protected Object lookup(ManagedPythonClass klass, Object key, @Cached("create()") GetMroNode getMroNode, @Cached("create()") ReadAttributeFromObjectNode readAttrNode) { return LookupAttributeInMRONode.lookupSlow(klass, key, getMroNode, readAttrNode); @@ -150,7 +148,7 @@ final static class PythonClassAssumptionPair { } } - protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonClass klass) { + protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(ManagedPythonClass klass) { AbstractPythonClass[] mro = getMro(klass); Assumption attrAssumption = klass.createAttributeInMROFinalAssumption(key); for (int i = 0; i < mro.length; i++) { @@ -179,8 +177,8 @@ protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonClass @Specialization(guards = {"klass == cachedKlass", "cachedClassInMROInfo != null"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = { "cachedClassInMROInfo.assumption"}) - protected Object lookupConstantMROCached(@SuppressWarnings("unused") PythonClass klass, - @Cached("klass") @SuppressWarnings("unused") PythonClass cachedKlass, + protected Object lookupConstantMROCached(@SuppressWarnings("unused") ManagedPythonClass klass, + @Cached("klass") @SuppressWarnings("unused") ManagedPythonClass cachedKlass, @Cached("findAttrClassAndAssumptionInMRO(cachedKlass)") PythonClassAssumptionPair cachedClassInMROInfo) { return cachedClassInMROInfo.value; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java index 5ee6b078be..ee3c19147e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java @@ -43,7 +43,8 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetNativeDictNode; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetObjectDictNode; -import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeDictNode; +import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; +import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.common.HashingStorage; @@ -65,7 +66,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; -@ImportStatic({PGuards.class, PythonOptions.class}) +@ImportStatic({PGuards.class, PythonOptions.class, NativeMemberNames.class}) public abstract class ReadAttributeFromObjectNode extends ObjectAttributeNode { public static ReadAttributeFromObjectNode create() { return ReadAttributeFromObjectNodeGen.create(); @@ -145,7 +146,7 @@ protected Object readNativeObject(PythonNativeObject object, Object key, @Specialization(guards = {"!isHiddenKey(key)"}) protected Object readNativeClass(PythonNativeClass object, Object key, - @Cached("create()") GetTypeDictNode getNativeDict, + @Cached("create(TP_DICT)") GetTypeMemberNode getNativeDict, @Cached("create()") HashingStorageNodes.GetItemNode getItemNode) { return readNative(object, key, getNativeDict, getItemNode); } @@ -186,6 +187,8 @@ public static Object doSlowPath(Object object, Object key) { if (object instanceof PythonObject) { PythonObject po = (PythonObject) object; if (ObjectAttributeNode.isDictUnsetOrSameAsStorage(po)) { + return ReadAttributeFromDynamicObjectNode.doSlowPath(po.getStorage(), key); + } else { HashingStorage dictStorage = po.getDict().getDictStorage(); Object value = dictStorage.getItem(key, HashingStorage.getSlowPathEquivalence(key)); if (value == null) { @@ -193,8 +196,6 @@ public static Object doSlowPath(Object object, Object key) { } else { return value; } - } else { - return ReadAttributeFromDynamicObjectNode.doSlowPath(po.getStorage(), key); } } else if (object instanceof PythonNativeObject || object instanceof PythonNativeClass) { Object d = GetObjectDictNode.doSlowPath(object); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java index 512b0e1f3b..8f0342811d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java @@ -52,7 +52,7 @@ import com.oracle.graal.python.builtins.objects.method.PMethod; 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.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.runtime.PythonOptions; import com.oracle.truffle.api.Assumption; @@ -78,16 +78,16 @@ public static WriteAttributeToObjectNode create() { } protected boolean isAttrWritable(PythonObject self, Object key) { - if (isHiddenKey(key) || self instanceof PythonClass || self instanceof PFunction || self instanceof PMethod || self instanceof PythonModule || self instanceof PBaseException) { + if (isHiddenKey(key) || self instanceof ManagedPythonClass || self instanceof PFunction || self instanceof PMethod || self instanceof PythonModule || self instanceof PBaseException) { return true; } return !exactBuiltinInstanceProfile.profileIsAnyBuiltinObject(self); } private void handlePythonClass(PythonObject object, Object key) { - if (isClassProfile.profile(object instanceof PythonClass)) { + if (isClassProfile.profile(object instanceof ManagedPythonClass)) { if (key instanceof String) { - ((PythonClass) object).invalidateAttributeInMROFinalAssumptions((String) key); + ((ManagedPythonClass) object).invalidateAttributeInMROFinalAssumptions((String) key); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java index c53a7c9ddf..d255c52a3e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java @@ -43,6 +43,7 @@ import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.runtime.PythonOptions; import com.oracle.graal.python.runtime.exception.PythonErrorType; @@ -62,6 +63,7 @@ public abstract class IsSubtypeNode extends PNodeWithContext { @Child private AbstractObjectGetBasesNode getBasesNode = AbstractObjectGetBasesNode.create(); @Child private AbstractObjectIsSubclassNode abstractIsSubclassNode = AbstractObjectIsSubclassNode.create(); @Child private GetMroNode getMroNode; + @Child private IsSameTypeNode isSameTypeNode; private final ConditionProfile exceptionDerivedProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile exceptionClsProfile = ConditionProfile.createBinaryProfile(); @@ -74,11 +76,11 @@ public static IsSubtypeNode create() { @Specialization(guards = {"derived == cachedDerived", "cls == cachedCls"}, limit = "getVariableArgumentInlineCacheLimit()") @ExplodeLoop - boolean isSubtypeOfConstantType(@SuppressWarnings("unused") PythonClass derived, @SuppressWarnings("unused") PythonClass cls, - @Cached("derived") PythonClass cachedDerived, - @Cached("cls") PythonClass cachedCls) { + boolean isSubtypeOfConstantType(@SuppressWarnings("unused") AbstractPythonClass derived, @SuppressWarnings("unused") AbstractPythonClass cls, + @Cached("derived") AbstractPythonClass cachedDerived, + @Cached("cls") AbstractPythonClass cachedCls) { for (AbstractPythonClass n : getMro(cachedDerived)) { - if (n == cachedCls) { + if (isSameType(n, cachedCls)) { return true; } } @@ -87,10 +89,10 @@ boolean isSubtypeOfConstantType(@SuppressWarnings("unused") PythonClass derived, @Specialization(guards = {"derived == cachedDerived"}, limit = "getVariableArgumentInlineCacheLimit()", replaces = "isSubtypeOfConstantType") @ExplodeLoop - boolean isSubtypeOfVariableType(@SuppressWarnings("unused") PythonClass derived, PythonClass cls, - @Cached("derived") PythonClass cachedDerived) { + boolean isSubtypeOfVariableType(@SuppressWarnings("unused") AbstractPythonClass derived, PythonClass cls, + @Cached("derived") AbstractPythonClass cachedDerived) { for (AbstractPythonClass n : getMro(cachedDerived)) { - if (n == cls) { + if (isSameType(n, cls)) { return true; } } @@ -98,9 +100,9 @@ boolean isSubtypeOfVariableType(@SuppressWarnings("unused") PythonClass derived, } @Specialization(replaces = {"isSubtypeOfConstantType", "isSubtypeOfVariableType"}) - boolean issubTypeGeneric(PythonClass derived, PythonClass cls) { + boolean issubTypeGeneric(AbstractPythonClass derived, AbstractPythonClass cls) { for (AbstractPythonClass n : getMro(derived)) { - if (n == cls) { + if (isSameType(n, cls)) { return true; } } @@ -127,4 +129,12 @@ private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { } return getMroNode.execute(clazz); } + + private boolean isSameType(AbstractPythonClass left, AbstractPythonClass right) { + if (isSameTypeNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isSameTypeNode = insert(IsSameTypeNode.create()); + } + return isSameTypeNode.execute(left, right); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java index c67384605e..584b554749 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java @@ -46,6 +46,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PNotImplemented; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetNativeClassNode; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr; import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptor; @@ -205,6 +206,12 @@ protected AbstractPythonClass getIt(PythonNativeObject object, return getNativeClassNode.execute(object); } + @Specialization + protected static PythonNativeClass getIt(PythonNativeClass object, + @Cached("create()") GetNativeClassNode getNativeClassNode) { + return getNativeClassNode.execute(object); + } + @Specialization(assumptions = "singleContextAssumption()") protected PythonBuiltinClass getIt(@SuppressWarnings("unused") PythonNativeVoidPtr object, @Cached("getIt(object)") PythonBuiltinClass klass) { @@ -252,8 +259,9 @@ public static AbstractPythonClass getItSlowPath(Object o) { } else if (o instanceof PythonObject) { return ((PythonObject) o).getPythonClass(); } else if (o instanceof PythonNativeObject) { - // TODO(fa): implement - throw new UnsupportedOperationException("get class of native object on slow path not yet implemented"); + return GetNativeClassNode.doSlowPath((PythonNativeObject) o); + } else if (o instanceof PythonNativeClass) { + return GetNativeClassNode.doSlowPath((PythonNativeClass) o); } else if (o instanceof PEllipsis) { return core.lookupType(PythonBuiltinClassType.PEllipsis); } else if (o instanceof PNotImplemented) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java index f2c5193bf9..4ab3c90ae6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java @@ -45,12 +45,12 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PNotImplemented; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetNativeClassNode; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr; import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptor; import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.truffle.PythonTypes; @@ -137,7 +137,18 @@ protected static LazyPythonClass getIt(@SuppressWarnings("unused") String object } @Specialization - protected static PythonClass getIt(PythonNativeObject object, + protected static LazyPythonClass getIt(@SuppressWarnings("unused") PythonBuiltinClassType object) { + return PythonBuiltinClassType.PythonClass; + } + + @Specialization + protected static PythonNativeClass getIt(PythonNativeObject object, + @Cached("create()") GetNativeClassNode getNativeClassNode) { + return getNativeClassNode.execute(object); + } + + @Specialization + protected static PythonNativeClass getIt(PythonNativeClass object, @Cached("create()") GetNativeClassNode getNativeClassNode) { return getNativeClassNode.execute(object); } @@ -178,11 +189,14 @@ public static LazyPythonClass getItSlowPath(Object o) { return PythonBuiltinClassType.PFloat; } else if (o instanceof Integer || o instanceof Long || o instanceof Short || o instanceof Byte || o instanceof PythonNativeVoidPtr) { return PythonBuiltinClassType.PInt; + } else if (o instanceof PythonBuiltinClassType) { + return PythonBuiltinClassType.PythonClass; } else if (o instanceof PythonObject) { return ((PythonObject) o).getLazyPythonClass(); } else if (o instanceof PythonNativeObject) { - // TODO(fa): implement - throw new UnsupportedOperationException("get class of native object on slow path not yet implemented"); + return GetNativeClassNode.doSlowPath((PythonNativeObject) o); + } else if (o instanceof PythonNativeClass) { + return GetNativeClassNode.doSlowPath((PythonNativeClass) o); } else if (o instanceof PEllipsis) { return PythonBuiltinClassType.PEllipsis; } else if (o instanceof PNotImplemented) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java index ee0f78a2f6..cd3b1ecd8f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java @@ -30,8 +30,8 @@ import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.expression.ExpressionNode; import com.oracle.graal.python.nodes.frame.WriteNode; @@ -57,6 +57,7 @@ public class ExceptNode extends PNodeWithContext implements InstrumentableNode { @Child private WriteNode exceptName; @Child private GetLazyClassNode getClass; @Child private GetMroNode getMroNode; + @Child private IsSameTypeNode isSameTypeNode; // "object" is the uninitialized value (since it's not a valid error type) @CompilationFinal private PythonBuiltinClassType singleBuiltinError = PythonBuiltinClassType.PythonObject; @@ -109,7 +110,7 @@ public boolean matchesException(VirtualFrame frame, PException e) { if (error != null) { // check that the class is a subclass of BaseException if (!derivesFromBaseException(error)) { - throw raise(PythonErrorType.TypeError, "catching classes that do not inherit from BaseException is not allowed"); + raiseNoException(); } singleBuiltinError = error; } @@ -153,7 +154,7 @@ private boolean matchesExceptionCached(VirtualFrame frame, LazyPythonClass lazyC } } else { // non-builtin class: look through MRO - AbstractPythonClass[] mro = getMro((PythonClass) lazyClass); + AbstractPythonClass[] mro = getMro(lazyClass); for (AbstractPythonClass current : mro) { if (isClassProfile.profileClass(current, cachedError)) { matches = true; @@ -195,7 +196,7 @@ private boolean matchesExceptionFallback(VirtualFrame frame, PException e, Objec matches = matches(expectedType, builtinType); } } else { - PythonClass clazz = (PythonClass) lazyClass; + AbstractPythonClass clazz = (AbstractPythonClass) lazyClass; if (isTupleProfile.profile(expectedType instanceof PTuple)) { // check for every type in the tuple for (Object etype : ((PTuple) expectedType).getArray()) { @@ -212,9 +213,9 @@ private boolean matchesExceptionFallback(VirtualFrame frame, PException e, Objec return writeResult(frame, e, matches); } - private boolean matches(Object expectedType, PythonClass clazz) { + private boolean matches(Object expectedType, AbstractPythonClass clazz) { // TODO: check whether expected type derives from BaseException - if (equalsProfile.profile(expectedType == clazz)) { + if (equalsProfile.profile(isSameType(expectedType, clazz))) { return true; } AbstractPythonClass[] mro = getMro(clazz); @@ -227,12 +228,12 @@ private boolean matches(Object expectedType, PythonClass clazz) { } private boolean matches(Object expectedType, PythonBuiltinClassType clazz) { - if (!(expectedType instanceof PythonClass)) { + if (!(expectedType instanceof AbstractPythonClass)) { errorProfile.enter(); - throw raise(PythonErrorType.TypeError, "catching classes that do not inherit from BaseException is not allowed"); + throw raiseNoException(); } - PythonClass expectedClass = (PythonClass) expectedType; + AbstractPythonClass expectedClass = (AbstractPythonClass) expectedType; // TODO: check whether expected type derives from BaseException PythonBuiltinClassType builtinClass = clazz; @@ -245,6 +246,10 @@ private boolean matches(Object expectedType, PythonBuiltinClassType clazz) { return false; } + private PException raiseNoException() { + throw raise(PythonErrorType.TypeError, "catching classes that do not inherit from BaseException is not allowed"); + } + private boolean derivesFromBaseException(PythonBuiltinClassType error) { if (error == PythonBuiltinClassType.PBaseException) { return true; @@ -276,11 +281,19 @@ public boolean isInstrumentable() { return getSourceSection() != null; } - private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { + private AbstractPythonClass[] getMro(LazyPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); } return getMroNode.execute(clazz); } + + private boolean isSameType(Object left, Object right) { + if (isSameTypeNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isSameTypeNode = insert(IsSameTypeNode.create()); + } + return isSameTypeNode.execute(left, right); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java index 47b3a49f50..ab0f4a7c49 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/RaiseNode.java @@ -32,7 +32,6 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.exception.PBaseException; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; @@ -40,7 +39,6 @@ import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.exception.PException; -import com.oracle.graal.python.runtime.exception.PythonErrorType; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -82,7 +80,7 @@ public void doRaise(PBaseException exception, Object cause, throw raise(exception); } - private void checkBaseClass(PythonClass pythonClass) { + private void checkBaseClass(AbstractPythonClass pythonClass) { if (simpleBaseCheckProfile.profileClass(pythonClass, BaseException)) { return; } @@ -92,17 +90,17 @@ private void checkBaseClass(PythonClass pythonClass) { } } baseCheckFailedProfile.enter(); - throw raise(PythonErrorType.TypeError, "exceptions must derive from BaseException"); + throw raiseNoException(); } @Specialization - public void doRaise(PythonClass pythonClass, PNone cause) { + public void doRaise(AbstractPythonClass pythonClass, PNone cause) { checkBaseClass(pythonClass); throw raise(pythonClass); } @Specialization(guards = "!isPNone(cause)") - public void doRaise(PythonClass pythonClass, Object cause, + public void doRaise(AbstractPythonClass pythonClass, Object cause, @Cached("create()") WriteAttributeToObjectNode writeCause) { checkBaseClass(pythonClass); PBaseException pythonException = factory().createBaseException(pythonClass); @@ -112,6 +110,10 @@ public void doRaise(PythonClass pythonClass, Object cause, @Fallback public void doRaise(Object exception, Object cause) { + throw raiseNoException(); + } + + private PException raiseNoException() { throw raise(TypeError, "exceptions must derive from BaseException"); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java index d421bea1e3..a00e9785b8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java @@ -588,7 +588,7 @@ public Object access(Object receiver) { @Resolve(message = "IS_INSTANTIABLE") abstract static class IsInstantiableNode extends Node { public Object access(Object obj) { - return obj instanceof PythonClass; + return obj instanceof LazyPythonClass; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index 0d98768e94..dd7ce2d10d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -187,7 +187,7 @@ private boolean reportAllocations() { @CompilationFinal private Optional cachedInstanceShape = Optional.empty(); - public PythonObject createPythonObject(PythonClass cls) { + public PythonObject createPythonObject(LazyPythonClass cls) { assert cls != null; Optional cached = cachedInstanceShape; if (cached != null) { @@ -214,7 +214,7 @@ public PythonNativeVoidPtr createNativeVoidPtr(TruffleObject obj) { return trace(new PythonNativeVoidPtr(obj)); } - public SuperObject createSuperObject(AbstractPythonClass self) { + public SuperObject createSuperObject(LazyPythonClass self) { return trace(new SuperObject(self)); } @@ -338,7 +338,7 @@ public PSlice createSlice(int start, int stop, int step) { return trace(new PSlice(PythonBuiltinClassType.PSlice, start, stop, step)); } - public PRandom createRandom(PythonClass cls) { + public PRandom createRandom(LazyPythonClass cls) { return trace(new PRandom(cls)); } @@ -350,7 +350,7 @@ public PythonModule createPythonModule(String name) { return trace(new PythonModule(PythonBuiltinClassType.PythonModule, name)); } - public PythonModule createPythonModule(PythonClass cls, String name) { + public PythonModule createPythonModule(LazyPythonClass cls, String name) { return trace(new PythonModule(cls, name)); } @@ -473,7 +473,7 @@ public PSet createSet(HashingStorage storage) { return trace(new PSet(PythonBuiltinClassType.PSet, storage)); } - public PFrozenSet createFrozenSet(PythonClass cls) { + public PFrozenSet createFrozenSet(LazyPythonClass cls) { return trace(new PFrozenSet(cls)); } @@ -493,7 +493,7 @@ public PDict createDict(PKeyword[] keywords) { return trace(new PDict(PythonBuiltinClassType.PDict, keywords)); } - public PDict createDict(PythonClass cls) { + public PDict createDict(LazyPythonClass cls) { return trace(new PDict(cls)); } @@ -612,27 +612,27 @@ public PBaseException createBaseException(LazyPythonClass cls) { * Arrays */ - public PArray createArray(PythonClass cls, byte[] array) { + public PArray createArray(LazyPythonClass cls, byte[] array) { return trace(new PArray(cls, new ByteSequenceStorage(array))); } - public PArray createArray(PythonClass cls, int[] array) { + public PArray createArray(LazyPythonClass cls, int[] array) { return trace(new PArray(cls, new IntSequenceStorage(array))); } - public PArray createArray(PythonClass cls, double[] array) { + public PArray createArray(LazyPythonClass cls, double[] array) { return trace(new PArray(cls, new DoubleSequenceStorage(array))); } - public PArray createArray(PythonClass cls, char[] array) { + public PArray createArray(LazyPythonClass cls, char[] array) { return trace(new PArray(cls, new CharSequenceStorage(array))); } - public PArray createArray(PythonClass cls, long[] array) { + public PArray createArray(LazyPythonClass cls, long[] array) { return trace(new PArray(cls, new LongSequenceStorage(array))); } - public PArray createArray(PythonClass cls, SequenceStorage store) { + public PArray createArray(LazyPythonClass cls, SequenceStorage store) { return trace(new PArray(cls, store)); } @@ -684,7 +684,7 @@ public PStringIterator createStringIterator(String str) { return trace(new PStringIterator(PythonBuiltinClassType.PIterator, str)); } - public PStringReverseIterator createStringReverseIterator(PythonClass cls, String str) { + public PStringReverseIterator createStringReverseIterator(LazyPythonClass cls, String str) { return trace(new PStringReverseIterator(cls, str)); } @@ -704,7 +704,7 @@ public PSequenceIterator createSequenceIterator(Object sequence) { return trace(new PSequenceIterator(PythonBuiltinClassType.PIterator, sequence)); } - public PSequenceReverseIterator createSequenceReverseIterator(PythonClass cls, Object sequence, int lengthHint) { + public PSequenceReverseIterator createSequenceReverseIterator(LazyPythonClass cls, Object sequence, int lengthHint) { return trace(new PSequenceReverseIterator(cls, sequence, lengthHint)); } @@ -742,11 +742,11 @@ public Object createSentinelIterator(Object callable, Object sentinel) { return trace(new PSentinelIterator(PythonBuiltinClassType.PSentinelIterator, callable, sentinel)); } - public PEnumerate createEnumerate(PythonClass cls, Object iterator, long start) { + public PEnumerate createEnumerate(LazyPythonClass cls, Object iterator, long start) { return trace(new PEnumerate(cls, iterator, start)); } - public PZip createZip(PythonClass cls, Object[] iterables) { + public PZip createZip(LazyPythonClass cls, Object[] iterables) { return trace(new PZip(cls, iterables)); } @@ -754,7 +754,7 @@ public PForeignArrayIterator createForeignArrayIterator(TruffleObject iterable, return trace(new PForeignArrayIterator(PythonBuiltinClassType.PForeignArrayIterator, iterable, size)); } - public PBuffer createBuffer(PythonClass cls, Object iterable, boolean readonly) { + public PBuffer createBuffer(LazyPythonClass cls, Object iterable, boolean readonly) { return trace(new PBuffer(cls, iterable, readonly)); } @@ -791,7 +791,7 @@ public PSocket createSocket(int family, int type, int proto) { return trace(new PSocket(PythonBuiltinClassType.PSocket, family, type, proto)); } - public PSocket createSocket(PythonClass cls, int family, int type, int proto) { + public PSocket createSocket(LazyPythonClass cls, int family, int type, int proto) { return trace(new PSocket(cls, family, type, proto)); } @@ -803,7 +803,7 @@ public PLock createLock() { return trace(new PLock(PythonBuiltinClassType.PLock)); } - public PLock createLock(PythonClass cls) { + public PLock createLock(LazyPythonClass cls) { return trace(new PLock(cls)); } @@ -811,7 +811,7 @@ public PRLock createRLock() { return trace(new PRLock(PythonBuiltinClassType.PRLock)); } - public PRLock createRLock(PythonClass cls) { + public PRLock createRLock(LazyPythonClass cls) { return trace(new PRLock(cls)); } @@ -819,11 +819,11 @@ public PThread createPythonThread(Thread thread) { return trace(new PThread(PythonBuiltinClassType.PThread, thread)); } - public PThread createPythonThread(PythonClass cls, Thread thread) { + public PThread createPythonThread(LazyPythonClass cls, Thread thread) { return trace(new PThread(cls, thread)); } - public PScandirIterator createScandirIterator(PythonClass cls, String path, DirectoryStream next) { + public PScandirIterator createScandirIterator(LazyPythonClass cls, String path, DirectoryStream next) { return trace(new PScandirIterator(cls, path, next)); } @@ -831,7 +831,7 @@ public PDirEntry createDirEntry(String name, TruffleFile file) { return trace(new PDirEntry(PythonBuiltinClassType.PDirEntry, name, file)); } - public Object createDirEntry(PythonClass cls, String name, TruffleFile file) { + public Object createDirEntry(LazyPythonClass cls, String name, TruffleFile file) { return trace(new PDirEntry(cls, name, file)); } } From 578d531f16c2f7a63adee2a406d711377f2df9fe Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 18 Jan 2019 14:31:24 +0100 Subject: [PATCH 058/202] Refactor 'PyType_Ready'. --- .../com.oracle.graal.python.cext/src/capi.c | 27 ++------------- .../com.oracle.graal.python.cext/src/capi.h | 19 +++-------- .../src/typeobject.c | 33 ++++--------------- 3 files changed, 15 insertions(+), 64 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/capi.c b/graalpython/com.oracle.graal.python.cext/src/capi.c index 02170cc0a0..fe219e899b 100644 --- a/graalpython/com.oracle.graal.python.cext/src/capi.c +++ b/graalpython/com.oracle.graal.python.cext/src/capi.c @@ -233,15 +233,8 @@ void* native_long_to_java(uint64_t val) { return Py_None; } else if (!truffle_cannot_be_handle(obj)) { return resolve_handle(cache, (uint64_t)obj); - } else { - void* refcnt = obj->ob_refcnt; - if (!truffle_cannot_be_handle(refcnt)) { - return resolve_handle(cache, refcnt); - } else if (IS_POINTER(refcnt)) { - return refcnt; - } - return obj; } + return obj; } __attribute__((always_inline)) @@ -259,25 +252,11 @@ PyObject* to_sulong(void *o) { /** to be used from Java code only; reads native 'ob_type' field */ void* get_ob_type(PyObject* obj) { - PyTypeObject* type = obj->ob_type; + PyTypeObject* type = obj->ob_type; if (!truffle_cannot_be_handle(type)) { return resolve_handle(cache, (uint64_t)type); - } else { - PyObject* cast_type = ((PyObject*)type); - if (!polyglot_is_value(cast_type)) { - // we have stored a handle to the Java class in ob_refcnt - void* handle = (void*)(cast_type->ob_refcnt); - if (!truffle_cannot_be_handle(handle)) { - return resolve_handle(cache, (uint64_t)handle); - } else { - // assume handle is a TruffleObject - return handle; - } - } else { - // the type is already the right value (e.g. on sandboxed it's a managed pointer) - return cast_type; - } } + return (void *)type; } /** to be used from Java code only; reads native 'tp_dict' field */ diff --git a/graalpython/com.oracle.graal.python.cext/src/capi.h b/graalpython/com.oracle.graal.python.cext/src/capi.h index 50b40bb583..0519017d4b 100644 --- a/graalpython/com.oracle.graal.python.cext/src/capi.h +++ b/graalpython/com.oracle.graal.python.cext/src/capi.h @@ -175,25 +175,16 @@ inline void* native_to_java(PyObject* obj) { return obj; } else if (!truffle_cannot_be_handle(obj)) { return resolve_handle(cache, (uint64_t)obj); - } else { - void* refcnt = obj->ob_refcnt; - if (!truffle_cannot_be_handle(refcnt)) { - return resolve_handle(cache, refcnt); - } else if (IS_POINTER(refcnt)) { - return refcnt; - } - return obj; } + return obj; } __attribute__((always_inline)) inline void* native_type_to_java(PyTypeObject* type) { - if (IS_POINTER(((PyObject*)type)->ob_refcnt)) { - return (void*)((PyObject*)type)->ob_refcnt; - } else if (!truffle_cannot_be_handle(((PyObject*)type)->ob_refcnt)) { - return resolve_handle(cache, ((PyObject*)type)->ob_refcnt); - } - return (void*)type; + if (!truffle_cannot_be_handle(type)) { + return (void *)resolve_handle(cache, (uint64_t)type); + } + return (void *)type; } extern void* to_java(PyObject* obj); diff --git a/graalpython/com.oracle.graal.python.cext/src/typeobject.c b/graalpython/com.oracle.graal.python.cext/src/typeobject.c index 645bb730d1..7bcbcdbc2e 100644 --- a/graalpython/com.oracle.graal.python.cext/src/typeobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/typeobject.c @@ -192,7 +192,7 @@ int PyType_Ready(PyTypeObject* cls) { if (meth) { \ polyglot_invoke(PY_TRUFFLE_CEXT, \ "AddFunction", \ - javacls, \ + cls, \ polyglot_from_string((name), SRC_CS), \ (meth), \ (clanding), \ @@ -260,22 +260,6 @@ int PyType_Ready(PyTypeObject* cls) { PyDict_SetItemString(native_members, "tp_itemsize", PyLong_FromSsize_t(cls->tp_itemsize)); PyDict_SetItemString(native_members, "tp_dictoffset", PyLong_FromSsize_t(cls->tp_dictoffset)); const char* class_name = cls->tp_name; - PyTypeObject* javacls = polyglot_invoke(PY_TRUFFLE_CEXT, - "PyType_Ready", - // no conversion of cls here, because we - // store this into the PyTypeObject - cls, - native_to_java((PyObject*)metaclass), - native_to_java(bases), - native_to_java(native_members)); - - // remember the managed wrapper - ((PyObject*)cls)->ob_refcnt = javacls; - if (cls->tp_dict != NULL) { - javacls->tp_dict = native_to_java(cls->tp_dict); - } else { - cls->tp_dict = javacls->tp_dict; - } PyMethodDef* methods = cls->tp_methods; if (methods) { @@ -295,7 +279,7 @@ int PyType_Ready(PyTypeObject* cls) { int i = 0; PyMemberDef member = members[i]; while (member.name != NULL) { - ADD_MEMBER(javacls, polyglot_from_string(member.name, SRC_CS), member.type, member.offset, member.flags, member.doc); + ADD_MEMBER(cls, polyglot_from_string(member.name, SRC_CS), member.type, member.offset, member.flags, member.doc); member = members[++i]; } } @@ -310,7 +294,7 @@ int PyType_Ready(PyTypeObject* cls) { polyglot_invoke(PY_TRUFFLE_CEXT, "AddGetSet", // TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between - javacls, + cls, polyglot_from_string(getset.name, SRC_CS), getter_fun != NULL ? (getter)getter_fun : native_to_java(Py_None), wrap_direct, @@ -445,10 +429,11 @@ int PyType_Ready(PyTypeObject* cls) { // CPython doesn't do that in 'PyType_Ready' but we must because a native type can inherit // dynamic slots from a managed Python class. Since the managed Python class may be created // when the C API is not loaded, we need to do that later. - PyObject* inherited_slots_tuple = UPCALL_CEXT_O(_jls_PyTruffle_Type_Slots, native_to_java((PyObject*)javacls)); -// PyObject* inherited_slots_tuple = PyObject_GetAttrString(javacls, "__slots__"); +// PyObject* inherited_slots_tuple = UPCALL_CEXT_O(_jls_PyTruffle_Type_Slots, native_to_java((PyObject*)javacls)); + PyObject* inherited_slots_tuple = PyObject_GetAttrString(cls, "__slots__"); if(inherited_slots_tuple != NULL) { - PyTruffle_Type_AddSlots(javacls, inherited_slots_tuple); + PyTruffle_Debug(native_to_java(inherited_slots_tuple)); + PyTruffle_Type_AddSlots(cls, inherited_slots_tuple); } /* Link into each base class's list of subclasses */ @@ -464,10 +449,6 @@ int PyType_Ready(PyTypeObject* cls) { } } - // down-sync possibly re-computed attributes - cls->tp_dictoffset = javacls->tp_dictoffset; - cls->tp_basicsize = javacls->tp_basicsize; - // done cls->tp_flags = cls->tp_flags & ~Py_TPFLAGS_READYING; cls->tp_flags = cls->tp_flags | Py_TPFLAGS_READY; From a408651c5aa6fcc89e4b524dafcfe197d164944d Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 22 Jan 2019 13:18:14 +0100 Subject: [PATCH 059/202] Create 'PythonNativeClass' when reading from 'ob_type'. --- .../builtins/objects/cext/CExtNodes.java | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index 88d7762d02..40f01cfcff 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -418,6 +418,12 @@ public abstract static class AsPythonObjectNode extends CExtBaseNode { @Child private MaterializeDelegateNode materializeNode; @Child private IsPointerNode isPointerNode; + private final boolean forceNativeClass; + + public AsPythonObjectNode(boolean forceNativeClass) { + this.forceNativeClass = forceNativeClass; + } + public abstract Object execute(Object value); @Specialization(guards = "object.isBool()") @@ -459,6 +465,9 @@ Object doNativeWrapper(PythonNativeWrapper object) { PythonAbstractObject doNativeObject(TruffleObject object, @SuppressWarnings("unused") @Cached("create()") GetLazyClassNode getClassNode, @SuppressWarnings("unused") @Cached("create()") IsBuiltinClassProfile isForeignClassProfile) { + if (forceNativeClass) { + return factory().createNativeClassWrapper(object); + } return factory().createNativeObjectWrapper(object); } @@ -524,10 +533,13 @@ protected boolean isForeignObject(TruffleObject obj, GetLazyClassNode getClassNo } @TruffleBoundary - public static Object doSlowPath(Object object) { + public static Object doSlowPath(Object object, boolean forceNativeClass) { if (object instanceof PythonNativeWrapper) { return ((PythonNativeWrapper) object).getDelegate(); } else if (IsBuiltinClassProfile.profileClassSlowPath(GetClassNode.getItSlowPath(object), PythonBuiltinClassType.TruffleObject)) { + if (forceNativeClass) { + return PythonLanguage.getCore().factory().createNativeClassWrapper(object); + } return PythonLanguage.getCore().factory().createNativeObjectWrapper((TruffleObject) object); } else if (object instanceof Number || object instanceof Boolean) { return object; @@ -544,7 +556,11 @@ private MaterializeDelegateNode getMaterializeNode() { } public static AsPythonObjectNode create() { - return AsPythonObjectNodeGen.create(); + return AsPythonObjectNodeGen.create(false); + } + + static AsPythonObjectNode create(boolean forceNativeClass) { + return AsPythonObjectNodeGen.create(forceNativeClass); } } @@ -745,11 +761,11 @@ public static Object doSlowPath(Object value, boolean forcePointer) { return value; } else if (value instanceof Long) { String funName = forcePointer ? NativeCAPISymbols.FUN_NATIVE_LONG_TO_JAVA : NativeCAPISymbols.FUN_NATIVE_POINTER_TO_JAVA; - return AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(funName, value)); + return AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(funName, value), false); } else if (value instanceof PythonNativeWrapper) { - return AsPythonObjectNode.doSlowPath(value); + return AsPythonObjectNode.doSlowPath(value, false); } - return AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_NATIVE_TO_JAVA, value)); + return AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_NATIVE_TO_JAVA, value), false); } } @@ -848,16 +864,16 @@ public static FromCharPointerNode create() { public abstract static class GetNativeClassNode extends CExtBaseNode { @Child private PCallCapiFunction callGetObTypeNode; - @Child private ToJavaNode toJavaNode; + @Child private AsPythonObjectNode toJavaNode; @CompilationFinal private TruffleObject func; - public abstract PythonNativeClass execute(PythonAbstractObject object); + public abstract AbstractPythonClass execute(PythonAbstractObject object); @Specialization(guards = "object == cachedObject", limit = "1") - PythonNativeClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeObject object, + AbstractPythonClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeObject object, @SuppressWarnings("unused") @Cached("object") PythonNativeObject cachedObject, - @Cached("getNativeClass(cachedObject)") PythonNativeClass cachedClass) { + @Cached("getNativeClass(cachedObject)") AbstractPythonClass cachedClass) { // TODO: (tfel) is this really something we can do? It's so rare for this class to // change that it shouldn't be worth the effort, but in native code, anything can // happen. OTOH, CPython also has caches that can become invalid when someone just goes @@ -866,15 +882,15 @@ PythonNativeClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeO } @Specialization - PythonNativeClass getNativeClass(PythonNativeObject object) { + AbstractPythonClass getNativeClass(PythonNativeObject object) { // do not convert wrap 'object.object' since that is really the native pointer object - return (PythonNativeClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.object)); + return (AbstractPythonClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.object)); } @Specialization(guards = "object == cachedObject", limit = "1") - PythonNativeClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeClass object, + AbstractPythonClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeClass object, @SuppressWarnings("unused") @Cached("object") PythonNativeClass cachedObject, - @Cached("getNativeClass(cachedObject)") PythonNativeClass cachedClass) { + @Cached("getNativeClass(cachedObject)") AbstractPythonClass cachedClass) { // TODO: (tfel) is this really something we can do? It's so rare for this class to // change that it shouldn't be worth the effort, but in native code, anything can // happen. OTOH, CPython also has caches that can become invalid when someone just goes @@ -883,25 +899,25 @@ PythonNativeClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeC } @Specialization - PythonNativeClass getNativeClass(PythonNativeClass object) { + AbstractPythonClass getNativeClass(PythonNativeClass object) { // do not convert wrap 'object.object' since that is really the native pointer object - return (PythonNativeClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.getPtr())); + return (AbstractPythonClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.getPtr())); } @TruffleBoundary public static PythonNativeClass doSlowPath(PythonNativeObject object) { - return (PythonNativeClass) ToJavaNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.object), true); + return (PythonNativeClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.object), true); } @TruffleBoundary public static PythonNativeClass doSlowPath(PythonNativeClass object) { - return (PythonNativeClass) ToJavaNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.getPtr()), true); + return (PythonNativeClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.getPtr()), true); } - private ToJavaNode getToJavaNode() { + private AsPythonObjectNode getToJavaNode() { if (toJavaNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - toJavaNode = insert(ToJavaNode.create()); + toJavaNode = insert(AsPythonObjectNode.create(true)); } return toJavaNode; } @@ -1665,7 +1681,7 @@ public static Object doSlowPath(Object self, String memberName) { if (!NativeCAPISymbols.isValid(getterFuncName)) { throw new IllegalArgumentException("invalid native member getter function " + getterFuncName); } - return AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(getterFuncName, ToSulongNode.doSlowPath(self))); + return AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(getterFuncName, ToSulongNode.doSlowPath(self)), false); } public static GetTypeMemberNode create(String typeMember) { From 20e2be29acc8d9fcbd15f365c07b9333c6ea26d8 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 22 Jan 2019 13:32:37 +0100 Subject: [PATCH 060/202] Fix some invalid type checks. --- .../graal/python/builtins/modules/ImpModuleBuiltins.java | 2 +- .../graal/python/builtins/objects/cext/CExtNodes.java | 8 ++++---- .../objects/cext/PythonObjectNativeWrapperMR.java | 3 +-- .../oracle/graal/python/nodes/object/GetClassNode.java | 2 +- .../graal/python/nodes/object/GetLazyClassNode.java | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java index e67e415e9a..070fbe053a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java @@ -204,7 +204,7 @@ private Object loadDynamicModuleWithSpec(String name, String path, Node readNode // restore previous exception state getContext().setCaughtException(exceptionState); - Object result = AsPythonObjectNode.doSlowPath(nativeResult); + Object result = AsPythonObjectNode.doSlowPath(nativeResult, false); if (!(result instanceof PythonModule)) { // PyModuleDef_Init(pyModuleDef) // TODO: PyModule_FromDefAndSpec((PyModuleDef*)m, spec); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index 40f01cfcff..f8488abb29 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -905,13 +905,13 @@ AbstractPythonClass getNativeClass(PythonNativeClass object) { } @TruffleBoundary - public static PythonNativeClass doSlowPath(PythonNativeObject object) { - return (PythonNativeClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.object), true); + public static AbstractPythonClass doSlowPath(PythonNativeObject object) { + return (AbstractPythonClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.object), true); } @TruffleBoundary - public static PythonNativeClass doSlowPath(PythonNativeClass object) { - return (PythonNativeClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.getPtr()), true); + public static AbstractPythonClass doSlowPath(PythonNativeClass object) { + return (AbstractPythonClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.getPtr()), true); } private AsPythonObjectNode getToJavaNode() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index f6c29d8653..fdd6cfe855 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -1249,8 +1249,7 @@ private TruffleObject getPyObjectHandle_ForJavaObject() { } protected static boolean isManagedPythonClass(PythonClassNativeWrapper wrapper) { - assert wrapper.getDelegate() instanceof PythonClass; - return !(wrapper.getDelegate() instanceof PythonNativeClass); + return !PGuards.isNativeClass(wrapper.getDelegate()); } private Object callUnaryIntoCapi(TruffleObject fun, Object arg) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java index 584b554749..99fb39aa01 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java @@ -207,7 +207,7 @@ protected AbstractPythonClass getIt(PythonNativeObject object, } @Specialization - protected static PythonNativeClass getIt(PythonNativeClass object, + protected static AbstractPythonClass getIt(PythonNativeClass object, @Cached("create()") GetNativeClassNode getNativeClassNode) { return getNativeClassNode.execute(object); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java index 4ab3c90ae6..9fb8ee0840 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java @@ -142,13 +142,13 @@ protected static LazyPythonClass getIt(@SuppressWarnings("unused") PythonBuiltin } @Specialization - protected static PythonNativeClass getIt(PythonNativeObject object, + protected static LazyPythonClass getIt(PythonNativeObject object, @Cached("create()") GetNativeClassNode getNativeClassNode) { return getNativeClassNode.execute(object); } @Specialization - protected static PythonNativeClass getIt(PythonNativeClass object, + protected static LazyPythonClass getIt(PythonNativeClass object, @Cached("create()") GetNativeClassNode getNativeClassNode) { return getNativeClassNode.execute(object); } From e5f2a8cf6d9126f5dfda68e1c54d349909f6d1c3 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 22 Jan 2019 19:31:46 +0100 Subject: [PATCH 061/202] Introduce 'MroSequenceStorage' for representing native MRO tuple. --- .../com.oracle.graal.python.cext/src/capi.c | 12 +- .../src/typeobject.c | 31 ++- .../builtins/modules/TruffleCextBuiltins.java | 38 ++- .../builtins/objects/cext/CExtNodes.java | 8 +- .../objects/cext/NativeCAPISymbols.java | 2 + .../objects/cext/NativeMemberNames.java | 1 + .../objects/cext/PythonNativeClass.java | 4 + .../objects/common/SequenceStorageNodes.java | 10 + .../objects/type/ManagedPythonClass.java | 84 +------ .../builtins/objects/type/TypeBuiltins.java | 10 +- .../builtins/objects/type/TypeNodes.java | 158 ++++++++++++- .../attributes/LookupAttributeInMRONode.java | 11 +- .../WriteAttributeToObjectNode.java | 25 +- .../sequence/storage/MroSequenceStorage.java | 222 ++++++++++++++++++ graalpython/lib-graalpython/python_cext.py | 11 +- 15 files changed, 519 insertions(+), 108 deletions(-) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java diff --git a/graalpython/com.oracle.graal.python.cext/src/capi.c b/graalpython/com.oracle.graal.python.cext/src/capi.c index fe219e899b..f5d1ceeac6 100644 --- a/graalpython/com.oracle.graal.python.cext/src/capi.c +++ b/graalpython/com.oracle.graal.python.cext/src/capi.c @@ -264,11 +264,21 @@ PyObject* get_tp_dict(PyTypeObject* obj) { return native_to_java(obj->tp_dict); } -/** to be used from Java code only; reads native 'tp_dict' field */ +/** to be used from Java code only; reads native 'tp_bases' field */ PyObject* get_tp_bases(PyTypeObject* obj) { return native_to_java(obj->tp_bases); } +/** to be used from Java code only; reads native 'tp_name' field */ +PyObject* get_tp_name(PyTypeObject* obj) { + return polyglot_from_string(obj->tp_name, SRC_CS); +} + +/** to be used from Java code only; reads native 'tp_mro' field */ +PyObject* get_tp_mro(PyTypeObject* obj) { + return native_to_java(obj->tp_mro); +} + /** to be used from Java code only; returns the type ID for a byte array */ polyglot_typeid get_byte_array_typeid(uint64_t len) { return polyglot_array_typeid(polyglot_i8_typeid(), len); diff --git a/graalpython/com.oracle.graal.python.cext/src/typeobject.c b/graalpython/com.oracle.graal.python.cext/src/typeobject.c index 7bcbcdbc2e..3e3deafa3b 100644 --- a/graalpython/com.oracle.graal.python.cext/src/typeobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/typeobject.c @@ -183,7 +183,14 @@ UPCALL_ID(AddMember); UPCALL_ID(PyTruffle_Type_Slots); +UPCALL_ID(PyTruffle_Compute_Mro); int PyType_Ready(PyTypeObject* cls) { +#define RETURN_ERROR(__type__) \ + do { \ + (__type__)->tp_flags &= ~Py_TPFLAGS_READYING; \ + return -1; \ + } while(0) + #define ADD_IF_MISSING(attr, def) if (!(attr)) { attr = def; } #define ADD_METHOD(m) ADD_METHOD_OR_SLOT(m.ml_name, get_method_flags_cwrapper(m.ml_flags), m.ml_meth, m.ml_flags, m.ml_doc) #define ADD_SLOT(name, meth, flags) ADD_METHOD_OR_SLOT(name, get_method_flags_cwrapper(flags), meth, flags, name) @@ -192,7 +199,8 @@ int PyType_Ready(PyTypeObject* cls) { if (meth) { \ polyglot_invoke(PY_TRUFFLE_CEXT, \ "AddFunction", \ - cls, \ + cls, \ + native_to_java(dict), \ polyglot_from_string((name), SRC_CS), \ (meth), \ (clanding), \ @@ -227,8 +235,7 @@ int PyType_Ready(PyTypeObject* cls) { /* Initialize the base class */ if (base != NULL && !(base->tp_flags % Py_TPFLAGS_READY)) { if (PyType_Ready(base) < 0) { - cls->tp_flags &= ~Py_TPFLAGS_READYING; - return -1; + RETURN_ERROR(cls); } } @@ -261,6 +268,17 @@ int PyType_Ready(PyTypeObject* cls) { PyDict_SetItemString(native_members, "tp_dictoffset", PyLong_FromSsize_t(cls->tp_dictoffset)); const char* class_name = cls->tp_name; + /* Initialize tp_dict */ + PyObject* dict = cls->tp_dict; + if (dict == NULL) { + dict = PyDict_New(); + if (dict == NULL) { + RETURN_ERROR(cls); + } + cls->tp_dict = dict; + } + + PyMethodDef* methods = cls->tp_methods; if (methods) { int idx = 0; @@ -293,7 +311,6 @@ int PyType_Ready(PyTypeObject* cls) { setter setter_fun = getset.set; polyglot_invoke(PY_TRUFFLE_CEXT, "AddGetSet", - // TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between cls, polyglot_from_string(getset.name, SRC_CS), getter_fun != NULL ? (getter)getter_fun : native_to_java(Py_None), @@ -308,6 +325,9 @@ int PyType_Ready(PyTypeObject* cls) { } } + // initialize mro + cls->tp_mro = UPCALL_CEXT_O(_jls_PyTruffle_Compute_Mro, cls); + ADD_IF_MISSING(cls->tp_alloc, PyType_GenericAlloc); ADD_IF_MISSING(cls->tp_new, PyType_GenericNew); @@ -444,8 +464,7 @@ int PyType_Ready(PyTypeObject* cls) { PyObject* base_class_object = PyTuple_GetItem(bases, i); PyTypeObject* b = (PyTypeObject*) base_class_object; if (PyType_Check(b) && add_subclass(b, cls) < 0) { - cls->tp_flags &= ~Py_TPFLAGS_READYING; - return -1; + RETURN_ERROR(cls); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 9c21b0f495..304366cd6e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -126,6 +126,7 @@ import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; @@ -161,6 +162,7 @@ import com.oracle.graal.python.runtime.exception.PythonErrorType; import com.oracle.graal.python.runtime.object.PythonObjectFactory; import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; +import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage; import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; @@ -213,8 +215,8 @@ public void initialize(PythonCore core) { } /** - * Called mostly from our C code to convert arguments into a wrapped representation for - * consumption in Java. + * Called mostly from Python code to convert arguments into a wrapped representation for + * consumption in Python or Java. */ @Builtin(name = "to_java", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory @@ -226,6 +228,16 @@ Object run(Object object, } } + @Builtin(name = "to_java_type", fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + public abstract static class AsPythonClassNode extends PythonUnaryBuiltinNode { + @Specialization + Object run(Object object, + @Cached("createForceClass()") CExtNodes.AsPythonObjectNode toJavaNode) { + return toJavaNode.execute(object); + } + } + /** * Called from C when they actually want a {@code const char*} for a Python string */ @@ -529,6 +541,13 @@ Object setattr(PythonObject object, String key, Object value) { object.getStorage().define(key, value); return PNone.NONE; } + + @Specialization + Object setattr(PythonNativeClass object, String key, Object value, + @Cached("create()") WriteAttributeToObjectNode writeAttrNode) { + writeAttrNode.execute(object, key, value); + return PNone.NONE; + } } @Builtin(name = "PyType_Ready", fixedNumOfPositionalArgs = 4) @@ -768,7 +787,9 @@ private void checkFunctionResult(String name, boolean isNull) { } else if (errOccurred) { // consume exception context.setCurrentException(null); - throw raise(PythonErrorType.SystemError, "%s returned a result with an error set", name); + PBaseException sysExc = factory().createBaseException(PythonErrorType.SystemError, "%s returned a result with an error set", new Object[]{name}); + sysExc.setAttribute(SpecialAttributeNames.__CAUSE__, currentException.getExceptionObject()); + throw PException.fromObject(sysExc, this); } } @@ -2437,4 +2458,15 @@ int add(Object self, @SuppressWarnings("unused") Object o) { } } + + @Builtin(name = "PyTruffle_Compute_Mro", fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + public abstract static class PyTruffle_Compute_Mro extends PythonUnaryBuiltinNode { + + @Specialization + Object doIt(PythonNativeObject self) { + AbstractPythonClass[] doSlowPath = TypeNodes.ComputeMroNode.doSlowPath(PythonNativeClass.cast(self)); + return factory().createTuple(new MroSequenceStorage(doSlowPath)); + } + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index f8488abb29..a42048aaa6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -541,7 +541,7 @@ public static Object doSlowPath(Object object, boolean forceNativeClass) { return PythonLanguage.getCore().factory().createNativeClassWrapper(object); } return PythonLanguage.getCore().factory().createNativeObjectWrapper((TruffleObject) object); - } else if (object instanceof Number || object instanceof Boolean) { + } else if (object instanceof String || object instanceof Number || object instanceof Boolean || object instanceof PythonNativeNull || object instanceof PythonAbstractObject) { return object; } throw PythonLanguage.getCore().raise(PythonErrorType.SystemError, "invalid object from native: %s", object); @@ -562,6 +562,10 @@ public static AsPythonObjectNode create() { static AsPythonObjectNode create(boolean forceNativeClass) { return AsPythonObjectNodeGen.create(forceNativeClass); } + + public static AsPythonObjectNode createForceClass() { + return AsPythonObjectNodeGen.create(true); + } } /** @@ -917,7 +921,7 @@ public static AbstractPythonClass doSlowPath(PythonNativeClass object) { private AsPythonObjectNode getToJavaNode() { if (toJavaNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - toJavaNode = insert(AsPythonObjectNode.create(true)); + toJavaNode = insert(AsPythonObjectNode.createForceClass()); } return toJavaNode; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java index ad8c0d521c..a8039d1b96 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java @@ -62,6 +62,8 @@ public abstract class NativeCAPISymbols { public static final String FUN_GET_OB_TYPE = "get_ob_type"; public static final String FUN_GET_TP_DICT = "get_tp_dict"; public static final String FUN_GET_TP_BASES = "get_tp_bases"; + public static final String FUN_GET_TP_NAME = "get_tp_name"; + public static final String FUN_GET_TP_MRO = "get_tp_mro"; public static final String FUN_DEREF_HANDLE = "truffle_deref_handle_for_managed"; public static final String FUN_GET_BYTE_ARRAY_TYPE_ID = "get_byte_array_typeid"; public static final String FUN_GET_PTR_ARRAY_TYPE_ID = "get_ptr_array_typeid"; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java index 89ac910702..66481addfb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java @@ -57,6 +57,7 @@ public final class NativeMemberNames { public static final String TP_NAME = "tp_name"; public static final String TP_BASE = "tp_base"; public static final String TP_BASES = "tp_bases"; + public static final String TP_MRO = "tp_mro"; public static final String TP_BASICSIZE = "tp_basicsize"; public static final String TP_ITEMSIZE = "tp_itemsize"; public static final String TP_DICTOFFSET = "tp_dictoffset"; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java index f332bf9189..1f15a02e88 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java @@ -77,4 +77,8 @@ public void lookupChanged() { CompilerDirectives.transferToInterpreter(); throw new UnsupportedOperationException("not yet implemented"); } + + public static PythonNativeClass cast(PythonNativeObject object) { + return new PythonNativeClass(object.object); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java index 64670b2abe..d47d8b4714 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java @@ -51,6 +51,7 @@ import java.util.function.Function; import java.util.function.Supplier; +import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.objects.cext.CExtNodes; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.PCallCapiFunction; import com.oracle.graal.python.builtins.objects.cext.NativeCAPISymbols; @@ -3126,6 +3127,15 @@ public static ToArrayNode create() { public static ToArrayNode create(boolean exact) { return ToArrayNodeGen.create(exact); } + + @TruffleBoundary + public static Object[] doSlowPath(SequenceStorage s) { + if (s instanceof BasicSequenceStorage) { + return s.getInternalArray(); + } + // TODO implement remaining cases + throw PythonLanguage.getCore().raise(TypeError, "unsupported sequence type"); + } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java index 0159211d4d..9f364e5495 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java @@ -15,10 +15,10 @@ import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.object.PythonObject; -import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.ComputeMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode; +import com.oracle.graal.python.nodes.PGuards; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -67,7 +67,8 @@ public ManagedPythonClass(LazyPythonClass typeClass, String name, Shape instance this.lookupStableAssumption = new CyclicAssumption(className); // Compute MRO - computeMethodResolutionOrder(); + this.methodResolutionOrder = ComputeMroNode.doSlowPath(this); + computeNeedsNativeAllocation(); setAttribute(__NAME__, getBaseName(name)); setAttribute(__QUALNAME__, className); @@ -157,79 +158,14 @@ String getName() { return className; } - private void computeMethodResolutionOrder() { - CompilerAsserts.neverPartOfCompilation(); - - AbstractPythonClass[] currentMRO = null; - - if (getBaseClasses().length == 0) { - currentMRO = new AbstractPythonClass[]{this}; - } else if (getBaseClasses().length == 1) { - AbstractPythonClass[] baseMRO = GetMroNode.doSlowPath(getBaseClasses()[0]); - - if (baseMRO == null) { - currentMRO = new AbstractPythonClass[]{this}; - } else { - currentMRO = new AbstractPythonClass[baseMRO.length + 1]; - System.arraycopy(baseMRO, 0, currentMRO, 1, baseMRO.length); - currentMRO[0] = this; - } - } else { - MROMergeState[] toMerge = new MROMergeState[getBaseClasses().length + 1]; - - for (int i = 0; i < getBaseClasses().length; i++) { - toMerge[i] = new MROMergeState(); - toMerge[i].mro = GetMroNode.doSlowPath(getBaseClasses()[i]); - } - - toMerge[getBaseClasses().length] = new MROMergeState(); - toMerge[getBaseClasses().length].mro = getBaseClasses(); - ArrayList mro = new ArrayList<>(); - mro.add(this); - currentMRO = mergeMROs(toMerge, mro); - } - - for (AbstractPythonClass cls : currentMRO) { - if (cls instanceof PythonNativeClass) { + private void computeNeedsNativeAllocation() { + for (AbstractPythonClass cls : getMethodResolutionOrder()) { + if (PGuards.isNativeClass(cls)) { needsNativeAllocation = true; - break; - } - } - - methodResolutionOrder = currentMRO; - } - - AbstractPythonClass[] mergeMROs(MROMergeState[] toMerge, List mro) { - int idx; - scan: for (idx = 0; idx < toMerge.length; idx++) { - if (toMerge[idx].isMerged()) { - continue scan; - } - - AbstractPythonClass candidate = toMerge[idx].getCandidate(); - for (MROMergeState mergee : toMerge) { - if (mergee.pastnextContains(candidate)) { - continue scan; - } - } - - mro.add(candidate); - - for (MROMergeState element : toMerge) { - element.noteMerged(candidate); - } - - // restart scan - idx = -1; - } - - for (MROMergeState mergee : toMerge) { - if (!mergee.isMerged()) { - throw new IllegalStateException(); + return; } } - - return mro.toArray(new AbstractPythonClass[mro.size()]); + needsNativeAllocation = false; } @Override @@ -258,7 +194,7 @@ private void unsafeSetSuperClass(AbstractPythonClass... newBaseClasses) { GetSubclassesNode.doSlowPath(base).add(this); } } - computeMethodResolutionOrder(); + this.methodResolutionOrder = ComputeMroNode.doSlowPath(this); } final Set getSubClasses() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 92dd3ddf4c..4d392c7ee5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -60,6 +60,7 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodes; import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage; import com.oracle.graal.python.builtins.objects.common.PHashingCollection; import com.oracle.graal.python.builtins.objects.dict.PDict; @@ -343,12 +344,17 @@ protected Object doIt(LazyPythonClass object, Object key) { throw raise(AttributeError, "type object '%s' has no attribute %s", getTypeName(object), key); } - private Object readAttribute(Object object, Object key) { + @Specialization + protected Object doIt(PythonNativeObject object, Object key) { + return doIt(new PythonNativeClass(object.object), key); + } + + private Object readAttribute(LazyPythonClass object, Object key) { if (lookupAsClass == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); lookupAsClass = insert(LookupAttributeInMRONode.Dynamic.create()); } - return lookupAsClass.execute((LazyPythonClass) object, key); + return lookupAsClass.execute(object, key); } private Object lookupDelete(LazyPythonClass dataDescClass) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 01e44a8283..5b032532db 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -42,6 +42,8 @@ import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import com.oracle.graal.python.PythonLanguage; @@ -50,6 +52,7 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass.FlagsContainer; @@ -64,6 +67,9 @@ import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialMethodNames; +import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage; +import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; @@ -152,6 +158,7 @@ public static GetTypeFlagsNode create() { } } + @ImportStatic(NativeMemberNames.class) public abstract static class GetMroNode extends PNodeWithContext { public abstract AbstractPythonClass[] execute(Object obj); @@ -166,6 +173,19 @@ AbstractPythonClass[] doPythonClass(PythonBuiltinClassType obj) { return getBuiltinPythonClass(obj).getMethodResolutionOrder(); } + @Specialization + AbstractPythonClass[] doNativeClass(PythonNativeClass obj, + @Cached("create(TP_MRO)") GetTypeMemberNode getTpMroNode) { + Object tupleObj = getTpMroNode.execute(obj); + if (tupleObj instanceof PTuple) { + SequenceStorage sequenceStorage = ((PTuple) tupleObj).getSequenceStorage(); + if (sequenceStorage instanceof MroSequenceStorage) { + return ((MroSequenceStorage) sequenceStorage).getInternalClassArray(); + } + } + throw raise(PythonBuiltinClassType.SystemError, "invalid mro object"); + } + @TruffleBoundary public static AbstractPythonClass[] doSlowPath(Object obj) { if (obj instanceof ManagedPythonClass) { @@ -173,7 +193,14 @@ public static AbstractPythonClass[] doSlowPath(Object obj) { } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getMethodResolutionOrder(); } else if (obj instanceof PythonNativeClass) { - // TODO implement + Object tupleObj = GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_MRO); + if (tupleObj instanceof PTuple) { + SequenceStorage sequenceStorage = ((PTuple) tupleObj).getSequenceStorage(); + if (sequenceStorage instanceof MroSequenceStorage) { + return ((MroSequenceStorage) sequenceStorage).getInternalClassArray(); + } + } + throw PythonLanguage.getCore().raise(PythonBuiltinClassType.SystemError, "invalid mro object"); } throw new IllegalStateException("unknown type " + obj.getClass().getName()); } @@ -183,20 +210,27 @@ public static GetMroNode create() { } } + @ImportStatic(NativeMemberNames.class) public abstract static class GetNameNode extends PNodeWithContext { public abstract String execute(Object obj); @Specialization - String doPythonClass(ManagedPythonClass obj) { + String doManagedClass(ManagedPythonClass obj) { return obj.getName(); } @Specialization - String doPythonClass(PythonBuiltinClassType obj) { + String doBuiltinClassType(PythonBuiltinClassType obj) { return obj.getName(); } + @Specialization + String doNativeClass(PythonNativeClass obj, + @Cached("create(TP_NAME)") CExtNodes.GetTypeMemberNode getTpNameNode) { + return (String) getTpNameNode.execute(obj); + } + @TruffleBoundary public static String doSlowPath(Object obj) { if (obj instanceof ManagedPythonClass) { @@ -208,7 +242,7 @@ public static String doSlowPath(Object obj) { } return ((PythonBuiltinClassType) obj).getName(); } else if (obj instanceof PythonNativeClass) { - // TODO implement + return (String) CExtNodes.GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_NAME); } throw new IllegalStateException("unknown type " + obj.getClass().getName()); } @@ -308,7 +342,7 @@ AbstractPythonClass[] doNative(PythonNativeClass obj, if (result instanceof PTuple) { Object[] values = toArrayNode.execute(((PTuple) result).getSequenceStorage()); try { - return (AbstractPythonClass[]) values; + return cast(values); } catch (ClassCastException e) { throw raise(PythonBuiltinClassType.SystemError, "unsupported object in 'tp_bases'"); } @@ -323,8 +357,16 @@ public static AbstractPythonClass[] doSlowPath(Object obj) { } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getBaseClasses(); } else if (obj instanceof PythonNativeClass) { - // TODO implement - throw new UnsupportedOperationException("not yet implemented"); + Object basesObj = GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_BASES); + if (!(basesObj instanceof PTuple)) { + throw PythonLanguage.getCore().raise(PythonBuiltinClassType.SystemError, "invalid type of tp_bases (was %p)", basesObj); + } + PTuple basesTuple = (PTuple) basesObj; + try { + return cast(SequenceStorageNodes.ToArrayNode.doSlowPath(basesTuple.getSequenceStorage())); + } catch (ClassCastException e) { + throw PythonLanguage.getCore().raise(PythonBuiltinClassType.SystemError, "unsupported object in 'tp_bases' (msg: %s)", e.getMessage()); + } } throw new IllegalStateException("unknown type " + obj.getClass().getName()); } @@ -337,6 +379,15 @@ public static GetBaseClassesNode create() { return GetBaseClassesNodeGen.create(); } + // TODO: get rid of this + private static AbstractPythonClass[] cast(Object[] arr) { + AbstractPythonClass[] bases = new AbstractPythonClass[arr.length]; + for (int i = 0; i < arr.length; i++) { + bases[i] = (AbstractPythonClass) arr[i]; + } + return bases; + } + } @ImportStatic(SpecialMethodNames.class) @@ -355,6 +406,12 @@ boolean doNative(PythonNativeClass left, PythonNativeClass right, return pointerCompareNode.execute(left, right); } + @Specialization + boolean doNative(PythonNativeObject left, PythonNativeObject right, + @Cached("create(__EQ__)") CExtNodes.PointerCompareNode pointerCompareNode) { + return pointerCompareNode.execute(left, right); + } + @Fallback boolean doOther(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") Object right) { return false; @@ -366,6 +423,8 @@ public static boolean doSlowPath(Object left, Object right) { return left == right; } else if (left instanceof PythonNativeClass && right instanceof PythonNativeClass) { return CExtNodes.PointerCompareNode.create(__EQ__).execute((PythonNativeClass) left, (PythonNativeClass) right); + } else if (left instanceof PythonNativeObject && right instanceof PythonNativeObject) { + return CExtNodes.PointerCompareNode.create(__EQ__).execute((PythonNativeObject) left, (PythonNativeObject) right); } return false; } @@ -415,4 +474,89 @@ public static GetSulongTypeNode create() { } + public abstract static class ComputeMroNode extends Node { + + @TruffleBoundary + public static AbstractPythonClass[] doSlowPath(AbstractPythonClass cls) { + return computeMethodResolutionOrder(cls); + } + + private static AbstractPythonClass[] computeMethodResolutionOrder(AbstractPythonClass cls) { + CompilerAsserts.neverPartOfCompilation(); + + AbstractPythonClass[] currentMRO = null; + + AbstractPythonClass[] baseClasses = GetBaseClassesNode.doSlowPath(cls); + if (baseClasses.length == 0) { + currentMRO = new AbstractPythonClass[]{cls}; + } else if (baseClasses.length == 1) { + AbstractPythonClass[] baseMRO = GetMroNode.doSlowPath(baseClasses[0]); + + if (baseMRO == null) { + currentMRO = new AbstractPythonClass[]{cls}; + } else { + currentMRO = new AbstractPythonClass[baseMRO.length + 1]; + System.arraycopy(baseMRO, 0, currentMRO, 1, baseMRO.length); + currentMRO[0] = cls; + } + } else { + MROMergeState[] toMerge = new MROMergeState[baseClasses.length + 1]; + + for (int i = 0; i < baseClasses.length; i++) { + toMerge[i] = new MROMergeState(); + toMerge[i].mro = GetMroNode.doSlowPath(baseClasses[i]); + } + + toMerge[baseClasses.length] = new MROMergeState(); + toMerge[baseClasses.length].mro = baseClasses; + ArrayList mro = new ArrayList<>(); + mro.add(cls); + currentMRO = mergeMROs(toMerge, mro); + } + +// for (AbstractPythonClass c : currentMRO) { +// if (c instanceof PythonNativeClass) { +// needsNativeAllocation = true; +// break; +// } +// } + + return currentMRO; + } + + private static AbstractPythonClass[] mergeMROs(MROMergeState[] toMerge, List mro) { + int idx; + scan: for (idx = 0; idx < toMerge.length; idx++) { + if (toMerge[idx].isMerged()) { + continue scan; + } + + AbstractPythonClass candidate = toMerge[idx].getCandidate(); + for (MROMergeState mergee : toMerge) { + if (mergee.pastnextContains(candidate)) { + continue scan; + } + } + + mro.add(candidate); + + for (MROMergeState element : toMerge) { + element.noteMerged(candidate); + } + + // restart scan + idx = -1; + } + + for (MROMergeState mergee : toMerge) { + if (!mergee.isMerged()) { + throw new IllegalStateException(); + } + } + + return mro.toArray(new AbstractPythonClass[mro.size()]); + } + + } + } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index 6ecc118723..52288c1295 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -216,6 +216,13 @@ protected Object lookup(ManagedPythonClass klass, return lookupSlow(klass, key, getMroNode, readAttrNode); } + @Specialization + protected Object lookup(PythonNativeClass klass, + @Cached("create()") GetMroNode getMroNode, + @Cached("create()") ReadAttributeFromObjectNode readAttrNode) { + return lookupSlow(klass, key, getMroNode, readAttrNode); + } + protected AbstractPythonClass[] getMro(AbstractPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -224,8 +231,8 @@ protected AbstractPythonClass[] getMro(AbstractPythonClass clazz) { return getMroNode.execute(clazz); } - protected static Object lookupSlow(ManagedPythonClass klass, Object key, GetMroNode getMroNode, ReadAttributeFromObjectNode readAttrNode) { - AbstractPythonClass[] mro = getMroNode.doSlowPath(klass); + protected static Object lookupSlow(AbstractPythonClass klass, Object key, GetMroNode getMroNode, ReadAttributeFromObjectNode readAttrNode) { + AbstractPythonClass[] mro = getMroNode.execute(klass); for (int i = 0; i < mro.length; i++) { AbstractPythonClass kls = mro[i]; Object value = readAttrNode.execute(kls, key); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java index 8f0342811d..ac6a5631c2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java @@ -42,6 +42,9 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetObjectDictNode; +import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; +import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes; import com.oracle.graal.python.builtins.objects.common.HashingStorage; @@ -63,7 +66,7 @@ import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; -@ImportStatic(PythonOptions.class) +@ImportStatic({PythonOptions.class, NativeMemberNames.class}) public abstract class WriteAttributeToObjectNode extends ObjectAttributeNode { private final ConditionProfile isClassProfile = ConditionProfile.createBinaryProfile(); @@ -162,11 +165,8 @@ protected boolean writeToDict(PythonObject object, Object key, Object value, return true; } - @Specialization(guards = { - "!isHiddenKey(key)", - "!isPythonObject(object)" - }) - protected boolean readNative(PythonNativeObject object, Object key, Object value, + @Specialization(guards = "!isHiddenKey(key)") + protected boolean writeNative(PythonNativeObject object, Object key, Object value, @Cached("create()") GetObjectDictNode getNativeDict, @Cached("create()") HashingCollectionNodes.SetItemNode setItemNode) { Object d = getNativeDict.execute(object); @@ -178,6 +178,19 @@ protected boolean readNative(PythonNativeObject object, Object key, Object value } } + @Specialization(guards = "!isHiddenKey(key)") + protected boolean writeNativeClass(PythonNativeClass object, Object key, Object value, + @Cached("create(TP_DICT)") GetTypeMemberNode getNativeDict, + @Cached("create()") HashingCollectionNodes.SetItemNode setItemNode) { + Object d = getNativeDict.execute(object); + if (d instanceof PHashingCollection) { + setItemNode.execute(((PHashingCollection) d), key, value); + return true; + } else { + return raise(object, key, value); + } + } + @Fallback protected boolean raise(Object object, Object key, @SuppressWarnings("unused") Object value) { throw raise(PythonBuiltinClassType.AttributeError, "'%p' object has no attribute '%s'", object, key); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java new file mode 100644 index 0000000000..af2d62da3a --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. + * Copyright (c) 2013, Regents of the University of California + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.oracle.graal.python.runtime.sequence.storage; + +import java.util.Arrays; + +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.truffle.api.profiles.ConditionProfile; + +public final class MroSequenceStorage extends TypedSequenceStorage { + + private AbstractPythonClass[] values; + + public MroSequenceStorage(AbstractPythonClass[] elements) { + this.values = elements; + this.capacity = elements.length; + this.length = elements.length; + } + + public MroSequenceStorage(AbstractPythonClass[] elements, int length) { + this.values = elements; + this.capacity = elements.length; + this.length = length; + } + + public MroSequenceStorage(int capacity) { + this.values = new AbstractPythonClass[capacity]; + this.capacity = capacity; + this.length = 0; + } + + @Override + public Object getItemNormalized(int idx) { + return values[idx]; + } + + @Override + public void setItemNormalized(int idx, Object value) { + if (value instanceof AbstractPythonClass) { + setClassItemNormalized(idx, (AbstractPythonClass) value); + } else { + throw new SequenceStoreException(value); + } + } + + public void setClassItemNormalized(int idx, AbstractPythonClass value) { + values[idx] = value; + } + + @Override + public void insertItem(int idx, Object value) { + ensureCapacity(length + 1); + + // shifting tail to the right by one slot + for (int i = values.length - 1; i > idx; i--) { + values[i] = values[i - 1]; + } + + setItemNormalized(idx, value); + length++; + } + + @Override + public void copyItem(int idxTo, int idxFrom) { + values[idxTo] = values[idxFrom]; + } + + @Override + public MroSequenceStorage getSliceInBound(int start, int stop, int step, int sliceLength) { + AbstractPythonClass[] newArray = new AbstractPythonClass[sliceLength]; + + if (step == 1) { + System.arraycopy(values, start, newArray, 0, sliceLength); + return new MroSequenceStorage(newArray); + } + + for (int i = start, j = 0; j < sliceLength; i += step, j++) { + newArray[j] = values[i]; + } + + return new MroSequenceStorage(newArray); + } + + public void setObjectSliceInBound(int start, int stop, int step, MroSequenceStorage sequence, ConditionProfile sameLengthProfile) { + int otherLength = sequence.length(); + + // range is the whole sequence? + if (sameLengthProfile.profile(start == 0 && stop == length && step == 1)) { + values = Arrays.copyOf(sequence.values, otherLength); + length = otherLength; + minimizeCapacity(); + return; + } + + ensureCapacity(stop); + + for (int i = start, j = 0; i < stop; i += step, j++) { + values[i] = sequence.values[j]; + } + + length = length > stop ? length : stop; + } + + @Override + public SequenceStorage copy() { + return new MroSequenceStorage(Arrays.copyOf(values, length)); + } + + @Override + public SequenceStorage createEmpty(int newCapacity) { + return new MroSequenceStorage(newCapacity); + } + + @Override + public Object[] getInternalArray() { + return values; + } + + public AbstractPythonClass[] getInternalClassArray() { + return values; + } + + @Override + public void increaseCapacityExactWithCopy(int newCapacity) { + values = Arrays.copyOf(values, newCapacity); + capacity = values.length; + } + + @Override + public void increaseCapacityExact(int newCapacity) { + values = new AbstractPythonClass[newCapacity]; + capacity = values.length; + } + + public Object popObject() { + Object pop = values[length - 1]; + length--; + return pop; + } + + @Override + public void reverse() { + if (length > 0) { + int head = 0; + int tail = length - 1; + int middle = (length - 1) / 2; + + for (; head <= middle; head++, tail--) { + AbstractPythonClass temp = values[head]; + values[head] = values[tail]; + values[tail] = temp; + } + } + } + + @Override + public Object getIndicativeValue() { + return null; + } + + @Override + public boolean equals(SequenceStorage other) { + if (other.length() != length()) { + return false; + } + if (this == other) { + return true; + } + int nominalLength = length() <= other.length() ? length() : other.length(); + Object[] otherArray = other.getInternalArray(); + for (int i = 0; i < nominalLength; i++) { + if (!values[i].equals(otherArray[i])) { + return false; + } + } + + return true; + } + + @Override + public Object getInternalArrayObject() { + return values; + } + + @Override + public Object getCopyOfInternalArrayObject() { + return Arrays.copyOf(values, length); + } + + @Override + public void setInternalArrayObject(Object arrayObject) { + this.values = (AbstractPythonClass[]) arrayObject; + } + + @Override + public ListStorageType getElementType() { + return ListStorageType.Generic; + } +} diff --git a/graalpython/lib-graalpython/python_cext.py b/graalpython/lib-graalpython/python_cext.py index 690add5f0a..0dd8b721f3 100644 --- a/graalpython/lib-graalpython/python_cext.py +++ b/graalpython/lib-graalpython/python_cext.py @@ -748,8 +748,9 @@ def __call__(*args, **kwargs): return self.__func__(None, *args, **kwargs) -def AddFunction(primary, name, cfunc, cwrapper, wrapper, doc, isclass=False, isstatic=False): - owner = to_java(primary) +def AddFunction(primary, tpDict, name, cfunc, cwrapper, wrapper, doc, isclass=False, isstatic=False): + owner = to_java_type(primary) + type_dict = to_java(tpDict) if isinstance(owner, moduletype): # module case, we create the bound function-or-method func = PyCFunction_NewEx(name, cfunc, cwrapper, wrapper, owner, owner.__name__, doc) @@ -766,9 +767,9 @@ def AddFunction(primary, name, cfunc, cwrapper, wrapper, doc, isclass=False, iss def __init__(self, *args, **kwargs): if func(self, *args, **kwargs) != 0: raise TypeError("__init__ failed") - object.__setattr__(owner, name, __init__) + type_dict[name] = __init__ else: - object.__setattr__(owner, name, func) + type_dict[name] = func def PyCFunction_NewEx(name, cfunc, cwrapper, wrapper, self, module, doc): @@ -808,7 +809,7 @@ def member_setter(self, value): getset_descriptor = type(type(AddMember).__code__) def AddGetSet(primary, name, getter, getter_wrapper, setter, setter_wrapper, doc, closure): - pclass = to_java(primary) + pclass = to_java_type(primary) fset = fget = None if getter: getter_w = CreateFunction(name, getter, getter_wrapper, pclass) From 6548c080b8bc9417c722ad6e152a256ee0d53ef6 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 22 Jan 2019 21:42:37 +0100 Subject: [PATCH 062/202] Improve stack traces of exceptions from native code. --- .../graal/python/builtins/modules/ImpModuleBuiltins.java | 3 ++- .../graal/python/builtins/modules/TruffleCextBuiltins.java | 2 ++ .../oracle/graal/python/builtins/objects/cext/CExtNodes.java | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java index 070fbe053a..1e63a76a34 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java @@ -274,15 +274,16 @@ private CheckFunctionResultNode getCheckResultNode() { @TruffleBoundary private PException reportImportError(RuntimeException e, String path) { StringBuilder sb = new StringBuilder(); + Object pythonCause = PNone.NONE; if (e instanceof PException) { PBaseException excObj = ((PException) e).getExceptionObject(); + pythonCause = excObj; sb.append(callReprNode.executeObject(excObj)); } else { // that call will cause problems if the format string contains '%p' sb.append(e.getMessage()); } Throwable cause = e; - Object pythonCause = PNone.NONE; while ((cause = cause.getCause()) != null) { if (e instanceof PException) { if (pythonCause != PNone.NONE) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 304366cd6e..8bc9fe6268 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -782,12 +782,14 @@ private void checkFunctionResult(String name, boolean isNull) { if (!errOccurred) { throw raise(PythonErrorType.SystemError, "%s returned NULL without setting an error", name); } else { + currentException.getExceptionObject().reifyException(); throw currentException; } } else if (errOccurred) { // consume exception context.setCurrentException(null); PBaseException sysExc = factory().createBaseException(PythonErrorType.SystemError, "%s returned a result with an error set", new Object[]{name}); + currentException.getExceptionObject().reifyException(); sysExc.setAttribute(SpecialAttributeNames.__CAUSE__, currentException.getExceptionObject()); throw PException.fromObject(sysExc, this); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index a42048aaa6..ac06e30e03 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -1501,6 +1501,7 @@ Object doit(Object argument) { } catch (PException e) { // getContext() acts as a branch profile getContext().setCurrentException(e); + e.getExceptionObject().reifyException(); return errorResult; } } @@ -1526,6 +1527,7 @@ Object doit(Object arg1, Object arg2) { } catch (PException e) { // getContext() acts as a branch profile getContext().setCurrentException(e); + e.getExceptionObject().reifyException(); return errorResult; } } @@ -1551,6 +1553,7 @@ Object doit(Object arg1, Object arg2, Object arg3) { } catch (PException e) { // getContext() acts as a branch profile getContext().setCurrentException(e); + e.getExceptionObject().reifyException(); return errorResult; } } @@ -1580,6 +1583,7 @@ public final Object execute(VirtualFrame frame) { } catch (PException e) { // getContext() acts as a branch profile getContext().setCurrentException(e); + e.getExceptionObject().reifyException(); return errorResult; } } From b37d810540a8b5353a4f44ad434182a91f6aff86 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 22 Jan 2019 22:29:44 +0100 Subject: [PATCH 063/202] Accept more 'PythonNativeObject' as potential native class. --- .../cext/PythonObjectNativeWrapperMR.java | 3 +- .../function/BuiltinFunctionBuiltins.java | 4 +- .../builtins/objects/type/TypeBuiltins.java | 44 ++++++++++++++++--- .../graal/python/nodes/PNodeWithContext.java | 10 ++--- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index fdd6cfe855..c2c277f7c0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -225,9 +225,8 @@ Object doBuiltinCached(@SuppressWarnings("unused") PythonBuiltinClassType clazz, @Specialization(replaces = "doBuiltinCached") Object doBuiltinGeneric(PythonBuiltinClassType clazz, @Cached("create()") TypeNodes.GetSulongTypeNode getSulongTypeNode, - @Cached("createBinaryProfile()") ConditionProfile profile, @Cached("createBinaryProfile()") ConditionProfile hasSulongTypeProfile) { - ManagedPythonClass pythonClass = getPythonClass(clazz, profile); + PythonBuiltinClass pythonClass = getBuiltinPythonClass(clazz); return doManagedGeneric(pythonClass, getSulongTypeNode, hasSulongTypeProfile); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java index 4bb66e9173..50268fe18a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java @@ -34,7 +34,7 @@ import com.oracle.graal.python.builtins.CoreFunctions; import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.PythonBuiltins; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; @@ -85,7 +85,7 @@ Object objclassMissing(@SuppressWarnings("unused") PBuiltinFunction self) { @Specialization(guards = "self.getEnclosingType() != null") @TruffleBoundary - ManagedPythonClass objclass(PBuiltinFunction self, + AbstractPythonClass objclass(PBuiltinFunction self, @Cached("createBinaryProfile()") ConditionProfile profile) { return getPythonClass(self.getEnclosingType(), profile); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 4d392c7ee5..7fbb1bf776 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -104,6 +104,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; @CoreFunctions(extendClasses = PythonBuiltinClassType.PythonClass) public class TypeBuiltins extends PythonBuiltins { @@ -183,20 +184,38 @@ public final Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeywo return execute(frame, PNone.NO_VALUE, arguments, keywords); } - protected AbstractPythonClass first(Object[] ary) { - return (AbstractPythonClass) ary[0]; + protected static Object first(Object[] ary) { + return ary[0]; } - @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"first(arguments) == cachedSelf"}) + protected static boolean isClass(Object object) { + return PGuards.isClass(object) || PGuards.isNativeObject(object); + } + + protected static boolean accept(Object[] ary, Object cachedSelf) { + Object first = first(ary); + return first == cachedSelf && isClass(first); + } + + @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"accept(arguments, cachedSelf)"}) protected Object doItUnboxed(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords, - @Cached("first(arguments)") AbstractPythonClass cachedSelf) { - return op(frame, cachedSelf, arguments, keywords, false); + @Cached("first(arguments)") Object cachedSelf, + @Cached("createClassProfile()") ValueProfile profile) { + Object profiled = profile.profile(cachedSelf); + if (profiled instanceof PythonNativeObject) { + return op(frame, PythonNativeClass.cast((PythonNativeObject) cachedSelf), arguments, keywords, false); + } + return op(frame, (AbstractPythonClass) cachedSelf, arguments, keywords, false); + } @Specialization(replaces = "doItUnboxed") protected Object doItUnboxedIndirect(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords) { - AbstractPythonClass self = (AbstractPythonClass) arguments[0]; - return op(frame, self, arguments, keywords, false); + Object self = arguments[0]; + if (self instanceof PythonNativeObject) { + return op(frame, PythonNativeClass.cast((PythonNativeObject) self), arguments, keywords, false); + } + return op(frame, (AbstractPythonClass) self, arguments, keywords, false); } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf"}) @@ -210,6 +229,17 @@ protected Object doItIndirect(VirtualFrame frame, AbstractPythonClass self, Obje return op(frame, self, arguments, keywords, true); } + @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf"}) + protected Object doIt(VirtualFrame frame, @SuppressWarnings("unused") PythonNativeObject self, Object[] arguments, PKeyword[] keywords, + @Cached("self") PythonNativeObject cachedSelf) { + return op(frame, PythonNativeClass.cast(cachedSelf), arguments, keywords, true); + } + + @Specialization(replaces = "doIt") + protected Object doItIndirect(VirtualFrame frame, PythonNativeObject self, Object[] arguments, PKeyword[] keywords) { + return op(frame, PythonNativeClass.cast(self), arguments, keywords, true); + } + private Object op(VirtualFrame frame, AbstractPythonClass self, Object[] arguments, PKeyword[] keywords, boolean doCreateArgs) { Object newMethod = lookupNew.execute(self); if (newMethod != PNone.NO_VALUE) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java index e272add5ed..194a443f78 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNodeWithContext.java @@ -46,8 +46,8 @@ import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum; import com.oracle.graal.python.builtins.objects.exception.PBaseException; import com.oracle.graal.python.builtins.objects.function.PKeyword; +import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; import com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode; @@ -153,11 +153,11 @@ public final PException raiseOSError(VirtualFrame frame, Object[] args) { return raise(error); } - public final ManagedPythonClass getPythonClass(LazyPythonClass lazyClass, ConditionProfile profile) { - if (profile.profile(lazyClass instanceof ManagedPythonClass)) { - return (ManagedPythonClass) lazyClass; - } else { + public final AbstractPythonClass getPythonClass(LazyPythonClass lazyClass, ConditionProfile profile) { + if (profile.profile(lazyClass instanceof PythonBuiltinClassType)) { return getCore().lookupType((PythonBuiltinClassType) lazyClass); + } else { + return (AbstractPythonClass) lazyClass; } } From c8be99dcb7ca7df4e127296b3e0082f24e70477e Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 22 Jan 2019 22:51:05 +0100 Subject: [PATCH 064/202] Fix: 'AddFunction' for modules does not need a type dict. --- graalpython/com.oracle.graal.python.cext/src/moduleobject.c | 1 + graalpython/lib-graalpython/python_cext.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/moduleobject.c b/graalpython/com.oracle.graal.python.cext/src/moduleobject.c index 2abaca6960..be4dfda6dc 100644 --- a/graalpython/com.oracle.graal.python.cext/src/moduleobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/moduleobject.c @@ -53,6 +53,7 @@ int PyModule_AddFunctions(PyObject* mod, PyMethodDef* methods) { polyglot_invoke(PY_TRUFFLE_CEXT, "AddFunction", native_to_java(mod), + NULL, polyglot_from_string((const char*)(def.ml_name), SRC_CS), def.ml_meth, get_method_flags_cwrapper(def.ml_flags), diff --git a/graalpython/lib-graalpython/python_cext.py b/graalpython/lib-graalpython/python_cext.py index 0dd8b721f3..93b58cbb71 100644 --- a/graalpython/lib-graalpython/python_cext.py +++ b/graalpython/lib-graalpython/python_cext.py @@ -750,7 +750,6 @@ def __call__(*args, **kwargs): def AddFunction(primary, tpDict, name, cfunc, cwrapper, wrapper, doc, isclass=False, isstatic=False): owner = to_java_type(primary) - type_dict = to_java(tpDict) if isinstance(owner, moduletype): # module case, we create the bound function-or-method func = PyCFunction_NewEx(name, cfunc, cwrapper, wrapper, owner, owner.__name__, doc) @@ -763,6 +762,7 @@ def AddFunction(primary, tpDict, name, cfunc, cwrapper, wrapper, doc, isclass=Fa func = cstaticmethod(func) PyTruffle_SetAttr(func, "__name__", name) PyTruffle_SetAttr(func, "__doc__", doc) + type_dict = to_java(tpDict) if name == "__init__": def __init__(self, *args, **kwargs): if func(self, *args, **kwargs) != 0: From a6833111b47cd7ebbe278283254644d7d243948b Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 22 Jan 2019 22:53:23 +0100 Subject: [PATCH 065/202] Fix: incorrectly ran into error case. --- .../oracle/graal/python/builtins/objects/type/TypeNodes.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 5b032532db..e76fda2c20 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -464,8 +464,9 @@ public static Object getSlowPath(AbstractPythonClass clazz) { public static void setSlowPath(AbstractPythonClass clazz, Object sulongType) { if (clazz instanceof ManagedPythonClass) { ((ManagedPythonClass) clazz).setSulongType(sulongType); + } else { + throw new IllegalStateException("cannot set Sulong type for " + clazz.getClass().getName()); } - throw new IllegalStateException("cannot set Sulong type for " + clazz.getClass().getName()); } public static GetSulongTypeNode create() { From e01390b96aed097e29bed9884d1a5f3b9fce9b92 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 22 Jan 2019 23:17:45 +0100 Subject: [PATCH 066/202] Pass type dict to 'AddMember'. --- .../src/typeobject.c | 32 ++++++++++--------- graalpython/lib-graalpython/python_cext.py | 7 ++-- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/typeobject.c b/graalpython/com.oracle.graal.python.cext/src/typeobject.c index 3e3deafa3b..304d8917b2 100644 --- a/graalpython/com.oracle.graal.python.cext/src/typeobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/typeobject.c @@ -171,14 +171,16 @@ static PyObject* wrap_reverse_binop(binaryfunc f, PyObject* a, PyObject* b) { // TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between // TODO support member flags other than READONLY UPCALL_ID(AddMember); -#define ADD_MEMBER(__javacls__, __mname__, __mtype__, __moffset__, __mflags__, __mdoc__) do { \ - UPCALL_CEXT_VOID(_jls_AddMember, \ - (__javacls__), \ - (__mname__), \ - (__mtype__), \ - (__moffset__), \ - native_to_java((((__mflags__) & READONLY) == 0) ? Py_True : Py_False), \ - polyglot_from_string((__mdoc__) ? (__mdoc__) : "", SRC_CS)); \ +#define ADD_MEMBER(__javacls__, __tpdict__, __mname__, __mtype__, __moffset__, __mflags__, __mdoc__) \ + do { \ + UPCALL_CEXT_VOID(_jls_AddMember, \ + (__javacls__), \ + native_to_java(__tpdict__), \ + (__mname__), \ + (__mtype__), \ + (__moffset__), \ + native_to_java((((__mflags__) & READONLY) == 0) ? Py_True : Py_False), \ + polyglot_from_string((__mdoc__) ? (__mdoc__) : "", SRC_CS)); \ } while (0) @@ -297,7 +299,7 @@ int PyType_Ready(PyTypeObject* cls) { int i = 0; PyMemberDef member = members[i]; while (member.name != NULL) { - ADD_MEMBER(cls, polyglot_from_string(member.name, SRC_CS), member.type, member.offset, member.flags, member.doc); + ADD_MEMBER(cls, dict, polyglot_from_string(member.name, SRC_CS), member.type, member.offset, member.flags, member.doc); member = members[++i]; } } @@ -450,11 +452,11 @@ int PyType_Ready(PyTypeObject* cls) { // dynamic slots from a managed Python class. Since the managed Python class may be created // when the C API is not loaded, we need to do that later. // PyObject* inherited_slots_tuple = UPCALL_CEXT_O(_jls_PyTruffle_Type_Slots, native_to_java((PyObject*)javacls)); - PyObject* inherited_slots_tuple = PyObject_GetAttrString(cls, "__slots__"); - if(inherited_slots_tuple != NULL) { - PyTruffle_Debug(native_to_java(inherited_slots_tuple)); - PyTruffle_Type_AddSlots(cls, inherited_slots_tuple); - } +// PyObject* inherited_slots_tuple = PyObject_GetAttrString(cls, "__slots__"); +// if(inherited_slots_tuple != NULL) { +// PyTruffle_Debug(native_to_java(inherited_slots_tuple)); +// PyTruffle_Type_AddSlots(cls, inherited_slots_tuple); +// } /* Link into each base class's list of subclasses */ bases = cls->tp_bases; @@ -515,7 +517,7 @@ Py_ssize_t PyTruffle_Type_AddSlots(PyTypeObject* cls, PyObject* slotsTuple) { for(i = 0; i < slotLen; i++) { slot = PyTuple_GetItem(slotsTuple, i); // note: no flags and no doc (see typeobject.c in function 'type_new') - ADD_MEMBER(native_to_java(cls), slot, T_OBJECT_EX, cur_offset, 0, NULL); + ADD_MEMBER(cls, cls->tp_dict, slot, T_OBJECT_EX, cur_offset, 0, NULL); cur_offset += sizeof(PyObject*); dictoffset += sizeof(PyObject*); } diff --git a/graalpython/lib-graalpython/python_cext.py b/graalpython/lib-graalpython/python_cext.py index 93b58cbb71..842cb8f331 100644 --- a/graalpython/lib-graalpython/python_cext.py +++ b/graalpython/lib-graalpython/python_cext.py @@ -789,10 +789,10 @@ def bound_function(*args, **kwargs): return bound_function -def AddMember(primary, name, memberType, offset, canSet, doc): +def AddMember(primary, tpDict, name, memberType, offset, canSet, doc): # the ReadMemberFunctions and WriteMemberFunctions don't have a wrapper to # convert arguments to Sulong, so we can avoid boxing the offsets into PInts - pclass = primary + pclass = to_java_type(primary) member = property() getter = ReadMemberFunctions[memberType] def member_getter(self): @@ -804,7 +804,8 @@ def member_setter(self, value): setter(to_sulong(self), TrufflePInt_AsPrimitive(offset, 1, 8), to_sulong(value)) member.setter(member_setter) member.__doc__ = doc - object.__setattr__(pclass, name, member) + type_dict = to_java(tpDict) + type_dict[name] = member getset_descriptor = type(type(AddMember).__code__) From 446f9dee3cd33d045e020f494afe30e446fdd57f Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 10:37:47 +0100 Subject: [PATCH 067/202] Introduce 'PythonAbstractNativeObject'. --- .../builtins/objects/cext/CExtNodes.java | 10 +--- .../cext/PythonAbstractNativeObject.java | 58 +++++++++++++++++++ .../objects/cext/PythonNativeClass.java | 20 +++---- .../objects/cext/PythonNativeObject.java | 12 +--- .../graal/python/nodes/expression/IsNode.java | 4 +- .../runtime/object/PythonObjectFactory.java | 2 +- 6 files changed, 74 insertions(+), 32 deletions(-) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index ac06e30e03..e7ad063b2a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -538,7 +538,7 @@ public static Object doSlowPath(Object object, boolean forceNativeClass) { return ((PythonNativeWrapper) object).getDelegate(); } else if (IsBuiltinClassProfile.profileClassSlowPath(GetClassNode.getItSlowPath(object), PythonBuiltinClassType.TruffleObject)) { if (forceNativeClass) { - return PythonLanguage.getCore().factory().createNativeClassWrapper(object); + return PythonLanguage.getCore().factory().createNativeClassWrapper((TruffleObject) object); } return PythonLanguage.getCore().factory().createNativeObjectWrapper((TruffleObject) object); } else if (object instanceof String || object instanceof Number || object instanceof Boolean || object instanceof PythonNativeNull || object instanceof PythonAbstractObject) { @@ -980,15 +980,11 @@ private boolean executeCFunction(Object a, Object b) { } } - public boolean execute(PythonNativeClass a, PythonNativeClass b) { - return executeCFunction(a.getPtr(), b.getPtr()); - } - - public boolean execute(PythonNativeObject a, PythonNativeObject b) { + public boolean execute(PythonAbstractNativeObject a, PythonAbstractNativeObject b) { return executeCFunction(a.object, b.object); } - public boolean execute(PythonNativeObject a, long b) { + public boolean execute(PythonAbstractNativeObject a, long b) { return executeCFunction(a.object, b); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java new file mode 100644 index 0000000000..b5de264b87 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, 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 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.builtins.objects.cext; + +import com.oracle.graal.python.builtins.objects.PythonAbstractObject; +import com.oracle.truffle.api.interop.TruffleObject; + +public class PythonAbstractNativeObject extends PythonAbstractObject { + + public final TruffleObject object; + + public PythonAbstractNativeObject(TruffleObject object) { + this.object = object; + } + + public int compareTo(Object o) { + return 0; + } + +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java index 1f15a02e88..8355f9b038 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -40,9 +40,9 @@ */ package com.oracle.graal.python.builtins.objects.cext; -import com.oracle.graal.python.builtins.objects.PythonAbstractObject; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.object.Shape; /** @@ -51,20 +51,14 @@ * types are assumed to be mutated afterwards, so accessing the struct in native mode would work, * but our copy should just never become stale. */ -public final class PythonNativeClass extends PythonAbstractObject implements AbstractPythonClass { - public final Object ptr; +public final class PythonNativeClass extends PythonAbstractNativeObject implements AbstractPythonClass { - public PythonNativeClass(Object ptr) { - this.ptr = ptr; + public PythonNativeClass(TruffleObject ptr) { + super(ptr); } - public Object getPtr() { - return ptr; - } - - public int compareTo(Object o) { - CompilerDirectives.transferToInterpreter(); - throw new UnsupportedOperationException("cannot compare native class to anything else"); + public TruffleObject getPtr() { + return object; } public Shape getInstanceShape() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeObject.java index 506ae6f095..8c65778599 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -40,20 +40,14 @@ */ package com.oracle.graal.python.builtins.objects.cext; -import com.oracle.graal.python.builtins.objects.PythonAbstractObject; import com.oracle.truffle.api.interop.TruffleObject; /** * A simple wrapper around objects created through the Python C API that can be cast to PyObject*. */ -public class PythonNativeObject extends PythonAbstractObject { - public final TruffleObject object; +public class PythonNativeObject extends PythonAbstractNativeObject { public PythonNativeObject(TruffleObject obj) { - object = obj; - } - - public int compareTo(Object o) { - return 0; + super(obj); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/IsNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/IsNode.java index 67403649b6..817be7bb3d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/IsNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/IsNode.java @@ -41,7 +41,7 @@ package com.oracle.graal.python.nodes.expression; import com.oracle.graal.python.builtins.objects.cext.CExtNodes; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -164,7 +164,7 @@ boolean doDD(double left, double right) { } @Specialization - boolean doNative(PythonNativeObject left, PythonNativeObject right, + boolean doNative(PythonAbstractNativeObject left, PythonAbstractNativeObject right, @Cached("create(__EQ__)") CExtNodes.PointerCompareNode isNode) { return isNode.execute(left, right); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index dd7ce2d10d..06f71783bd 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -358,7 +358,7 @@ public PythonClass createPythonClass(LazyPythonClass metaclass, String name, Abs return trace(new PythonClass(metaclass, name, PythonLanguage.freshShape(), bases)); } - public PythonNativeClass createNativeClassWrapper(Object ptr) { + public PythonNativeClass createNativeClassWrapper(TruffleObject ptr) { return trace(new PythonNativeClass(ptr)); } From c46343da3ede9c367c69535e3af3eb2d7b4f69ca Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 12:07:18 +0100 Subject: [PATCH 068/202] Implement getter for '__module__'/'__name__' of native types. --- .../objects/object/ObjectBuiltins.java | 14 +++-- .../builtins/objects/type/TypeBuiltins.java | 63 +++++++++++++++++-- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java index 172f16e88f..5957ccaf5b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java @@ -28,8 +28,6 @@ import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CLASS__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICT__; -import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MODULE__; -import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__SLOTS__; import static com.oracle.graal.python.nodes.SpecialMethodNames.RICHCMP; import static com.oracle.graal.python.nodes.SpecialMethodNames.__BOOL__; @@ -71,6 +69,8 @@ import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.nodes.PGuards; +import com.oracle.graal.python.nodes.SpecialAttributeNames; +import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetFixedAttributeNode; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; @@ -93,6 +93,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; @@ -289,19 +290,20 @@ public Object str(Object self, @Builtin(name = __REPR__, fixedNumOfPositionalArgs = 1) @GenerateNodeFactory + @ImportStatic(SpecialAttributeNames.class) public abstract static class ReprNode extends PythonUnaryBuiltinNode { @Specialization @TruffleBoundary String repr(Object self, @Cached("create()") GetClassNode getClass, - @Cached("create()") ReadAttributeFromObjectNode readModuleNode, - @Cached("create()") ReadAttributeFromObjectNode readQualNameNode) { + @Cached("create(__MODULE__)") GetFixedAttributeNode readModuleNode, + @Cached("create(__QUALNAME__)") GetFixedAttributeNode readQualNameNode) { if (self == PNone.NONE) { return "None"; } AbstractPythonClass type = getClass.execute(self); - Object moduleName = readModuleNode.execute(type, __MODULE__); - Object qualName = readQualNameNode.execute(type, __QUALNAME__); + Object moduleName = readModuleNode.executeObject(type); + Object qualName = readQualNameNode.executeObject(type); if (moduleName != PNone.NO_VALUE && !moduleName.equals(getCore().getBuiltins().getModuleName())) { return String.format("<%s.%s object at 0x%x>", moduleName, qualName, self.hashCode()); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 7fbb1bf776..606eee7623 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -32,7 +32,6 @@ import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MODULE__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MRO__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__; -import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__CALL__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__DELETE__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__; @@ -58,7 +57,9 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.cext.CExtNodes; +import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage; @@ -72,7 +73,9 @@ import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode; import com.oracle.graal.python.nodes.PGuards; +import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.argument.positional.PositionalArgumentsNode; +import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetFixedAttributeNode; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; @@ -116,14 +119,15 @@ protected List> getNodeFa @Builtin(name = __REPR__, fixedNumOfPositionalArgs = 1) @GenerateNodeFactory + @ImportStatic(SpecialAttributeNames.class) public abstract static class ReprNode extends PythonUnaryBuiltinNode { @Specialization - public String repr(AbstractPythonClass self, - @Cached("create()") ReadAttributeFromObjectNode readModuleNode, - @Cached("create()") ReadAttributeFromObjectNode readQualNameNode) { - Object moduleName = readModuleNode.execute(self, __MODULE__); - Object qualName = readQualNameNode.execute(self, __QUALNAME__); + String repr(AbstractPythonClass self, + @Cached("create(__MODULE__)") GetFixedAttributeNode readModuleNode, + @Cached("create(__QUALNAME__)") GetFixedAttributeNode readQualNameNode) { + Object moduleName = readModuleNode.executeObject(self); + Object qualName = readQualNameNode.executeObject(self); return concat(moduleName, qualName); } @@ -557,6 +561,7 @@ private static Object[] toArray(Set subclasses) { @Builtin(name = __NAME__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) @GenerateNodeFactory + @ImportStatic(NativeMemberNames.class) static abstract class NameNode extends PythonBinaryBuiltinNode { @Specialization(guards = "isNoValue(value)") String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { @@ -579,10 +584,34 @@ Object setName(PythonClass cls, Object value, @Cached("create()") WriteAttributeToObjectNode setName) { return setName.execute(cls, __NAME__, value); } + + @Specialization(guards = "isNoValue(value)") + Object getModule(PythonAbstractNativeObject cls, @SuppressWarnings("unused") PNone value, + @Cached("create(TP_NAME)") GetTypeMemberNode getTpNameNode) { + // 'tp_name' contains the fully-qualified name, i.e., 'module.A.B...' + String tpName = (String) getTpNameNode.execute(cls); + return getQualName(tpName); + } + + @Specialization(guards = "!isNoValue(value)") + Object getModule(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type"); + } + + @TruffleBoundary + private static String getQualName(String fqname) { + int firstDot = fqname.indexOf('.'); + if (firstDot != -1) { + return fqname.substring(firstDot + 1); + } + return fqname; + } + } @Builtin(name = __MODULE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) @GenerateNodeFactory + @ImportStatic(NativeMemberNames.class) static abstract class ModuleNode extends PythonBinaryBuiltinNode { @Specialization(guards = "isNoValue(value)") @@ -607,5 +636,27 @@ Object setModule(PythonClass cls, Object value, writeAttrNode.execute(cls, __MODULE__, value); return PNone.NONE; } + + @Specialization(guards = "isNoValue(value)") + Object getModule(PythonAbstractNativeObject cls, @SuppressWarnings("unused") PNone value, + @Cached("create(TP_NAME)") GetTypeMemberNode getTpNameNode) { + // 'tp_name' contains the fully-qualified name, i.e., 'module.A.B...' + String tpName = (String) getTpNameNode.execute(cls); + return getModuleName(tpName); + } + + @Specialization(guards = "!isNoValue(value)") + Object getModule(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type"); + } + + @TruffleBoundary + private static String getModuleName(String fqname) { + int firstDotIdx = fqname.indexOf('.'); + if (firstDotIdx != -1) { + return fqname.substring(0, firstDotIdx); + } + return null; + } } } From bc519c55e0d73e027d6d5b3b24fb05ca1fc0ece1 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 14:18:27 +0100 Subject: [PATCH 069/202] Add '__qualname__' getter/setter for types. --- .../builtins/objects/type/TypeBuiltins.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 606eee7623..d8aad090d8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -32,6 +32,7 @@ import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MODULE__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MRO__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__CALL__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__DELETE__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__; @@ -659,4 +660,55 @@ private static String getModuleName(String fqname) { return null; } } + + @Builtin(name = __QUALNAME__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) + @GenerateNodeFactory + @ImportStatic(NativeMemberNames.class) + static abstract class QualNameNode extends PythonBinaryBuiltinNode { + @Specialization(guards = "isNoValue(value)") + String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { + return cls.getName(); + } + + @Specialization(guards = {"isNoValue(value)", "!isPythonBuiltinClass(cls)"}) + Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create()") ReadAttributeFromObjectNode getName) { + return getName.execute(cls, __QUALNAME__); + } + + @Specialization(guards = "!isNoValue(value)") + Object setName(@SuppressWarnings("unused") PythonBuiltinClass cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of built-in/extension 'type'"); + } + + @Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)"}) + Object setName(PythonClass cls, Object value, + @Cached("create()") WriteAttributeToObjectNode setName) { + return setName.execute(cls, __QUALNAME__, value); + } + + @Specialization(guards = "isNoValue(value)") + String getNative(PythonAbstractNativeObject cls, @SuppressWarnings("unused") PNone value, + @Cached("create(TP_NAME)") GetTypeMemberNode getTpNameNode) { + // 'tp_name' contains the fully-qualified name, i.e., 'module.A.B...' + String tpName = (String) getTpNameNode.execute(cls); + return getQualName(tpName); + } + + @Specialization(guards = "!isNoValue(value)") + Object getModule(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type"); + } + + @TruffleBoundary + private static String getQualName(String fqname) { + int firstDot = fqname.indexOf('.'); + if (firstDot != -1) { + return fqname.substring(firstDot + 1); + } + return fqname; + } + + } + } From f04c1792cb0a756373f03ddf8814c2d7de5016cd Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 14:18:52 +0100 Subject: [PATCH 070/202] Fix: 'hasattr' should use 'getattr'. --- graalpython/lib-graalpython/functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/lib-graalpython/functions.py b/graalpython/lib-graalpython/functions.py index e836d7144b..66ef952d15 100644 --- a/graalpython/lib-graalpython/functions.py +++ b/graalpython/lib-graalpython/functions.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2019, 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 @@ -40,7 +40,7 @@ @__builtin__ def hasattr(obj, key): try: - type(obj).__getattribute__(obj, key) + getattr(obj, key) return True except AttributeError: return False From 04f1426b2f0b49d04cb008f70bf85b562e642e18 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 16:42:32 +0100 Subject: [PATCH 071/202] Use one impl class for PythonNative(Object|Class). --- .../oracle/graal/python/PythonLanguage.java | 5 +- .../builtins/modules/BuiltinConstructors.java | 6 +- .../builtins/modules/TruffleCextBuiltins.java | 8 ++- .../builtins/objects/cext/CExtNodes.java | 68 ++++--------------- .../cext/PythonAbstractNativeObject.java | 19 +++++- .../objects/cext/PythonNativeClass.java | 28 ++------ .../objects/cext/PythonNativeObject.java | 13 +++- .../cext/PythonObjectNativeWrapperMR.java | 8 +-- .../objects/object/ObjectBuiltins.java | 9 +-- .../builtins/objects/type/TypeBuiltins.java | 22 +----- .../builtins/objects/type/TypeNodes.java | 42 ++++-------- .../oracle/graal/python/nodes/PGuards.java | 4 +- .../attributes/LookupAttributeInMRONode.java | 13 ++-- .../ReadAttributeFromObjectNode.java | 28 ++++++-- .../python/nodes/object/GetClassNode.java | 17 ++--- .../python/nodes/object/GetLazyClassNode.java | 17 ++--- .../nodes/truffle/PythonArithmeticTypes.java | 24 +++++++ .../python/nodes/truffle/PythonTypes.java | 24 +++++++ .../interop/PythonMessageResolution.java | 14 ++-- .../runtime/object/PythonObjectFactory.java | 5 +- 20 files changed, 181 insertions(+), 193 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index 0cd17a7299..b5361ec5d7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -37,7 +37,6 @@ import com.oracle.graal.python.builtins.Python3Core; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PythonAbstractObject; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.code.PCode; import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.function.PArguments; @@ -51,6 +50,7 @@ import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.NodeFactory; +import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode; import com.oracle.graal.python.nodes.call.InvokeNode; import com.oracle.graal.python.nodes.control.TopLevelExceptionHandler; @@ -312,7 +312,8 @@ protected Object findMetaObject(PythonContext context, Object value) { if (value != null) { if (value instanceof PythonObject) { return ((PythonObject) value).asPythonClass(); - } else if (value instanceof PythonNativeObject) { + } else if (PGuards.isNativeObject(value)) { + // TODO(fa): we could also use 'GetClassNode.getItSlowPath(value)' here return null; } else if (value instanceof PythonAbstractObject || value instanceof Number || diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index 39d2b41bc5..d0aeb1c83f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -1379,8 +1379,8 @@ Object doNativeObjectIndirect(PythonNativeClass self, Object[] varargs, PKeyword private static PythonNativeClass findFirstNativeBaseClass(AbstractPythonClass[] methodResolutionOrder) { for (AbstractPythonClass cls : methodResolutionOrder) { - if (cls instanceof PythonNativeClass) { - return (PythonNativeClass) cls; + if (PGuards.isNativeClass(cls)) { + return PythonNativeClass.cast(cls); } } throw new IllegalStateException("class needs native allocation but has not native base class"); @@ -2042,7 +2042,7 @@ private boolean addDictIfNative(ManagedPythonClass pythonClass) { boolean addedNewDict = false; if (pythonClass.needsNativeAllocation()) { for (Object cls : getMro(pythonClass)) { - if (cls instanceof PythonNativeClass) { + if (PGuards.isNativeClass(cls)) { long dictoffset = ensureCastToIntNode().execute(ensureReadAttrNode().execute(cls, SpecialAttributeNames.__DICTOFFSET__)); long basicsize = ensureCastToIntNode().execute(ensureReadAttrNode().execute(cls, SpecialAttributeNames.__BASICSIZE__)); long itemsize = ensureCastToIntNode().execute(ensureReadAttrNode().execute(cls, SpecialAttributeNames.__ITEMSIZE__)); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 8bc9fe6268..7504e447f0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -154,6 +154,7 @@ import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.nodes.subscript.SliceLiteralNode; import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; +import com.oracle.graal.python.nodes.truffle.PythonTypes; import com.oracle.graal.python.nodes.util.CastToIndexNode; import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.PythonCore; @@ -622,7 +623,7 @@ private void computeAndSetDictoffset(Object tpDictoffset, PythonNativeClass ccla if (initialDictoffset == 0) { for (Object cls : getMro(cclass)) { if (cls != cclass) { - if (cls instanceof PythonNativeClass) { + if (PGuards.isNativeClass(cls)) { int baseDictoffset = castToIntNode.execute(ensureReadAttrNode().execute(cls, __DICTOFFSET__)); if (baseDictoffset != 0) { long dictoffset; @@ -922,6 +923,7 @@ PNone doNativeNone() { } } + @TypeSystemReference(PythonTypes.class) abstract static class NativeBuiltin extends PythonBuiltinNode { @Child private Node hasSizeNode; @@ -2177,7 +2179,7 @@ private static BigInteger convertToBigInteger(long n) { @Specialization Object doPointer(PythonNativeObject n, @SuppressWarnings("unused") int signed, @Cached("create()") CExtNodes.ToSulongNode toSulongNode) { - return toSulongNode.execute(factory().createNativeVoidPtr(n.object)); + return toSulongNode.execute(factory().createNativeVoidPtr(n.getPtr())); } } @@ -2317,7 +2319,7 @@ abstract static class PyBytes_FromStringAndSize extends NativeBuiltin { @Specialization PBytes doGeneric(PythonNativeObject object) { - return factory().createBytes(getByteArray(object.object)); + return factory().createBytes(getByteArray(object.getPtr())); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index e7ad063b2a..aa73dce537 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -312,15 +312,10 @@ Object doDouble(double d) { } @Specialization - Object doNativeClass(PythonNativeClass nativeClass) { + Object doNativeClass(PythonAbstractNativeObject nativeClass) { return nativeClass.getPtr(); } - @Specialization - Object doNativeObject(PythonNativeObject nativeObject) { - return nativeObject.object; - } - @Specialization Object doNativeNull(PythonNativeNull object) { return object.getPtr(); @@ -369,10 +364,6 @@ protected static boolean isPythonClass(PythonAbstractObject o) { return o instanceof AbstractPythonClass; } - protected static boolean isNativeObject(PythonAbstractObject o) { - return o instanceof PythonNativeObject; - } - protected static PythonClassNativeWrapper wrapNativeClass(ManagedPythonClass object) { return PythonClassNativeWrapper.wrap(object, GetNameNode.doSlowPath(object)); } @@ -391,10 +382,10 @@ public static Object doSlowPath(Object o) { return PrimitiveNativeWrapper.createLong((Long) o); } else if (o instanceof Double) { return PrimitiveNativeWrapper.createDouble((Double) o); - } else if (o instanceof PythonNativeClass) { + } else if (PythonNativeClass.isInstance(o)) { return ((PythonNativeClass) o).getPtr(); - } else if (o instanceof PythonNativeObject) { - return ((PythonNativeObject) o).object; + } else if (PythonNativeObject.isInstance(o)) { + return PythonNativeObject.cast(o).getPtr(); } else if (o instanceof PythonNativeNull) { return ((PythonNativeNull) o).getPtr(); } else if (o instanceof ManagedPythonClass) { @@ -418,12 +409,6 @@ public abstract static class AsPythonObjectNode extends CExtBaseNode { @Child private MaterializeDelegateNode materializeNode; @Child private IsPointerNode isPointerNode; - private final boolean forceNativeClass; - - public AsPythonObjectNode(boolean forceNativeClass) { - this.forceNativeClass = forceNativeClass; - } - public abstract Object execute(Object value); @Specialization(guards = "object.isBool()") @@ -462,12 +447,9 @@ Object doNativeWrapper(PythonNativeWrapper object) { } @Specialization(guards = {"isForeignObject(object, getClassNode, isForeignClassProfile)", "!isNativeWrapper(object)", "!isNativeNull(object)"}, limit = "1") - PythonAbstractObject doNativeObject(TruffleObject object, + Object doNativeObject(TruffleObject object, @SuppressWarnings("unused") @Cached("create()") GetLazyClassNode getClassNode, @SuppressWarnings("unused") @Cached("create()") IsBuiltinClassProfile isForeignClassProfile) { - if (forceNativeClass) { - return factory().createNativeClassWrapper(object); - } return factory().createNativeObjectWrapper(object); } @@ -556,15 +538,11 @@ private MaterializeDelegateNode getMaterializeNode() { } public static AsPythonObjectNode create() { - return AsPythonObjectNodeGen.create(false); - } - - static AsPythonObjectNode create(boolean forceNativeClass) { - return AsPythonObjectNodeGen.create(forceNativeClass); + return AsPythonObjectNodeGen.create(); } public static AsPythonObjectNode createForceClass() { - return AsPythonObjectNodeGen.create(true); + return AsPythonObjectNodeGen.create(); } } @@ -872,11 +850,11 @@ public abstract static class GetNativeClassNode extends CExtBaseNode { @CompilationFinal private TruffleObject func; - public abstract AbstractPythonClass execute(PythonAbstractObject object); + public abstract AbstractPythonClass execute(PythonAbstractNativeObject object); @Specialization(guards = "object == cachedObject", limit = "1") - AbstractPythonClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeObject object, - @SuppressWarnings("unused") @Cached("object") PythonNativeObject cachedObject, + AbstractPythonClass getNativeClassCached(@SuppressWarnings("unused") PythonAbstractNativeObject object, + @SuppressWarnings("unused") @Cached("object") PythonAbstractNativeObject cachedObject, @Cached("getNativeClass(cachedObject)") AbstractPythonClass cachedClass) { // TODO: (tfel) is this really something we can do? It's so rare for this class to // change that it shouldn't be worth the effort, but in native code, anything can @@ -886,35 +864,13 @@ AbstractPythonClass getNativeClassCached(@SuppressWarnings("unused") PythonNativ } @Specialization - AbstractPythonClass getNativeClass(PythonNativeObject object) { + AbstractPythonClass getNativeClass(PythonAbstractNativeObject object) { // do not convert wrap 'object.object' since that is really the native pointer object return (AbstractPythonClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.object)); } - @Specialization(guards = "object == cachedObject", limit = "1") - AbstractPythonClass getNativeClassCached(@SuppressWarnings("unused") PythonNativeClass object, - @SuppressWarnings("unused") @Cached("object") PythonNativeClass cachedObject, - @Cached("getNativeClass(cachedObject)") AbstractPythonClass cachedClass) { - // TODO: (tfel) is this really something we can do? It's so rare for this class to - // change that it shouldn't be worth the effort, but in native code, anything can - // happen. OTOH, CPython also has caches that can become invalid when someone just goes - // and changes the ob_type of an object. - return cachedClass; - } - - @Specialization - AbstractPythonClass getNativeClass(PythonNativeClass object) { - // do not convert wrap 'object.object' since that is really the native pointer object - return (AbstractPythonClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.getPtr())); - } - - @TruffleBoundary - public static AbstractPythonClass doSlowPath(PythonNativeObject object) { - return (AbstractPythonClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.object), true); - } - @TruffleBoundary - public static AbstractPythonClass doSlowPath(PythonNativeClass object) { + public static AbstractPythonClass doSlowPath(PythonAbstractNativeObject object) { return (AbstractPythonClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.getPtr()), true); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java index b5de264b87..6c2853f10b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java @@ -41,9 +41,11 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.PythonAbstractObject; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.object.Shape; -public class PythonAbstractNativeObject extends PythonAbstractObject { +public class PythonAbstractNativeObject extends PythonAbstractObject implements PythonNativeObject, PythonNativeClass { public final TruffleObject object; @@ -55,4 +57,19 @@ public int compareTo(Object o) { return 0; } + public Shape getInstanceShape() { + CompilerDirectives.transferToInterpreter(); + throw new UnsupportedOperationException("native class does not have a shape"); + } + + public void lookupChanged() { + // TODO invalidate cached native MRO + CompilerDirectives.transferToInterpreter(); + throw new UnsupportedOperationException("not yet implemented"); + } + + public TruffleObject getPtr() { + return object; + } + } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java index 8355f9b038..ba97fc787a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java @@ -41,9 +41,7 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.object.Shape; /** * A simple wrapper around types objects created through the Python C API that can be cast to @@ -51,28 +49,16 @@ * types are assumed to be mutated afterwards, so accessing the struct in native mode would work, * but our copy should just never become stale. */ -public final class PythonNativeClass extends PythonAbstractNativeObject implements AbstractPythonClass { +public interface PythonNativeClass extends AbstractPythonClass { - public PythonNativeClass(TruffleObject ptr) { - super(ptr); - } - - public TruffleObject getPtr() { - return object; - } - - public Shape getInstanceShape() { - CompilerDirectives.transferToInterpreter(); - throw new UnsupportedOperationException("native class does not have a shape"); - } + TruffleObject getPtr(); - public void lookupChanged() { - // TODO invalidate cached native MRO - CompilerDirectives.transferToInterpreter(); - throw new UnsupportedOperationException("not yet implemented"); + static boolean isInstance(Object object) { + return object instanceof PythonAbstractNativeObject; } - public static PythonNativeClass cast(PythonNativeObject object) { - return new PythonNativeClass(object.object); + static PythonNativeClass cast(Object object) { + assert isInstance(object); + return (PythonAbstractNativeObject) object; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeObject.java index 8c65778599..b0e20d2e04 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeObject.java @@ -45,9 +45,16 @@ /** * A simple wrapper around objects created through the Python C API that can be cast to PyObject*. */ -public class PythonNativeObject extends PythonAbstractNativeObject { +public interface PythonNativeObject { - public PythonNativeObject(TruffleObject obj) { - super(obj); + TruffleObject getPtr(); + + static boolean isInstance(Object object) { + return object instanceof PythonAbstractNativeObject; + } + + static PythonNativeObject cast(Object object) { + assert isInstance(object); + return (PythonAbstractNativeObject) object; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index c2c277f7c0..de8c264c3a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -736,9 +736,9 @@ Object doMemoryview(PMemoryView object, String key, @Cached("createReadNode()") Node readNode, @Cached("createBinaryProfile()") ConditionProfile isNativeObject) { Object delegateObj = readAttrNode.execute(object, "__c_memoryview"); - if (isNativeObject.profile(delegateObj instanceof PythonNativeObject)) { + if (isNativeObject.profile(PythonNativeObject.isInstance(delegateObj))) { try { - return ForeignAccess.sendRead(readNode, ((PythonNativeObject) delegateObj).object, key); + return ForeignAccess.sendRead(readNode, PythonNativeObject.cast(delegateObj).getPtr(), key); } catch (UnsupportedMessageException | UnknownIdentifierException e) { throw e.raise(); } @@ -958,9 +958,9 @@ Object doMemoryview(PMemoryView object, String key, Object value, @Cached("createWriteNode()") Node writeNode, @Cached("createBinaryProfile()") ConditionProfile isNativeObject) { Object delegateObj = readAttrNode.execute(object, "__c_memoryview"); - if (isNativeObject.profile(delegateObj instanceof PythonNativeObject)) { + if (isNativeObject.profile(PythonNativeObject.isInstance(delegateObj))) { try { - return ForeignAccess.sendWrite(writeNode, ((PythonNativeObject) delegateObj).object, key, value); + return ForeignAccess.sendWrite(writeNode, PythonNativeObject.cast(delegateObj).getPtr(), key, value); } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException e) { throw e.raise(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java index 5957ccaf5b..7f227823ff 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java @@ -58,6 +58,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PNotImplemented; import com.oracle.graal.python.builtins.objects.cext.CExtNodes; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.common.PHashingCollection; @@ -141,12 +142,12 @@ PNone setClass(PythonObject self, AbstractPythonClass value, @Cached("create()") BranchProfile errorSelfBranch, @Cached("create()") BranchProfile errorSlotsBranch, @Cached("create()") GetLazyClassNode getLazyClass) { - if (value instanceof PythonBuiltinClass || value instanceof PythonNativeClass) { + if (value instanceof PythonBuiltinClass || PGuards.isNativeClass(value)) { errorValueBranch.enter(); throw raise(TypeError, ERROR_MESSAGE); } LazyPythonClass lazyClass = getLazyClass.execute(self); - if (lazyClass instanceof PythonBuiltinClassType || lazyClass instanceof PythonBuiltinClass || lazyClass instanceof PythonNativeClass) { + if (lazyClass instanceof PythonBuiltinClassType || lazyClass instanceof PythonBuiltinClass || PGuards.isNativeClass(lazyClass)) { errorSelfBranch.enter(); throw raise(TypeError, ERROR_MESSAGE); } @@ -236,7 +237,7 @@ public int hash(Object self) { @GenerateNodeFactory public abstract static class EqNode extends PythonBinaryBuiltinNode { @Specialization - public boolean eq(PythonNativeObject self, PythonNativeObject other, + public boolean eq(PythonAbstractNativeObject self, PythonAbstractNativeObject other, @Cached("create(__EQ__)") CExtNodes.PointerCompareNode nativeIsNode) { return nativeIsNode.execute(self, other); } @@ -255,7 +256,7 @@ public abstract static class NeNode extends PythonBinaryBuiltinNode { @Child private CastToBooleanNode ifFalseNode; @Specialization - public boolean ne(PythonNativeObject self, PythonNativeObject other, + public boolean ne(PythonAbstractNativeObject self, PythonAbstractNativeObject other, @Cached("create(__NE__)") CExtNodes.PointerCompareNode nativeNeNode) { return nativeNeNode.execute(self, other); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index d8aad090d8..a413c38e9c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -108,7 +108,6 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.api.profiles.ValueProfile; @CoreFunctions(extendClasses = PythonBuiltinClassType.PythonClass) public class TypeBuiltins extends PythonBuiltins { @@ -193,23 +192,14 @@ protected static Object first(Object[] ary) { return ary[0]; } - protected static boolean isClass(Object object) { - return PGuards.isClass(object) || PGuards.isNativeObject(object); - } - protected static boolean accept(Object[] ary, Object cachedSelf) { Object first = first(ary); - return first == cachedSelf && isClass(first); + return first == cachedSelf && PGuards.isClass(first); } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"accept(arguments, cachedSelf)"}) protected Object doItUnboxed(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords, - @Cached("first(arguments)") Object cachedSelf, - @Cached("createClassProfile()") ValueProfile profile) { - Object profiled = profile.profile(cachedSelf); - if (profiled instanceof PythonNativeObject) { - return op(frame, PythonNativeClass.cast((PythonNativeObject) cachedSelf), arguments, keywords, false); - } + @Cached("first(arguments)") Object cachedSelf) { return op(frame, (AbstractPythonClass) cachedSelf, arguments, keywords, false); } @@ -217,9 +207,6 @@ protected Object doItUnboxed(VirtualFrame frame, @SuppressWarnings("unused") PNo @Specialization(replaces = "doItUnboxed") protected Object doItUnboxedIndirect(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords) { Object self = arguments[0]; - if (self instanceof PythonNativeObject) { - return op(frame, PythonNativeClass.cast((PythonNativeObject) self), arguments, keywords, false); - } return op(frame, (AbstractPythonClass) self, arguments, keywords, false); } @@ -379,11 +366,6 @@ protected Object doIt(LazyPythonClass object, Object key) { throw raise(AttributeError, "type object '%s' has no attribute %s", getTypeName(object), key); } - @Specialization - protected Object doIt(PythonNativeObject object, Object key) { - return doIt(new PythonNativeClass(object.object), key); - } - private Object readAttribute(LazyPythonClass object, Object key) { if (lookupAsClass == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index e76fda2c20..fb651e1d78 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -51,8 +51,8 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodes; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass.FlagsContainer; @@ -65,6 +65,7 @@ import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetTypeFlagsNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.IsSameTypeNodeGen; import com.oracle.graal.python.nodes.BuiltinNames; +import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage; @@ -78,7 +79,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.Message; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; @@ -129,7 +129,7 @@ public static long doSlowPath(AbstractPythonClass clazz) { } else { return getValue(mclazz.getFlagsContainer()); } - } else if (clazz instanceof PythonNativeClass) { + } else if (PGuards.isNativeClass(clazz)) { return doNativeGeneric((PythonNativeClass) clazz, createReadNode()); } throw new IllegalStateException("unknown type"); @@ -138,7 +138,7 @@ public static long doSlowPath(AbstractPythonClass clazz) { static long doNativeGeneric(PythonNativeClass clazz, Node readNode) { try { - return (long) ForeignAccess.sendRead(readNode, (TruffleObject) clazz.getPtr(), NativeMemberNames.TP_FLAGS); + return (long) ForeignAccess.sendRead(readNode, clazz.getPtr(), NativeMemberNames.TP_FLAGS); } catch (UnknownIdentifierException | UnsupportedMessageException e) { CompilerDirectives.transferToInterpreter(); throw e.raise(); @@ -192,7 +192,7 @@ public static AbstractPythonClass[] doSlowPath(Object obj) { return ((ManagedPythonClass) obj).getMethodResolutionOrder(); } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getMethodResolutionOrder(); - } else if (obj instanceof PythonNativeClass) { + } else if (PGuards.isNativeClass(obj)) { Object tupleObj = GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_MRO); if (tupleObj instanceof PTuple) { SequenceStorage sequenceStorage = ((PTuple) tupleObj).getSequenceStorage(); @@ -241,7 +241,7 @@ public static String doSlowPath(Object obj) { return BuiltinNames.FOREIGN; } return ((PythonBuiltinClassType) obj).getName(); - } else if (obj instanceof PythonNativeClass) { + } else if (PGuards.isNativeClass(obj)) { return (String) CExtNodes.GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_NAME); } throw new IllegalStateException("unknown type " + obj.getClass().getName()); @@ -273,7 +273,7 @@ public static LazyPythonClass doSlowPath(Object obj) { return ((ManagedPythonClass) obj).getSuperClass(); } else if (obj instanceof PythonBuiltinClassType) { return ((PythonBuiltinClassType) obj).getBase(); - } else if (obj instanceof PythonNativeClass) { + } else if (PGuards.isNativeClass(obj)) { // TODO implement } throw new IllegalStateException("unknown type " + obj.getClass().getName()); @@ -305,7 +305,7 @@ public static Set doSlowPath(Object obj) { return ((ManagedPythonClass) obj).getSubClasses(); } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getSubClasses(); - } else if (obj instanceof PythonNativeClass) { + } else if (PGuards.isNativeClass(obj)) { // TODO implement } throw new IllegalStateException("unknown type " + obj.getClass().getName()); @@ -356,7 +356,7 @@ public static AbstractPythonClass[] doSlowPath(Object obj) { return ((ManagedPythonClass) obj).getBaseClasses(); } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getBaseClasses(); - } else if (obj instanceof PythonNativeClass) { + } else if (PGuards.isNativeClass(obj)) { Object basesObj = GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_BASES); if (!(basesObj instanceof PTuple)) { throw PythonLanguage.getCore().raise(PythonBuiltinClassType.SystemError, "invalid type of tp_bases (was %p)", basesObj); @@ -401,13 +401,7 @@ boolean doManaged(ManagedPythonClass left, ManagedPythonClass right) { } @Specialization - boolean doNative(PythonNativeClass left, PythonNativeClass right, - @Cached("create(__EQ__)") CExtNodes.PointerCompareNode pointerCompareNode) { - return pointerCompareNode.execute(left, right); - } - - @Specialization - boolean doNative(PythonNativeObject left, PythonNativeObject right, + boolean doNative(PythonAbstractNativeObject left, PythonAbstractNativeObject right, @Cached("create(__EQ__)") CExtNodes.PointerCompareNode pointerCompareNode) { return pointerCompareNode.execute(left, right); } @@ -421,10 +415,8 @@ boolean doOther(@SuppressWarnings("unused") Object left, @SuppressWarnings("unus public static boolean doSlowPath(Object left, Object right) { if (left instanceof ManagedPythonClass && right instanceof ManagedPythonClass) { return left == right; - } else if (left instanceof PythonNativeClass && right instanceof PythonNativeClass) { - return CExtNodes.PointerCompareNode.create(__EQ__).execute((PythonNativeClass) left, (PythonNativeClass) right); - } else if (left instanceof PythonNativeObject && right instanceof PythonNativeObject) { - return CExtNodes.PointerCompareNode.create(__EQ__).execute((PythonNativeObject) left, (PythonNativeObject) right); + } else if (left instanceof PythonAbstractNativeObject && right instanceof PythonAbstractNativeObject) { + return CExtNodes.PointerCompareNode.create(__EQ__).execute((PythonAbstractNativeObject) left, (PythonAbstractNativeObject) right); } return false; } @@ -454,7 +446,7 @@ Object doNative(@SuppressWarnings("unused") PythonNativeClass clazz) { public static Object getSlowPath(AbstractPythonClass clazz) { if (clazz instanceof ManagedPythonClass) { return ((ManagedPythonClass) clazz).getSulongType(); - } else if (clazz instanceof PythonNativeClass) { + } else if (PGuards.isNativeClass(clazz)) { return null; } throw new IllegalStateException("unknown type " + clazz.getClass().getName()); @@ -514,14 +506,6 @@ private static AbstractPythonClass[] computeMethodResolutionOrder(AbstractPython mro.add(cls); currentMRO = mergeMROs(toMerge, mro); } - -// for (AbstractPythonClass c : currentMRO) { -// if (c instanceof PythonNativeClass) { -// needsNativeAllocation = true; -// break; -// } -// } - return currentMRO; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java index 7f481f767d..d1b31af626 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java @@ -256,11 +256,11 @@ public static boolean isPythonBuiltinClass(Object klass) { } public static boolean isNativeObject(Object object) { - return object instanceof PythonNativeObject; + return PythonNativeObject.isInstance(object); } public static boolean isNativeClass(Object klass) { - return klass instanceof PythonNativeClass; + return PythonNativeClass.isInstance(klass); } public static boolean isPRange(Object obj) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index 52288c1295..d5feb2595e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -47,6 +47,7 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.runtime.PythonCore; import com.oracle.graal.python.runtime.PythonOptions; @@ -89,7 +90,7 @@ protected Object lookup(PythonBuiltinClassType klass, Object key) { @Specialization(replaces = "lookupConstantMRO") protected Object lookup(ManagedPythonClass klass, Object key, @Cached("create()") GetMroNode getMroNode, - @Cached("create()") ReadAttributeFromObjectNode readAttrNode) { + @Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode) { return LookupAttributeInMRONode.lookupSlow(klass, key, getMroNode, readAttrNode); } } @@ -168,7 +169,7 @@ protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(ManagedPytho } } } else { - assert clsObj instanceof PythonNativeClass; + assert PGuards.isNativeClass(clsObj); return null; } } @@ -186,7 +187,7 @@ protected Object lookupConstantMROCached(@SuppressWarnings("unused") ManagedPyth protected ReadAttributeFromObjectNode[] create(int size) { ReadAttributeFromObjectNode[] nodes = new ReadAttributeFromObjectNode[size]; for (int i = 0; i < size; i++) { - nodes[i] = ReadAttributeFromObjectNode.create(); + nodes[i] = ReadAttributeFromObjectNode.createForceType(); } return nodes; } @@ -212,14 +213,14 @@ protected Object lookupConstantMRO(@SuppressWarnings("unused") ManagedPythonClas @Specialization(replaces = {"lookupConstantMROCached", "lookupConstantMRO"}) protected Object lookup(ManagedPythonClass klass, @Cached("create()") GetMroNode getMroNode, - @Cached("create()") ReadAttributeFromObjectNode readAttrNode) { + @Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode) { return lookupSlow(klass, key, getMroNode, readAttrNode); } @Specialization protected Object lookup(PythonNativeClass klass, @Cached("create()") GetMroNode getMroNode, - @Cached("create()") ReadAttributeFromObjectNode readAttrNode) { + @Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode) { return lookupSlow(klass, key, getMroNode, readAttrNode); } @@ -247,7 +248,7 @@ public static Object lookupSlow(LazyPythonClass klass, String key) { AbstractPythonClass[] mro = GetMroNode.doSlowPath(klass); for (int i = 0; i < mro.length; i++) { AbstractPythonClass kls = mro[i]; - Object value = ReadAttributeFromObjectNode.doSlowPath(kls, key); + Object value = ReadAttributeFromObjectNode.doSlowPath(kls, key, true); if (value != PNone.NO_VALUE) { return value; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java index ee3c19147e..2d4d89d0b4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java @@ -45,6 +45,7 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetObjectDictNode; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.common.HashingStorage; @@ -68,8 +69,19 @@ @ImportStatic({PGuards.class, PythonOptions.class, NativeMemberNames.class}) public abstract class ReadAttributeFromObjectNode extends ObjectAttributeNode { + + protected final boolean forceType; + + public ReadAttributeFromObjectNode(boolean forceType) { + this.forceType = forceType; + } + public static ReadAttributeFromObjectNode create() { - return ReadAttributeFromObjectNodeGen.create(); + return ReadAttributeFromObjectNodeGen.create(false); + } + + public static ReadAttributeFromObjectNode createForceType() { + return ReadAttributeFromObjectNodeGen.create(true); } public abstract Object execute(Object object, Object key); @@ -137,14 +149,14 @@ protected Node createReadMessageNode() { return Message.READ.createNode(); } - @Specialization(guards = {"!isHiddenKey(key)"}) + @Specialization(guards = {"!forceType", "!isHiddenKey(key)"}) protected Object readNativeObject(PythonNativeObject object, Object key, @Cached("create()") GetObjectDictNode getNativeDict, @Cached("create()") HashingStorageNodes.GetItemNode getItemNode) { return readNative(object, key, getNativeDict, getItemNode); } - @Specialization(guards = {"!isHiddenKey(key)"}) + @Specialization(guards = {"forceType", "!isHiddenKey(key)"}) protected Object readNativeClass(PythonNativeClass object, Object key, @Cached("create(TP_DICT)") GetTypeMemberNode getNativeDict, @Cached("create()") HashingStorageNodes.GetItemNode getItemNode) { @@ -182,8 +194,12 @@ protected PNone readUnboxed(Object object, Object key) { return PNone.NO_VALUE; } - @TruffleBoundary public static Object doSlowPath(Object object, Object key) { + return doSlowPath(object, key, false); + } + + @TruffleBoundary + public static Object doSlowPath(Object object, Object key, boolean forceType) { if (object instanceof PythonObject) { PythonObject po = (PythonObject) object; if (ObjectAttributeNode.isDictUnsetOrSameAsStorage(po)) { @@ -197,8 +213,8 @@ public static Object doSlowPath(Object object, Object key) { return value; } } - } else if (object instanceof PythonNativeObject || object instanceof PythonNativeClass) { - Object d = GetObjectDictNode.doSlowPath(object); + } else if (object instanceof PythonAbstractNativeObject) { + Object d = forceType ? GetTypeMemberNode.doSlowPath(object, NativeMemberNames.TP_DICT) : GetObjectDictNode.doSlowPath(object); Object value = null; if (d instanceof PHashingCollection) { HashingStorage dictStorage = ((PHashingCollection) d).getDictStorage(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java index 99fb39aa01..039c32dea4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java @@ -46,8 +46,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PNotImplemented; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetNativeClassNode; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr; import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptor; import com.oracle.graal.python.builtins.objects.object.PythonObject; @@ -201,13 +200,7 @@ protected PythonBuiltinClass getIt(String object) { } @Specialization - protected AbstractPythonClass getIt(PythonNativeObject object, - @Cached("create()") GetNativeClassNode getNativeClassNode) { - return getNativeClassNode.execute(object); - } - - @Specialization - protected static AbstractPythonClass getIt(PythonNativeClass object, + protected AbstractPythonClass getIt(PythonAbstractNativeObject object, @Cached("create()") GetNativeClassNode getNativeClassNode) { return getNativeClassNode.execute(object); } @@ -258,10 +251,8 @@ public static AbstractPythonClass getItSlowPath(Object o) { return core.lookupType(PythonBuiltinClassType.PInt); } else if (o instanceof PythonObject) { return ((PythonObject) o).getPythonClass(); - } else if (o instanceof PythonNativeObject) { - return GetNativeClassNode.doSlowPath((PythonNativeObject) o); - } else if (o instanceof PythonNativeClass) { - return GetNativeClassNode.doSlowPath((PythonNativeClass) o); + } else if (o instanceof PythonAbstractNativeObject) { + return GetNativeClassNode.doSlowPath((PythonAbstractNativeObject) o); } else if (o instanceof PEllipsis) { return core.lookupType(PythonBuiltinClassType.PEllipsis); } else if (o instanceof PNotImplemented) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java index 9fb8ee0840..bc0b83df7f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetLazyClassNode.java @@ -45,8 +45,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PNotImplemented; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetNativeClassNode; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr; import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptor; import com.oracle.graal.python.builtins.objects.object.PythonObject; @@ -142,13 +141,7 @@ protected static LazyPythonClass getIt(@SuppressWarnings("unused") PythonBuiltin } @Specialization - protected static LazyPythonClass getIt(PythonNativeObject object, - @Cached("create()") GetNativeClassNode getNativeClassNode) { - return getNativeClassNode.execute(object); - } - - @Specialization - protected static LazyPythonClass getIt(PythonNativeClass object, + protected static LazyPythonClass getIt(PythonAbstractNativeObject object, @Cached("create()") GetNativeClassNode getNativeClassNode) { return getNativeClassNode.execute(object); } @@ -193,10 +186,8 @@ public static LazyPythonClass getItSlowPath(Object o) { return PythonBuiltinClassType.PythonClass; } else if (o instanceof PythonObject) { return ((PythonObject) o).getLazyPythonClass(); - } else if (o instanceof PythonNativeObject) { - return GetNativeClassNode.doSlowPath((PythonNativeObject) o); - } else if (o instanceof PythonNativeClass) { - return GetNativeClassNode.doSlowPath((PythonNativeClass) o); + } else if (o instanceof PythonAbstractNativeObject) { + return GetNativeClassNode.doSlowPath((PythonAbstractNativeObject) o); } else if (o instanceof PEllipsis) { return PythonBuiltinClassType.PEllipsis; } else if (o instanceof PNotImplemented) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonArithmeticTypes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonArithmeticTypes.java index 84950fadef..74b64c0ee0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonArithmeticTypes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonArithmeticTypes.java @@ -25,9 +25,13 @@ */ package com.oracle.graal.python.nodes.truffle; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.floats.PFloat; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.truffle.api.dsl.ImplicitCast; +import com.oracle.truffle.api.dsl.TypeCast; +import com.oracle.truffle.api.dsl.TypeCheck; import com.oracle.truffle.api.dsl.TypeSystem; /** @@ -69,4 +73,24 @@ public static long booleanToLong(boolean value) { public static long intToLong(int value) { return value; } + + @TypeCheck(PythonNativeObject.class) + public static boolean isNativeObject(Object object) { + return PythonNativeObject.isInstance(object); + } + + @TypeCast(PythonNativeObject.class) + public static PythonNativeObject asNativeObject(Object object) { + return PythonNativeObject.cast(object); + } + + @TypeCheck(PythonNativeClass.class) + public static boolean isNativeClass(Object object) { + return PythonNativeClass.isInstance(object); + } + + @TypeCast(PythonNativeClass.class) + public static PythonNativeClass asNativeClass(Object object) { + return PythonNativeClass.cast(object); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypes.java index e8c98331f0..1f466c2cdc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypes.java @@ -25,7 +25,11 @@ */ package com.oracle.graal.python.nodes.truffle; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.truffle.api.dsl.ImplicitCast; +import com.oracle.truffle.api.dsl.TypeCast; +import com.oracle.truffle.api.dsl.TypeCheck; import com.oracle.truffle.api.dsl.TypeSystem; @TypeSystem @@ -34,4 +38,24 @@ public abstract class PythonTypes { public static long intToLong(int value) { return value; } + + @TypeCheck(PythonNativeObject.class) + public static boolean isNativeObject(Object object) { + return PythonNativeObject.isInstance(object); + } + + @TypeCast(PythonNativeObject.class) + public static PythonNativeObject asNativeObject(Object object) { + return PythonNativeObject.cast(object); + } + + @TypeCheck(PythonNativeClass.class) + public static boolean isNativeClass(Object object) { + return PythonNativeClass.isInstance(object); + } + + @TypeCast(PythonNativeClass.class) + public static PythonNativeClass asNativeClass(Object object) { + return PythonNativeClass.cast(object); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java index a00e9785b8..f8ee9b528d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java @@ -53,8 +53,6 @@ import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PythonAbstractObject; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.common.SequenceNodes; import com.oracle.graal.python.builtins.objects.common.SequenceNodes.LenNode; import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction; @@ -71,6 +69,7 @@ import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.attributes.DeleteAttributeNode; import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode; @@ -139,7 +138,7 @@ private static final class IsImmutable extends Node { @Child private GetLazyClassNode getClass; public boolean execute(Object object) { - if (object instanceof PythonBuiltinClass || object instanceof PythonBuiltinObject || object instanceof PythonNativeClass || object instanceof PythonNativeObject) { + if (object instanceof PythonBuiltinClass || object instanceof PythonBuiltinObject || PGuards.isNativeClass(object) || PGuards.isNativeObject(object)) { return true; } else if (object instanceof PythonClass) { return false; @@ -149,7 +148,7 @@ public boolean execute(Object object) { getClass = insert(GetLazyClassNode.create()); } LazyPythonClass klass = getClass.execute(object); - return klass instanceof PythonBuiltinClassType || klass instanceof PythonBuiltinClass || klass instanceof PythonNativeClass; + return klass instanceof PythonBuiltinClassType || klass instanceof PythonBuiltinClass || PGuards.isNativeClass(klass); } } } @@ -773,6 +772,7 @@ public Object access(Object object) { @Resolve(message = "KEY_INFO") abstract static class PKeyInfoNode extends Node { @Child private ReadAttributeFromObjectNode readNode = ReadAttributeFromObjectNode.create(); + @Child private ReadAttributeFromObjectNode readTypeAttrNode; @Child private IsCallableNode isCallableNode; @Child private LookupInheritedAttributeNode getGetNode; @Child private LookupInheritedAttributeNode getSetNode; @@ -798,7 +798,11 @@ public int access(Object object, Object fieldName) { AbstractPythonClass klass = getClassNode.execute(object); for (AbstractPythonClass c : getMro(klass)) { - attr = readNode.execute(c, fieldName); + if (readTypeAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + readTypeAttrNode = insert(ReadAttributeFromObjectNode.createForceType()); + } + attr = readTypeAttrNode.execute(c, fieldName); if (attr != PNone.NO_VALUE) { owner = c; break; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index 06f71783bd..4f31a2ff91 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -37,6 +37,7 @@ import com.oracle.graal.python.builtins.objects.bytes.PByteArray; import com.oracle.graal.python.builtins.objects.bytes.PBytes; import com.oracle.graal.python.builtins.objects.cell.PCell; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr; @@ -207,7 +208,7 @@ public PythonObject createPythonObject(LazyPythonClass cls) { } public PythonNativeObject createNativeObjectWrapper(TruffleObject obj) { - return trace(new PythonNativeObject(obj)); + return trace(new PythonAbstractNativeObject(obj)); } public PythonNativeVoidPtr createNativeVoidPtr(TruffleObject obj) { @@ -359,7 +360,7 @@ public PythonClass createPythonClass(LazyPythonClass metaclass, String name, Abs } public PythonNativeClass createNativeClassWrapper(TruffleObject ptr) { - return trace(new PythonNativeClass(ptr)); + return trace(new PythonAbstractNativeObject(ptr)); } public PMemoryView createMemoryView(LazyPythonClass metaclass, Object value) { From 0350314d99c449bfa4ffb8f07c03a28792ab59ec Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 17:15:50 +0100 Subject: [PATCH 072/202] Make 'WriteAttributeToObjectNode' aware of native classes. --- .../builtins/modules/BuiltinConstructors.java | 4 +-- .../builtins/modules/TruffleCextBuiltins.java | 2 +- .../builtins/objects/type/TypeBuiltins.java | 6 ++-- .../WriteAttributeToObjectNode.java | 36 +++++++++++-------- .../python/nodes/classes/IsSubtypeNode.java | 3 +- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index d0aeb1c83f..ad2898b0db 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -2141,7 +2141,7 @@ private ReadAttributeFromObjectNode ensureReadAttrNode() { private WriteAttributeToObjectNode ensureWriteAttrNode() { if (writeAttrNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - writeAttrNode = insert(WriteAttributeToObjectNode.create()); + writeAttrNode = insert(WriteAttributeToObjectNode.createForceType()); } return writeAttrNode; } @@ -2167,7 +2167,7 @@ private CastToStringNode ensureCastToStringNode() { @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) public abstract static class ModuleNode extends PythonBuiltinNode { - @Child WriteAttributeToObjectNode writeFile = WriteAttributeToObjectNode.create(); + @Child private WriteAttributeToObjectNode writeFile = WriteAttributeToObjectNode.create(); @Specialization public PythonModule module(LazyPythonClass cls, String name, @SuppressWarnings("unused") PNone path) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 7504e447f0..20676c7a59 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -545,7 +545,7 @@ Object setattr(PythonObject object, String key, Object value) { @Specialization Object setattr(PythonNativeClass object, String key, Object value, - @Cached("create()") WriteAttributeToObjectNode writeAttrNode) { + @Cached("createForceType()") WriteAttributeToObjectNode writeAttrNode) { writeAttrNode.execute(object, key, value); return PNone.NONE; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index a413c38e9c..4a569a5d1e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -154,7 +154,7 @@ Object doit(LazyPythonClass klass, @GenerateNodeFactory public abstract static class MroNode extends PythonBuiltinNode { @Specialization - Object doit(PythonClass klass, + Object doit(AbstractPythonClass klass, @Cached("create()") GetMroNode getMroNode) { AbstractPythonClass[] mro = getMroNode.execute(klass); return factory().createList(Arrays.copyOf(mro, mro.length, Object[].class)); @@ -492,7 +492,7 @@ private PythonObject getInstanceClassAttr(Object instance) { public abstract boolean executeWith(Object cls, Object instance); @Specialization - public boolean isInstance(PythonClass cls, Object instance, + public boolean isInstance(AbstractPythonClass cls, Object instance, @Cached("create()") IsSubtypeNode isSubtypeNode, @Cached("create()") GetClassNode getClass) { if (instance instanceof PythonObject && isSubtypeNode.execute(getClass.execute(instance), cls)) { @@ -530,7 +530,7 @@ boolean instanceCheck(LazyPythonClass cls, Object derived) { static abstract class SubclassesNode extends PythonUnaryBuiltinNode { @Specialization - PList getSubclasses(PythonClass cls, + PList getSubclasses(LazyPythonClass cls, @Cached("create()") GetSubclassesNode getSubclassesNode) { // TODO: missing: keep track of subclasses return factory().createList(toArray(getSubclassesNode.execute(cls))); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java index ac6a5631c2..42d187e12b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java @@ -44,8 +44,7 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetObjectDictNode; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes; import com.oracle.graal.python.builtins.objects.common.HashingStorage; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; @@ -72,12 +71,22 @@ public abstract class WriteAttributeToObjectNode extends ObjectAttributeNode { private final ConditionProfile isClassProfile = ConditionProfile.createBinaryProfile(); private final IsBuiltinClassProfile exactBuiltinInstanceProfile = IsBuiltinClassProfile.create(); + protected final boolean forceType; + + public WriteAttributeToObjectNode(boolean forceType) { + this.forceType = forceType; + } + public abstract boolean execute(Object primary, Object key, Object value); public abstract boolean execute(Object primary, String key, Object value); public static WriteAttributeToObjectNode create() { - return WriteAttributeToObjectNodeGen.create(); + return WriteAttributeToObjectNodeGen.create(false); + } + + public static WriteAttributeToObjectNode createForceType() { + return WriteAttributeToObjectNodeGen.create(true); } protected boolean isAttrWritable(PythonObject self, Object key) { @@ -165,24 +174,21 @@ protected boolean writeToDict(PythonObject object, Object key, Object value, return true; } - @Specialization(guards = "!isHiddenKey(key)") - protected boolean writeNative(PythonNativeObject object, Object key, Object value, + @Specialization(guards = {"!forceType", "!isHiddenKey(key)"}) + protected boolean writeNativeObject(PythonAbstractNativeObject object, Object key, Object value, @Cached("create()") GetObjectDictNode getNativeDict, @Cached("create()") HashingCollectionNodes.SetItemNode setItemNode) { - Object d = getNativeDict.execute(object); - if (d instanceof PHashingCollection) { - setItemNode.execute(((PHashingCollection) d), key, value); - return true; - } else { - return raise(object, key, value); - } + return writeNativeGeneric(object, key, value, getNativeDict.execute(object), setItemNode); } - @Specialization(guards = "!isHiddenKey(key)") - protected boolean writeNativeClass(PythonNativeClass object, Object key, Object value, + @Specialization(guards = {"forceType", "!isHiddenKey(key)"}) + protected boolean writeNativeClass(PythonAbstractNativeObject object, Object key, Object value, @Cached("create(TP_DICT)") GetTypeMemberNode getNativeDict, @Cached("create()") HashingCollectionNodes.SetItemNode setItemNode) { - Object d = getNativeDict.execute(object); + return writeNativeGeneric(object, key, value, getNativeDict.execute(object), setItemNode); + } + + private boolean writeNativeGeneric(PythonAbstractNativeObject object, Object key, Object value, Object d, HashingCollectionNodes.SetItemNode setItemNode) { if (d instanceof PHashingCollection) { setItemNode.execute(((PHashingCollection) d), key, value); return true; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java index d255c52a3e..bde385c69a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java @@ -41,7 +41,6 @@ package com.oracle.graal.python.nodes.classes; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; import com.oracle.graal.python.nodes.PNodeWithContext; @@ -89,7 +88,7 @@ boolean isSubtypeOfConstantType(@SuppressWarnings("unused") AbstractPythonClass @Specialization(guards = {"derived == cachedDerived"}, limit = "getVariableArgumentInlineCacheLimit()", replaces = "isSubtypeOfConstantType") @ExplodeLoop - boolean isSubtypeOfVariableType(@SuppressWarnings("unused") AbstractPythonClass derived, PythonClass cls, + boolean isSubtypeOfVariableType(@SuppressWarnings("unused") AbstractPythonClass derived, AbstractPythonClass cls, @Cached("derived") AbstractPythonClass cachedDerived) { for (AbstractPythonClass n : getMro(cachedDerived)) { if (isSameType(n, cls)) { From f7608da5972acb2268865efc0536336fbd79e40d Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 18:07:39 +0100 Subject: [PATCH 073/202] Fix native wrapper MR for 'tp_itemsize' and 'tp_weaklistoffset'. --- .../objects/cext/NativeMemberNames.java | 1 + .../cext/PythonObjectNativeWrapperMR.java | 20 ++++++++++++++++++- .../python/nodes/SpecialAttributeNames.java | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java index 66481addfb..823c34accf 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java @@ -61,6 +61,7 @@ public final class NativeMemberNames { public static final String TP_BASICSIZE = "tp_basicsize"; public static final String TP_ITEMSIZE = "tp_itemsize"; public static final String TP_DICTOFFSET = "tp_dictoffset"; + public static final String TP_WEAKLISTOFFSET = "tp_weaklistoffset"; public static final String TP_DOC = "tp_doc"; public static final String TP_ALLOC = "tp_alloc"; public static final String TP_AS_NUMBER = "tp_as_number"; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index de8c264c3a..a5ed92df85 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -508,7 +508,13 @@ Object doTpBasicsize(ManagedPythonClass object, @SuppressWarnings("unused") Stri @Specialization(guards = "eq(TP_ITEMSIZE, key)") Object doTpItemsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(__ITEMSIZE__)") LookupAttributeInMRONode getAttrNode) { - return getAttrNode.execute(object); + Object val = getAttrNode.execute(object); + // If the attribute does not exist, this means that we take 'tp_itemsize' from the base + // object which is by default 0 (see typeobject.c:PyBaseObject_Type). + if (val == PNone.NO_VALUE) { + return 0L; + } + return val; } @Specialization(guards = "eq(TP_DICTOFFSET, key)") @@ -523,6 +529,18 @@ Object doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") Str return castToIntNode.execute(dictoffset); } + @Specialization(guards = "eq(TP_WEAKLISTOFFSET, key)") + Object doTpWeaklistoffset(ManagedPythonClass object, @SuppressWarnings("unused") String key, + @Cached("create(__WEAKLISTOFFSET__)") LookupAttributeInMRONode getAttrNode) { + Object val = getAttrNode.execute(object); + // If the attribute does not exist, this means that we take 'tp_itemsize' from the base + // object which is by default 0 (see typeobject.c:PyBaseObject_Type). + if (val == PNone.NO_VALUE) { + return 0L; + } + return val; + } + @Specialization(guards = "eq(TP_RICHCOMPARE, key)") Object doTpRichcompare(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create(RICHCMP)") LookupAttributeInMRONode getCmpNode) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/SpecialAttributeNames.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/SpecialAttributeNames.java index 26ec69b1ad..22f2b7610d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/SpecialAttributeNames.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/SpecialAttributeNames.java @@ -72,4 +72,5 @@ public abstract class SpecialAttributeNames { public static final String __DICTOFFSET__ = "__dictoffset__"; public static final String __ITEMSIZE__ = "__itemsize__"; public static final String __WEAKREF__ = "__weakref__"; + public static final String __WEAKLISTOFFSET__ = "__weaklistoffset__"; } From a55c99b3a2417fbee402b037545a66327d8d4df9 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 18:27:54 +0100 Subject: [PATCH 074/202] Fix: do never return 'null' for '__module__'. --- .../graal/python/builtins/objects/type/TypeBuiltins.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 4a569a5d1e..47403573e7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -634,12 +634,16 @@ Object getModule(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @Su } @TruffleBoundary - private static String getModuleName(String fqname) { + private Object getModuleName(String fqname) { int firstDotIdx = fqname.indexOf('.'); if (firstDotIdx != -1) { return fqname.substring(0, firstDotIdx); } - return null; + return getBuiltinsName(); + } + + protected String getBuiltinsName() { + return getCore().getBuiltins().getModuleName(); } } @@ -692,5 +696,4 @@ private static String getQualName(String fqname) { } } - } From 1a2e4bcec859784a619e0467dd5466994c14df8f Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 21:41:05 +0100 Subject: [PATCH 075/202] Fix: Regex object may not have named capture groups. --- graalpython/lib-graalpython/_sre.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/graalpython/lib-graalpython/_sre.py b/graalpython/lib-graalpython/_sre.py index c8ad66ca9a..1a43e02219 100644 --- a/graalpython/lib-graalpython/_sre.py +++ b/graalpython/lib-graalpython/_sre.py @@ -168,10 +168,11 @@ def __group__(self, idx): def groupdict(self, default=None): d = {} - assert _interop.__has_keys__(self.compiled_regex.groups) - for k in _interop.__keys__(self.compiled_regex.groups): - idx = self.compiled_regex.groups[k] - d[k] = self.__group__(idx) + if self.compiled_regex.groups: + assert _interop.__has_keys__(self.compiled_regex.groups) + for k in _interop.__keys__(self.compiled_regex.groups): + idx = self.compiled_regex.groups[k] + d[k] = self.__group__(idx) return d def span(self, groupnum=0): From e198a5e2551653539b023570fcbe806549a08714 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 23 Jan 2019 21:41:55 +0100 Subject: [PATCH 076/202] Fix: 'LookupAttributeInMRO.Dynamic' node should accept native class. --- .../graal/python/nodes/attributes/LookupAttributeInMRONode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index d5feb2595e..f2b27a35ff 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -88,7 +88,7 @@ protected Object lookup(PythonBuiltinClassType klass, Object key) { } @Specialization(replaces = "lookupConstantMRO") - protected Object lookup(ManagedPythonClass klass, Object key, + protected Object lookup(AbstractPythonClass klass, Object key, @Cached("create()") GetMroNode getMroNode, @Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode) { return LookupAttributeInMRONode.lookupSlow(klass, key, getMroNode, readAttrNode); From 63b6055d7c7cc9848a8cf0bddaa79734995f819c Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Jan 2019 09:43:51 +0100 Subject: [PATCH 077/202] Support 'tp_weaklistoffset'. --- .../com.oracle.graal.python.cext/src/capi.c | 5 ++ .../modules/WeakRefModuleBuiltins.java | 61 +++++++++++++++---- .../objects/cext/NativeCAPISymbols.java | 1 + .../runtime/object/PythonObjectFactory.java | 5 ++ 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/capi.c b/graalpython/com.oracle.graal.python.cext/src/capi.c index f5d1ceeac6..b34561ce05 100644 --- a/graalpython/com.oracle.graal.python.cext/src/capi.c +++ b/graalpython/com.oracle.graal.python.cext/src/capi.c @@ -279,6 +279,11 @@ PyObject* get_tp_mro(PyTypeObject* obj) { return native_to_java(obj->tp_mro); } +/** to be used from Java code only; reads native 'tp_subclasses' field */ +PyObject* get_tp_subclasses(PyTypeObject* obj) { + return native_to_java(obj->tp_subclasses); +} + /** to be used from Java code only; returns the type ID for a byte array */ polyglot_typeid get_byte_array_typeid(uint64_t len) { return polyglot_array_typeid(polyglot_i8_typeid(), len); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java index 26c20072ce..693467a03a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java @@ -49,6 +49,10 @@ 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.CExtNodes; +import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; +import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; +import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.module.PythonModule; import com.oracle.graal.python.builtins.objects.object.PythonObject; @@ -56,6 +60,7 @@ import com.oracle.graal.python.builtins.objects.referencetype.PReferenceType.WeakRefStorage; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.runtime.AsyncHandler; @@ -63,6 +68,10 @@ import com.oracle.graal.python.runtime.exception.PythonErrorType; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.graal.python.nodes.object.GetLazyClassNode; +import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; +import com.oracle.graal.python.nodes.truffle.PythonTypes; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; @@ -70,8 +79,8 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.object.HiddenKey; +import com.oracle.truffle.api.dsl.TypeSystemReference; -@SuppressWarnings("unused") @CoreFunctions(defineModule = "_weakref") public class WeakRefModuleBuiltins extends PythonBuiltins { private final static HiddenKey weakRefQueueKey = new HiddenKey("weakRefQueue"); @@ -123,18 +132,49 @@ public void postInitialize(PythonCore core) { @Builtin(name = "ReferenceType", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3, constructsClass = PythonBuiltinClassType.PReferenceType) @GenerateNodeFactory public abstract static class ReferenceTypeNode extends PythonBuiltinNode { - @Child ReadAttributeFromObjectNode readQueue = ReadAttributeFromObjectNode.create(); + @Child private ReadAttributeFromObjectNode readQueue = ReadAttributeFromObjectNode.create(); + @Child private CExtNodes.GetTypeMemberNode getTpWeaklistoffsetNode; - @Specialization - public PReferenceType refType(LazyPythonClass cls, Object object, PNone none) { + @Specialization(guards = "!isNativeObject(object)") + public PReferenceType refType(LazyPythonClass cls, Object object, @SuppressWarnings("unused") PNone none) { return factory().createReferenceType(cls, object, null, getWeakReferenceQueue()); } - @Specialization + @Specialization(guards = "!isNativeObject(object)") public PReferenceType refType(LazyPythonClass cls, Object object, Object callback) { return factory().createReferenceType(cls, object, callback, getWeakReferenceQueue()); } + @Specialization + public PReferenceType refType(LazyPythonClass cls, PythonAbstractNativeObject pythonObject, Object callback, + @Cached("create()") GetLazyClassNode getClassNode, + @Cached("create()") IsBuiltinClassProfile profile) { + LazyPythonClass clazz = getClassNode.execute(pythonObject); + + // if the object is a type, a weak ref is allowed + if (profile.profileClass(clazz, PythonBuiltinClassType.PythonClass)) { + return factory().createReferenceType(cls, pythonObject, callback, getWeakReferenceQueue()); + } + + // if the object's type is a native type, we need to consider 'tp_weaklistoffset' + if (PGuards.isNativeClass(clazz)) { + if (getTpWeaklistoffsetNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getTpWeaklistoffsetNode = insert(GetTypeMemberNode.create(NativeMemberNames.TP_WEAKLISTOFFSET)); + } + Object tpWeaklistoffset = getTpWeaklistoffsetNode.execute(clazz); + if (tpWeaklistoffset != PNone.NO_VALUE) { + return factory().createReferenceType(cls, pythonObject, callback, getWeakReferenceQueue()); + } + } + return refType(cls, pythonObject, callback); + } + + @Fallback + public PReferenceType refType(Object cls, Object object, Object callback) { + throw raise(PythonErrorType.TypeError, "cannot create weak reference to '%p' object", object); + } + private ReferenceQueue getWeakReferenceQueue() { Object queueObject = readQueue.execute(getCore().lookupType(PythonBuiltinClassType.PReferenceType), weakRefQueueKey); if (queueObject instanceof ReferenceQueue) { @@ -145,11 +185,6 @@ private ReferenceQueue getWeakReferenceQueue() { throw new IllegalStateException("the weak reference queue was modified!"); } } - - @Fallback - public PReferenceType refType(Object cls, Object object, Object callback) { - throw raise(PythonErrorType.TypeError, "cannot create weak reference to '%p' object", object); - } } // getweakrefcount(obj) @@ -162,7 +197,7 @@ public Object getCount(PReferenceType pReferenceType) { } @Specialization - public Object getCount(PNone none) { + public Object getCount(@SuppressWarnings("unused") PNone none) { return 0; } } @@ -172,7 +207,7 @@ public Object getCount(PNone none) { @GenerateNodeFactory public abstract static class GetWeakRefsNode extends PythonBuiltinNode { @Specialization - public Object getRefs(PythonObject pythonObject) { + public Object getRefs(@SuppressWarnings("unused") PythonObject pythonObject) { return PNone.NONE; } } @@ -182,7 +217,7 @@ public Object getRefs(PythonObject pythonObject) { @GenerateNodeFactory public abstract static class RemoveDeadWeakRefsNode extends PythonBuiltinNode { @Specialization - public Object removeDeadRefs(PDict dict, Object key) { + public Object removeDeadRefs(@SuppressWarnings("unused") PDict dict, @SuppressWarnings("unused") Object key) { // TODO: do the removal from the dict ... (_weakref.c:60) return PNone.NONE; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java index a8039d1b96..6e2294369a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java @@ -64,6 +64,7 @@ public abstract class NativeCAPISymbols { public static final String FUN_GET_TP_BASES = "get_tp_bases"; public static final String FUN_GET_TP_NAME = "get_tp_name"; public static final String FUN_GET_TP_MRO = "get_tp_mro"; + public static final String FUN_GET_TP_SUBCLASSES = "get_tp_subclasses"; public static final String FUN_DEREF_HANDLE = "truffle_deref_handle_for_managed"; public static final String FUN_GET_BYTE_ARRAY_TYPE_ID = "get_byte_array_typeid"; public static final String FUN_GET_PTR_ARRAY_TYPE_ID = "get_ptr_array_typeid"; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index 4f31a2ff91..b40bce9921 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -33,6 +33,7 @@ import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.PythonBuiltinClassType; +import com.oracle.graal.python.builtins.objects.PythonAbstractObject; import com.oracle.graal.python.builtins.objects.array.PArray; import com.oracle.graal.python.builtins.objects.bytes.PByteArray; import com.oracle.graal.python.builtins.objects.bytes.PBytes; @@ -564,6 +565,10 @@ public PReferenceType createReferenceType(LazyPythonClass cls, Object object, Ob return trace(new PReferenceType(cls, object, callback, queue)); } + public PReferenceType createReferenceType(Object object, Object callback, ReferenceQueue queue) { + return createReferenceType(PythonBuiltinClassType.PReferenceType, object, callback, queue); + } + /* * Frames, traces and exceptions */ From 934dcd9e01e5f7fa1d2c42e2bbf03c36d26467a4 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Jan 2019 09:44:49 +0100 Subject: [PATCH 078/202] Inherit special flags and slots. --- .../src/typeobject.c | 82 +++++++++++++++++-- 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/typeobject.c b/graalpython/com.oracle.graal.python.cext/src/typeobject.c index 304d8917b2..5f8b8dc4ff 100644 --- a/graalpython/com.oracle.graal.python.cext/src/typeobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/typeobject.c @@ -168,6 +168,70 @@ static PyObject* wrap_reverse_binop(binaryfunc f, PyObject* a, PyObject* b) { return f(b, a); } +static void +inherit_special(PyTypeObject *type, PyTypeObject *base) +{ + + /* Copying basicsize is connected to the GC flags */ + if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC) && + (base->tp_flags & Py_TPFLAGS_HAVE_GC) && + (!type->tp_traverse && !type->tp_clear)) { + type->tp_flags |= Py_TPFLAGS_HAVE_GC; + if (type->tp_traverse == NULL) + type->tp_traverse = base->tp_traverse; + if (type->tp_clear == NULL) + type->tp_clear = base->tp_clear; + } + { + /* The condition below could use some explanation. + It appears that tp_new is not inherited for static types + whose base class is 'object'; this seems to be a precaution + so that old extension types don't suddenly become + callable (object.__new__ wouldn't insure the invariants + that the extension type's own factory function ensures). + Heap types, of course, are under our control, so they do + inherit tp_new; static extension types that specify some + other built-in type as the default also + inherit object.__new__. */ + if (base != &PyBaseObject_Type || + (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + if (type->tp_new == NULL) + type->tp_new = base->tp_new; + } + } + if (type->tp_basicsize == 0) + type->tp_basicsize = base->tp_basicsize; + + /* Copy other non-function slots */ + +#undef COPYVAL +#define COPYVAL(SLOT) \ + if (type->SLOT == 0) type->SLOT = base->SLOT + + COPYVAL(tp_itemsize); + COPYVAL(tp_weaklistoffset); + COPYVAL(tp_dictoffset); + + /* Setup fast subclass flags */ + if (PyType_IsSubtype(base, (PyTypeObject*)PyExc_BaseException)) + type->tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS; + else if (PyType_IsSubtype(base, &PyType_Type)) + type->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS; + else if (PyType_IsSubtype(base, &PyLong_Type)) + type->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS; + else if (PyType_IsSubtype(base, &PyBytes_Type)) + type->tp_flags |= Py_TPFLAGS_BYTES_SUBCLASS; + else if (PyType_IsSubtype(base, &PyUnicode_Type)) + type->tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS; + else if (PyType_IsSubtype(base, &PyTuple_Type)) + type->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS; + else if (PyType_IsSubtype(base, &PyList_Type)) + type->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS; + else if (PyType_IsSubtype(base, &PyDict_Type)) + type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS; +} + + // TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between // TODO support member flags other than READONLY UPCALL_ID(AddMember); @@ -251,7 +315,7 @@ int PyType_Ready(PyTypeObject* cls) { if (base == NULL) { bases = PyTuple_New(0); } else { - bases = PyTuple_Pack(1, native_to_java(base)); + bases = PyTuple_Pack(1, base); } } else { // we need to resolve pointers to Python classes @@ -327,9 +391,13 @@ int PyType_Ready(PyTypeObject* cls) { } } - // initialize mro + /* initialize mro */ cls->tp_mro = UPCALL_CEXT_O(_jls_PyTruffle_Compute_Mro, cls); + /* Inherit special flags from dominant base */ + if (cls->tp_base != NULL) + inherit_special(cls, cls->tp_base); + ADD_IF_MISSING(cls->tp_alloc, PyType_GenericAlloc); ADD_IF_MISSING(cls->tp_new, PyType_GenericNew); @@ -451,12 +519,10 @@ int PyType_Ready(PyTypeObject* cls) { // CPython doesn't do that in 'PyType_Ready' but we must because a native type can inherit // dynamic slots from a managed Python class. Since the managed Python class may be created // when the C API is not loaded, we need to do that later. -// PyObject* inherited_slots_tuple = UPCALL_CEXT_O(_jls_PyTruffle_Type_Slots, native_to_java((PyObject*)javacls)); -// PyObject* inherited_slots_tuple = PyObject_GetAttrString(cls, "__slots__"); -// if(inherited_slots_tuple != NULL) { -// PyTruffle_Debug(native_to_java(inherited_slots_tuple)); -// PyTruffle_Type_AddSlots(cls, inherited_slots_tuple); -// } + PyObject* inherited_slots_tuple = UPCALL_CEXT_O(_jls_PyTruffle_Type_Slots, native_to_java((PyObject*)cls)); + if(inherited_slots_tuple != NULL) { + PyTruffle_Type_AddSlots(cls, inherited_slots_tuple); + } /* Link into each base class's list of subclasses */ bases = cls->tp_bases; From 6641fa5675c6dd12d5c2942b7ccdc8c5d154027d Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Jan 2019 11:20:58 +0100 Subject: [PATCH 079/202] Support native types in 'GetSubclassesNode'. --- .../src/typeobject.c | 12 +- .../builtins/objects/type/TypeNodes.java | 104 +++++++++++++++++- 2 files changed, 106 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/typeobject.c b/graalpython/com.oracle.graal.python.cext/src/typeobject.c index 5f8b8dc4ff..94fc410037 100644 --- a/graalpython/com.oracle.graal.python.cext/src/typeobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/typeobject.c @@ -326,14 +326,6 @@ int PyType_Ready(PyTypeObject* cls) { } cls->tp_bases = bases; - PyObject* native_members = PyDict_New(); - PyDict_SetItemString(native_members, "tp_name", polyglot_from_string(cls->tp_name, SRC_CS)); - PyDict_SetItemString(native_members, "tp_doc", polyglot_from_string(cls->tp_doc ? cls->tp_doc : "", SRC_CS)); - PyDict_SetItemString(native_members, "tp_basicsize", PyLong_FromSsize_t(cls->tp_basicsize)); - PyDict_SetItemString(native_members, "tp_itemsize", PyLong_FromSsize_t(cls->tp_itemsize)); - PyDict_SetItemString(native_members, "tp_dictoffset", PyLong_FromSsize_t(cls->tp_dictoffset)); - const char* class_name = cls->tp_name; - /* Initialize tp_dict */ PyObject* dict = cls->tp_dict; if (dict == NULL) { @@ -344,7 +336,6 @@ int PyType_Ready(PyTypeObject* cls) { cls->tp_dict = dict; } - PyMethodDef* methods = cls->tp_methods; if (methods) { int idx = 0; @@ -524,6 +515,9 @@ int PyType_Ready(PyTypeObject* cls) { PyTruffle_Type_AddSlots(cls, inherited_slots_tuple); } + /* Initialize this classes' tp_subclasses dict. This is necessary because our managed classes won't do. */ + cls->tp_subclasses = PyDict_New(); + /* Link into each base class's list of subclasses */ bases = cls->tp_bases; Py_ssize_t n = PyTuple_GET_SIZE(bases); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index fb651e1d78..ed59b61919 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -43,6 +43,9 @@ import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -53,7 +56,11 @@ import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr; +import com.oracle.graal.python.builtins.objects.common.HashingStorage; +import com.oracle.graal.python.builtins.objects.common.HashingStorage.Equivalence; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; +import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass.FlagsContainer; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetBaseClassesNodeGen; @@ -68,6 +75,7 @@ import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialMethodNames; +import com.oracle.graal.python.nodes.truffle.PythonTypes; import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage; import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage; import com.oracle.truffle.api.CompilerAsserts; @@ -77,8 +85,10 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; @@ -285,6 +295,8 @@ public static GetSuperClassNode create() { } + @TypeSystemReference(PythonTypes.class) + @ImportStatic(NativeMemberNames.class) public abstract static class GetSubclassesNode extends PNodeWithContext { public abstract Set execute(Object obj); @@ -299,6 +311,21 @@ Set doPythonClass(PythonBuiltinClassType obj) { return getBuiltinPythonClass(obj).getSubClasses(); } + @Specialization + @TruffleBoundary + Set doNativeClass(PythonNativeClass obj, + @Cached("create(TP_SUBCLASSES)") GetTypeMemberNode getTpSubclassesNode, + @Cached("createClassProfile()") ValueProfile profile) { + Object tpSubclasses = getTpSubclassesNode.execute(obj); + + Object profiled = profile.profile(tpSubclasses); + if (profiled instanceof PDict) { + return wrapDict(profiled); + } + CompilerDirectives.transferToInterpreter(); + throw new IllegalStateException("invalid subclasses dict " + profiled.getClass().getName()); + } + @TruffleBoundary public static Set doSlowPath(Object obj) { if (obj instanceof ManagedPythonClass) { @@ -306,11 +333,86 @@ public static Set doSlowPath(Object obj) { } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getSubClasses(); } else if (PGuards.isNativeClass(obj)) { - // TODO implement + Object tpSubclasses = GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_SUBCLASSES); + if (tpSubclasses instanceof PDict) { + return wrapDict(tpSubclasses); + } + throw new IllegalStateException("invalid subclasses dict " + tpSubclasses.getClass().getName()); } throw new IllegalStateException("unknown type " + obj.getClass().getName()); } + private static Set wrapDict(Object tpSubclasses) { + return new Set() { + private final PDict dict = (PDict) tpSubclasses; + + public int size() { + return dict.getDictStorage().length(); + } + + public boolean isEmpty() { + return size() == 0; + } + + public boolean contains(Object o) { + HashingStorage s = dict.getDictStorage(); + Equivalence equiv = HashingStorage.getSlowPathEquivalence(o); + for (Object val : s.values()) { + if (equiv.equals(o, val)) { + return true; + } + } + return false; + } + + @SuppressWarnings("unchecked") + public Iterator iterator() { + return (Iterator) dict.getDictStorage().values(); + } + + public Object[] toArray() { + return dict.getDictStorage().valuesAsArray(); + } + + public T[] toArray(T[] a) { + throw new UnsupportedOperationException(); + } + + public boolean add(AbstractPythonClass e) { + if (PGuards.isNativeClass(e)) { + dict.setItem(PythonNativeClass.cast(e).getPtr(), e); + } + dict.setItem(new PythonNativeVoidPtr((TruffleObject) e), e); + return true; + } + + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + public boolean containsAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + }; + } + public static GetSubclassesNode create() { return GetSubclassesNodeGen.create(); } From 8890ec972ecd35103ec8312ec947c26000fee078 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Jan 2019 11:22:12 +0100 Subject: [PATCH 080/202] Implement get/set descr for '__itemsize__', '__basicsize__', and '__dictoffset__'. --- .../builtins/modules/BuiltinConstructors.java | 30 +++- .../builtins/objects/type/TypeBuiltins.java | 136 ++++++++++++++++-- 2 files changed, 147 insertions(+), 19 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index ad2898b0db..dace844457 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -49,8 +49,11 @@ import static com.oracle.graal.python.nodes.BuiltinNames.TUPLE; import static com.oracle.graal.python.nodes.BuiltinNames.TYPE; import static com.oracle.graal.python.nodes.BuiltinNames.ZIP; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASICSIZE__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICTOFFSET__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICT__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__FILE__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__ITEMSIZE__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MODULE__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__SLOTS__; @@ -123,8 +126,8 @@ import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.PGuards; -import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.argument.CreateArgumentsNode; +import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetAnyAttributeNode; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; @@ -1342,6 +1345,9 @@ public final Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeywo @Specialization Object doDirectConstruct(@SuppressWarnings("unused") PNone ignored, Object[] arguments, @SuppressWarnings("unused") PKeyword[] kwargs) { + if (PGuards.isNativeClass(arguments[0])) { + throw raise(PythonBuiltinClassType.SystemError, "cannot instantiate native class here"); + } return factory().createPythonObject((LazyPythonClass) arguments[0]); } @@ -1739,6 +1745,7 @@ public abstract static class TypeNode extends PythonBuiltinNode { private static final long SIZEOF_PY_OBJECT_PTR = Long.BYTES; @Child private ReadAttributeFromObjectNode readAttrNode; @Child private WriteAttributeToObjectNode writeAttrNode; + @Child private GetAnyAttributeNode getAttrNode; @Child private CastToIndexNode castToInt; @Child private CastToListNode castToList; @Child private CastToStringNode castToStringNode; @@ -2043,9 +2050,10 @@ private boolean addDictIfNative(ManagedPythonClass pythonClass) { if (pythonClass.needsNativeAllocation()) { for (Object cls : getMro(pythonClass)) { if (PGuards.isNativeClass(cls)) { - long dictoffset = ensureCastToIntNode().execute(ensureReadAttrNode().execute(cls, SpecialAttributeNames.__DICTOFFSET__)); - long basicsize = ensureCastToIntNode().execute(ensureReadAttrNode().execute(cls, SpecialAttributeNames.__BASICSIZE__)); - long itemsize = ensureCastToIntNode().execute(ensureReadAttrNode().execute(cls, SpecialAttributeNames.__ITEMSIZE__)); + // Use GetAnyAttributeNode since these are get-set-descriptors + long dictoffset = ensureCastToIntNode().execute(ensureGetAttributeNode().executeObject(cls, __DICTOFFSET__)); + long basicsize = ensureCastToIntNode().execute(ensureGetAttributeNode().executeObject(cls, __BASICSIZE__)); + long itemsize = ensureCastToIntNode().execute(ensureGetAttributeNode().executeObject(cls, __ITEMSIZE__)); if (dictoffset == 0) { addedNewDict = true; // add_dict @@ -2056,9 +2064,9 @@ private boolean addDictIfNative(ManagedPythonClass pythonClass) { basicsize += SIZEOF_PY_OBJECT_PTR; } } - ensureWriteAttrNode().execute(pythonClass, SpecialAttributeNames.__DICTOFFSET__, dictoffset); - ensureWriteAttrNode().execute(pythonClass, SpecialAttributeNames.__BASICSIZE__, basicsize); - ensureWriteAttrNode().execute(pythonClass, SpecialAttributeNames.__ITEMSIZE__, itemsize); + ensureWriteAttrNode().execute(pythonClass, __DICTOFFSET__, dictoffset); + ensureWriteAttrNode().execute(pythonClass, __BASICSIZE__, basicsize); + ensureWriteAttrNode().execute(pythonClass, __ITEMSIZE__, itemsize); break; } } @@ -2138,6 +2146,14 @@ private ReadAttributeFromObjectNode ensureReadAttrNode() { return readAttrNode; } + private GetAnyAttributeNode ensureGetAttributeNode() { + if (getAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getAttrNode = insert(GetAnyAttributeNode.create()); + } + return getAttrNode; + } + private WriteAttributeToObjectNode ensureWriteAttrNode() { if (writeAttrNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 47403573e7..b69d4b0e44 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -27,8 +27,11 @@ package com.oracle.graal.python.builtins.objects.type; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASES__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASICSIZE__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CLASS__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICTOFFSET__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICT__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__ITEMSIZE__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MODULE__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MRO__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__; @@ -95,6 +98,7 @@ import com.oracle.graal.python.nodes.object.GetClassNode; import com.oracle.graal.python.nodes.object.GetLazyClassNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; +import com.oracle.graal.python.nodes.truffle.PythonTypes; import com.oracle.graal.python.runtime.exception.PythonErrorType; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -105,6 +109,7 @@ import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -542,10 +547,14 @@ private static Object[] toArray(Set subclasses) { } } - @Builtin(name = __NAME__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) @GenerateNodeFactory @ImportStatic(NativeMemberNames.class) - static abstract class NameNode extends PythonBinaryBuiltinNode { + @TypeSystemReference(PythonTypes.class) + static abstract class AbstractSlotNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = __NAME__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) + static abstract class NameNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { return cls.getName(); @@ -593,9 +602,7 @@ private static String getQualName(String fqname) { } @Builtin(name = __MODULE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) - @GenerateNodeFactory - @ImportStatic(NativeMemberNames.class) - static abstract class ModuleNode extends PythonBinaryBuiltinNode { + static abstract class ModuleNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") Object getModule(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { @@ -621,7 +628,7 @@ Object setModule(PythonClass cls, Object value, } @Specialization(guards = "isNoValue(value)") - Object getModule(PythonAbstractNativeObject cls, @SuppressWarnings("unused") PNone value, + Object getModule(PythonNativeClass cls, @SuppressWarnings("unused") PNone value, @Cached("create(TP_NAME)") GetTypeMemberNode getTpNameNode) { // 'tp_name' contains the fully-qualified name, i.e., 'module.A.B...' String tpName = (String) getTpNameNode.execute(cls); @@ -629,7 +636,7 @@ Object getModule(PythonAbstractNativeObject cls, @SuppressWarnings("unused") PNo } @Specialization(guards = "!isNoValue(value)") - Object getModule(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @SuppressWarnings("unused") Object value) { + Object setNative(@SuppressWarnings("unused") PythonNativeClass cls, @SuppressWarnings("unused") Object value) { throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type"); } @@ -648,9 +655,7 @@ protected String getBuiltinsName() { } @Builtin(name = __QUALNAME__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) - @GenerateNodeFactory - @ImportStatic(NativeMemberNames.class) - static abstract class QualNameNode extends PythonBinaryBuiltinNode { + static abstract class QualNameNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { return cls.getName(); @@ -674,7 +679,7 @@ Object setName(PythonClass cls, Object value, } @Specialization(guards = "isNoValue(value)") - String getNative(PythonAbstractNativeObject cls, @SuppressWarnings("unused") PNone value, + String getNative(PythonNativeClass cls, @SuppressWarnings("unused") PNone value, @Cached("create(TP_NAME)") GetTypeMemberNode getTpNameNode) { // 'tp_name' contains the fully-qualified name, i.e., 'module.A.B...' String tpName = (String) getTpNameNode.execute(cls); @@ -682,7 +687,7 @@ String getNative(PythonAbstractNativeObject cls, @SuppressWarnings("unused") PNo } @Specialization(guards = "!isNoValue(value)") - Object getModule(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @SuppressWarnings("unused") Object value) { + Object setNative(@SuppressWarnings("unused") PythonNativeClass cls, @SuppressWarnings("unused") Object value) { throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type"); } @@ -694,6 +699,113 @@ private static String getQualName(String fqname) { } return fqname; } + } + + @Builtin(name = __DICTOFFSET__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) + static abstract class DictoffsetNode extends AbstractSlotNode { + @Specialization(guards = "isNoValue(value)") + String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { + return cls.getName(); + } + + @Specialization(guards = {"isNoValue(value)", "!isPythonBuiltinClass(cls)"}) + Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create()") ReadAttributeFromObjectNode getName) { + return getName.execute(cls, __DICTOFFSET__); + } + + @Specialization(guards = "!isNoValue(value)") + Object setName(@SuppressWarnings("unused") PythonBuiltinClass cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of built-in/extension 'type'"); + } + + @Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)"}) + Object setName(PythonClass cls, Object value, + @Cached("create()") WriteAttributeToObjectNode setName) { + return setName.execute(cls, __DICTOFFSET__, value); + } + + @Specialization(guards = "isNoValue(value)") + Object getNative(PythonNativeClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create(TP_DICTOFFSET)") GetTypeMemberNode getTpDictoffsetNode) { + return getTpDictoffsetNode.execute(cls); + } + + @Specialization(guards = "!isNoValue(value)") + Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type"); + } + } + + @Builtin(name = __ITEMSIZE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) + static abstract class ItemsizeNode extends AbstractSlotNode { + @Specialization(guards = "isNoValue(value)") + String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { + return cls.getName(); + } + + @Specialization(guards = {"isNoValue(value)", "!isPythonBuiltinClass(cls)"}) + Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create()") ReadAttributeFromObjectNode getName) { + return getName.execute(cls, __ITEMSIZE__); + } + + @Specialization(guards = "!isNoValue(value)") + Object setName(@SuppressWarnings("unused") PythonBuiltinClass cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of built-in/extension 'type'"); + } + + @Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)"}) + Object setName(PythonClass cls, Object value, + @Cached("create()") WriteAttributeToObjectNode setName) { + return setName.execute(cls, __ITEMSIZE__, value); + } + + @Specialization(guards = "isNoValue(value)") + Object getNative(PythonNativeClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create(TP_ITEMSIZE)") GetTypeMemberNode getTpDictoffsetNode) { + return getTpDictoffsetNode.execute(cls); + } + + @Specialization(guards = "!isNoValue(value)") + Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type"); + } + } + @Builtin(name = __BASICSIZE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) + static abstract class BasicsizeNode extends AbstractSlotNode { + @Specialization(guards = "isNoValue(value)") + String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { + return cls.getName(); + } + + @Specialization(guards = {"isNoValue(value)", "!isPythonBuiltinClass(cls)"}) + Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create()") ReadAttributeFromObjectNode getName) { + return getName.execute(cls, __BASICSIZE__); + } + + @Specialization(guards = "!isNoValue(value)") + Object setName(@SuppressWarnings("unused") PythonBuiltinClass cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of built-in/extension 'type'"); + } + + @Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)"}) + Object setName(PythonClass cls, Object value, + @Cached("create()") WriteAttributeToObjectNode setName) { + return setName.execute(cls, __BASICSIZE__, value); + } + + @Specialization(guards = "isNoValue(value)") + Object getNative(PythonNativeClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create(TP_BASICSIZE)") GetTypeMemberNode getTpDictoffsetNode) { + return getTpDictoffsetNode.execute(cls); + } + + @Specialization(guards = "!isNoValue(value)") + Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @SuppressWarnings("unused") Object value) { + throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type"); + } } } From 5ac9ce5638d8241dee0133abd419bb9a9bf5f6d7 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Jan 2019 11:26:15 +0100 Subject: [PATCH 081/202] Remove obsolete 'python_cext.PyType_Ready' builtin. --- .../builtins/modules/TruffleCextBuiltins.java | 151 ------------------ 1 file changed, 151 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 20676c7a59..ccc8835677 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -42,8 +42,6 @@ import static com.oracle.graal.python.builtins.PythonBuiltinClassType.IndexError; import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError; -import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASICSIZE__; -import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICTOFFSET__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__; import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError; @@ -97,7 +95,6 @@ import com.oracle.graal.python.builtins.objects.cext.UnicodeObjectNodes.UnicodeAsWideCharNode; import com.oracle.graal.python.builtins.objects.code.PCode; import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes; -import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.CastToByteNode; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NormalizeIndexNode; @@ -127,7 +124,6 @@ import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; -import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; @@ -551,153 +547,6 @@ Object setattr(PythonNativeClass object, String key, Object value, } } - @Builtin(name = "PyType_Ready", fixedNumOfPositionalArgs = 4) - @GenerateNodeFactory - abstract static class PyType_ReadyNode extends PythonBuiltinNode { - @Child private WriteAttributeToObjectNode writeAttrNode = WriteAttributeToObjectNode.create(); - @Child private HashingStorageNodes.GetItemNode getItemNode; - @Child private CastToIndexNode castToIntNode; - @Child private ReadAttributeFromObjectNode readAttrNode; - @Child private SequenceStorageNodes.LenNode slotLenNode; - @Child private SequenceStorageNodes.GetItemNode getSlotItemNode; - @Child private SequenceStorageNodes.AppendNode setSlotItemNode; - @Child private HashingStorageNodes.ContainsKeyNode containsKeyNode; - @Child private CExtNodes.PCallCapiFunction callAddNativeSlotsNode; - @Child private CExtNodes.ToSulongNode toSulongNode; - @Child private GetMroNode getMroNode; - - private HashingStorageNodes.GetItemNode getGetItemNode() { - if (getItemNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - getItemNode = insert(HashingStorageNodes.GetItemNode.create()); - } - return getItemNode; - } - - @Specialization - Object run(Object typestruct, PythonObjectNativeWrapper metaClass, PythonObjectNativeWrapper baseClasses, PythonObjectNativeWrapper nativeMembers, - @Cached("create()") CExtNodes.ToJavaNode toJavaNode) { - // TODO(fa) use recursive node - return run(typestruct, (PythonClass) toJavaNode.execute(metaClass), (PTuple) toJavaNode.execute(baseClasses), (PDict) toJavaNode.execute(nativeMembers)); - } - - @Specialization - Object run(Object typestruct, PythonClass metaClass, PTuple baseClasses, PDict nativeMembers) { -// Object[] array = baseClasses.getArray(); -// PythonClass[] bases = new PythonClass[array.length]; -// for (int i = 0; i < array.length; i++) { -// bases[i] = (PythonClass) array[i]; -// } -// -// if (castToIntNode == null) { -// CompilerDirectives.transferToInterpreterAndInvalidate(); -// castToIntNode = insert(CastToIndexNode.create()); -// } -// -// // 'tp_name' contains the fully-qualified name, i.e., 'module.A.B...' -// String fqname = getStringItem(nativeMembers, TP_NAME); -// String doc = getStringItem(nativeMembers, TP_DOC); -// // the qualified name (i.e. without module name) like 'A.B...' -// String qualName = getQualName(fqname); -// PythonNativeClass cclass = factory().createNativeClassWrapper(typestruct, metaClass, qualName, -// bases); -// writeAttrNode.execute(cclass, SpecialAttributeNames.__DOC__, doc); -// -// long basicsize = castToIntNode.execute(getLongItem(nativeMembers, TP_BASICSIZE)); -// long itemsize = castToIntNode.execute(getLongItem(nativeMembers, TP_ITEMSIZE)); -// writeAttrNode.execute(cclass, __BASICSIZE__, basicsize); -// writeAttrNode.execute(cclass, __ITEMSIZE__, itemsize); -// computeAndSetDictoffset(getLongItem(nativeMembers, TP_DICTOFFSET), cclass, basicsize, itemsize); -// -// String moduleName = getModuleName(fqname); -// if (moduleName != null) { -// writeAttrNode.execute(cclass, SpecialAttributeNames.__MODULE__, moduleName); -// } -// return new PythonClassInitNativeWrapper(cclass); - return null; - } - - // may also update '__basicsize__' if necessary - private void computeAndSetDictoffset(Object tpDictoffset, PythonNativeClass cclass, long basicsize, long itemsize) { - int initialDictoffset = castToIntNode.execute(tpDictoffset); - if (initialDictoffset == 0) { - for (Object cls : getMro(cclass)) { - if (cls != cclass) { - if (PGuards.isNativeClass(cls)) { - int baseDictoffset = castToIntNode.execute(ensureReadAttrNode().execute(cls, __DICTOFFSET__)); - if (baseDictoffset != 0) { - long dictoffset; - // add_dict - if (itemsize != 0) { - dictoffset = -Long.BYTES; - } else { - dictoffset = basicsize; - } - writeAttrNode.execute(cclass, __DICTOFFSET__, dictoffset); - writeAttrNode.execute(cclass, __BASICSIZE__, basicsize + Long.BYTES); - return; - } - } else if (!(cls instanceof PythonBuiltinClass)) { - writeAttrNode.execute(cclass, __DICTOFFSET__, itemsize == 0 ? basicsize : -Long.BYTES); - writeAttrNode.execute(cclass, __BASICSIZE__, basicsize + Long.BYTES); - return; - } - } - } - } - writeAttrNode.execute(cclass, __DICTOFFSET__, 0); - return; - } - - private ReadAttributeFromObjectNode ensureReadAttrNode() { - if (readAttrNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - readAttrNode = insert(ReadAttributeFromObjectNode.create()); - } - return readAttrNode; - } - - private static String getQualName(String fqname) { - int firstDot = fqname.indexOf('.'); - if (firstDot != -1) { - return fqname.substring(firstDot + 1); - } - return fqname; - } - - private static String getModuleName(String fqname) { - int firstDotIdx = fqname.indexOf('.'); - if (firstDotIdx != -1) { - return fqname.substring(0, firstDotIdx); - } - return null; - } - - private String getStringItem(PDict nativeMembers, String key) { - Object item = getGetItemNode().execute(nativeMembers.getDictStorage(), key); - if (item instanceof PString) { - return ((PString) item).getValue(); - } - return (String) item; - } - - private Object getLongItem(PDict nativeMembers, String key) { - Object item = getGetItemNode().execute(nativeMembers.getDictStorage(), key); - if (item instanceof PInt || item instanceof Number) { - return item; - } - return (long) item; - } - - private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { - if (getMroNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - getMroNode = insert(GetMroNode.create()); - } - return getMroNode.execute(clazz); - } - } - @Builtin(name = "PyTruffle_Type_Slots", fixedNumOfPositionalArgs = 2, declaresExplicitSelf = true) @GenerateNodeFactory @ImportStatic(SpecialAttributeNames.class) From 85470bcc2719ae83972dae9a40bf04f557ea112b Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Jan 2019 11:36:09 +0100 Subject: [PATCH 082/202] Support native type in 'GetSuperClassNode'. --- .../builtins/objects/type/TypeNodes.java | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index ed59b61919..264aa4193c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -40,11 +40,11 @@ */ package com.oracle.graal.python.builtins.objects.type; +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError; import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__; import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -92,6 +92,7 @@ import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; public abstract class TypeNodes { @@ -263,20 +264,34 @@ public static GetNameNode create() { } + @TypeSystemReference(PythonTypes.class) + @ImportStatic(NativeMemberNames.class) public abstract static class GetSuperClassNode extends PNodeWithContext { public abstract LazyPythonClass execute(Object obj); @Specialization - LazyPythonClass doPythonClass(ManagedPythonClass obj) { + LazyPythonClass doManaged(ManagedPythonClass obj) { return obj.getSuperClass(); } @Specialization - LazyPythonClass doPythonClass(PythonBuiltinClassType obj) { + LazyPythonClass doBuiltin(PythonBuiltinClassType obj) { return obj.getBase(); } + @Specialization + LazyPythonClass doNative(PythonNativeClass obj, + @Cached("create(TP_BASE)") GetTypeMemberNode getTpBaseNode, + @Cached("createBinaryProfile()") ConditionProfile profile) { + Object tpBaseObj = getTpBaseNode.execute(obj); + if (profile.profile(PGuards.isClass(tpBaseObj))) { + return (AbstractPythonClass) tpBaseObj; + } + CompilerDirectives.transferToInterpreter(); + throw raise(SystemError, "Invalid base type object for class %s (base type was '%p' object).", GetNameNode.doSlowPath(obj), tpBaseObj); + } + @TruffleBoundary public static LazyPythonClass doSlowPath(Object obj) { if (obj instanceof ManagedPythonClass) { @@ -284,7 +299,11 @@ public static LazyPythonClass doSlowPath(Object obj) { } else if (obj instanceof PythonBuiltinClassType) { return ((PythonBuiltinClassType) obj).getBase(); } else if (PGuards.isNativeClass(obj)) { - // TODO implement + Object tpBaseObj = GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_BASE); + if (PGuards.isClass(tpBaseObj)) { + return (AbstractPythonClass) tpBaseObj; + } + PythonLanguage.getCore().raise(SystemError, "Invalid base type object for class %s (base type was '%p' object).", GetNameNode.doSlowPath(obj), tpBaseObj); } throw new IllegalStateException("unknown type " + obj.getClass().getName()); } From 99aa8a94d36b7603e6ea3c031fe657c5a7c796b3 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Jan 2019 11:56:09 +0100 Subject: [PATCH 083/202] Add missing native member getters. --- .../com.oracle.graal.python.cext/src/capi.c | 15 +++++++++++++++ .../builtins/objects/cext/NativeCAPISymbols.java | 3 +++ 2 files changed, 18 insertions(+) diff --git a/graalpython/com.oracle.graal.python.cext/src/capi.c b/graalpython/com.oracle.graal.python.cext/src/capi.c index b34561ce05..42f55f73a1 100644 --- a/graalpython/com.oracle.graal.python.cext/src/capi.c +++ b/graalpython/com.oracle.graal.python.cext/src/capi.c @@ -284,6 +284,21 @@ PyObject* get_tp_subclasses(PyTypeObject* obj) { return native_to_java(obj->tp_subclasses); } +/** to be used from Java code only; reads native 'tp_dictoffset' field */ +Py_ssize_t get_tp_dictoffset(PyTypeObject* obj) { + return obj->tp_dictoffset; +} + +/** to be used from Java code only; reads native 'tp_itemsize' field */ +Py_ssize_t get_tp_itemsize(PyTypeObject* obj) { + return obj->tp_itemsize; +} + +/** to be used from Java code only; reads native 'tp_basicsize' field */ +Py_ssize_t get_tp_basicsize(PyTypeObject* obj) { + return obj->tp_basicsize; +} + /** to be used from Java code only; returns the type ID for a byte array */ polyglot_typeid get_byte_array_typeid(uint64_t len) { return polyglot_array_typeid(polyglot_i8_typeid(), len); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java index 6e2294369a..1d21acd9c4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java @@ -65,6 +65,9 @@ public abstract class NativeCAPISymbols { public static final String FUN_GET_TP_NAME = "get_tp_name"; public static final String FUN_GET_TP_MRO = "get_tp_mro"; public static final String FUN_GET_TP_SUBCLASSES = "get_tp_subclasses"; + public static final String FUN_GET_TP_DICTOFFSET = "get_tp_dictoffset"; + public static final String FUN_GET_TP_BASICSIZE = "get_tp_basicsize"; + public static final String FUN_GET_TP_ITEMSIZE = "get_tp_itemsize"; public static final String FUN_DEREF_HANDLE = "truffle_deref_handle_for_managed"; public static final String FUN_GET_BYTE_ARRAY_TYPE_ID = "get_byte_array_typeid"; public static final String FUN_GET_PTR_ARRAY_TYPE_ID = "get_ptr_array_typeid"; From 5c859a2ccab659e80dca2407da996f702931ec6f Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Jan 2019 16:44:35 +0100 Subject: [PATCH 084/202] Do not overwrite get/set descr for '__basicsize__', '__itemsize__', and '__dictoffset__' from native code. --- .../builtins/modules/BuiltinConstructors.java | 7 +-- .../cext/PythonObjectNativeWrapperMR.java | 38 +++++++--------- .../builtins/objects/type/TypeBuiltins.java | 44 +++++++++++-------- .../nodes/attributes/SetAttributeNode.java | 4 ++ 4 files changed, 51 insertions(+), 42 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index dace844457..5e463cea4f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -131,6 +131,7 @@ import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; +import com.oracle.graal.python.nodes.attributes.SetAttributeNode; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; import com.oracle.graal.python.nodes.builtins.TupleNodes; import com.oracle.graal.python.nodes.call.CallDispatchNode; @@ -1744,7 +1745,7 @@ public PFunction function(Object cls, Object method_def, Object def, Object name public abstract static class TypeNode extends PythonBuiltinNode { private static final long SIZEOF_PY_OBJECT_PTR = Long.BYTES; @Child private ReadAttributeFromObjectNode readAttrNode; - @Child private WriteAttributeToObjectNode writeAttrNode; + @Child private SetAttributeNode.Dynamic writeAttrNode; @Child private GetAnyAttributeNode getAttrNode; @Child private CastToIndexNode castToInt; @Child private CastToListNode castToList; @@ -2154,10 +2155,10 @@ private GetAnyAttributeNode ensureGetAttributeNode() { return getAttrNode; } - private WriteAttributeToObjectNode ensureWriteAttrNode() { + private SetAttributeNode.Dynamic ensureWriteAttrNode() { if (writeAttrNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - writeAttrNode = insert(WriteAttributeToObjectNode.createForceType()); + writeAttrNode = insert(SetAttributeNode.Dynamic.create()); } return writeAttrNode; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index a5ed92df85..c1b5512fb1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -98,6 +98,7 @@ import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeBuiltins; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; @@ -108,6 +109,7 @@ import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialAttributeNames; import com.oracle.graal.python.nodes.SpecialMethodNames; +import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetFixedAttributeNode; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; @@ -501,14 +503,14 @@ Object doTpHash(ManagedPythonClass object, @SuppressWarnings("unused") String ke @Specialization(guards = "eq(TP_BASICSIZE, key)") Object doTpBasicsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, - @Cached("create(__BASICSIZE__)") LookupAttributeInMRONode getAttrNode) { - return getAttrNode.execute(object); + @Cached("create(__BASICSIZE__)") GetFixedAttributeNode getAttrNode) { + return getAttrNode.executeObject(object); } @Specialization(guards = "eq(TP_ITEMSIZE, key)") Object doTpItemsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, - @Cached("create(__ITEMSIZE__)") LookupAttributeInMRONode getAttrNode) { - Object val = getAttrNode.execute(object); + @Cached("create(__ITEMSIZE__)") GetFixedAttributeNode getAttrNode) { + Object val = getAttrNode.executeObject(object); // If the attribute does not exist, this means that we take 'tp_itemsize' from the base // object which is by default 0 (see typeobject.c:PyBaseObject_Type). if (val == PNone.NO_VALUE) { @@ -520,12 +522,12 @@ Object doTpItemsize(ManagedPythonClass object, @SuppressWarnings("unused") Strin @Specialization(guards = "eq(TP_DICTOFFSET, key)") Object doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create()") CastToIndexNode castToIntNode, - @Cached("create(__DICTOFFSET__)") LookupAttributeInMRONode getAttrNode) { + @Cached("create(__DICTOFFSET__)") GetFixedAttributeNode getAttrNode) { // TODO properly implement 'tp_dictoffset' for builtin classes if (object instanceof PythonBuiltinClass) { return 0L; } - Object dictoffset = getAttrNode.execute(object); + Object dictoffset = getAttrNode.executeObject(object); return castToIntNode.execute(dictoffset); } @@ -876,7 +878,7 @@ public Object access(PythonNativeWrapper object, String key, Object value) { } } - @ImportStatic({NativeMemberNames.class, PGuards.class, SpecialMethodNames.class}) + @ImportStatic({NativeMemberNames.class, PGuards.class, SpecialMethodNames.class, SpecialAttributeNames.class}) abstract static class WriteNativeMemberNode extends PNodeWithContext { @Child private HashingStorageNodes.SetItemNode setItemNode; @@ -896,20 +898,14 @@ long doTpFlags(ManagedPythonClass object, @SuppressWarnings("unused") String key } @Specialization(guards = "eq(TP_BASICSIZE, key)") - @TruffleBoundary - long doTpBasicsize(PythonBuiltinClass object, @SuppressWarnings("unused") String key, long basicsize) { - // We have to use the 'setAttributeUnsafe' because this properly cannot be modified by - // the user and we need to initialize it. - object.setAttributeUnsafe(SpecialAttributeNames.__BASICSIZE__, basicsize); - return basicsize; - } - - @Specialization(guards = "eq(TP_BASICSIZE, key)") - @TruffleBoundary - long doTpBasicsize(PythonClass object, @SuppressWarnings("unused") String key, long basicsize) { - // Do deliberately not use "SetAttributeNode" because we want to directly set the - // attribute an bypass any user code. - object.setAttribute(SpecialAttributeNames.__BASICSIZE__, basicsize); + long doTpBasicsize(AbstractPythonClass object, @SuppressWarnings("unused") String key, long basicsize, + @Cached("create()") WriteAttributeToObjectNode writeAttrNode, + @Cached("create()") IsBuiltinClassProfile profile) { + if (profile.profileClass(object, PythonBuiltinClassType.PythonClass)) { + writeAttrNode.execute(object, TypeBuiltins.TYPE_BASICSIZE, basicsize); + } else { + writeAttrNode.execute(object, SpecialAttributeNames.__BASICSIZE__, basicsize); + } return basicsize; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index b69d4b0e44..3b6359b80b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -111,12 +111,17 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.object.HiddenKey; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; @CoreFunctions(extendClasses = PythonBuiltinClassType.PythonClass) public class TypeBuiltins extends PythonBuiltins { + public static final HiddenKey TYPE_DICTOFFSET = new HiddenKey(__DICTOFFSET__); + public static final HiddenKey TYPE_ITEMSIZE = new HiddenKey(__ITEMSIZE__); + public static final HiddenKey TYPE_BASICSIZE = new HiddenKey(__BASICSIZE__); + @Override protected List> getNodeFactories() { return TypeBuiltinsFactory.getFactories(); @@ -703,14 +708,15 @@ private static String getQualName(String fqname) { @Builtin(name = __DICTOFFSET__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) static abstract class DictoffsetNode extends AbstractSlotNode { - @Specialization(guards = "isNoValue(value)") - String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { - return cls.getName(); - } - @Specialization(guards = {"isNoValue(value)", "!isPythonBuiltinClass(cls)"}) - Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value, + @Specialization(guards = "isNoValue(value)") + Object getName(ManagedPythonClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create()") IsBuiltinClassProfile profile, @Cached("create()") ReadAttributeFromObjectNode getName) { + // recursion anchor; since the metaclass of 'type' is 'type' + if (profile.profileClass(cls, PythonBuiltinClassType.PythonClass)) { + return getName.execute(cls, TYPE_DICTOFFSET); + } return getName.execute(cls, __DICTOFFSET__); } @@ -739,14 +745,15 @@ Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @Su @Builtin(name = __ITEMSIZE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) static abstract class ItemsizeNode extends AbstractSlotNode { - @Specialization(guards = "isNoValue(value)") - String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { - return cls.getName(); - } - @Specialization(guards = {"isNoValue(value)", "!isPythonBuiltinClass(cls)"}) - Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value, + @Specialization(guards = "isNoValue(value)") + Object getName(ManagedPythonClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create()") IsBuiltinClassProfile profile, @Cached("create()") ReadAttributeFromObjectNode getName) { + // recursion anchor; since the metaclass of 'type' is 'type' + if (profile.profileClass(cls, PythonBuiltinClassType.PythonClass)) { + return getName.execute(cls, TYPE_ITEMSIZE); + } return getName.execute(cls, __ITEMSIZE__); } @@ -775,14 +782,15 @@ Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @Su @Builtin(name = __BASICSIZE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) static abstract class BasicsizeNode extends AbstractSlotNode { - @Specialization(guards = "isNoValue(value)") - String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { - return cls.getName(); - } - @Specialization(guards = {"isNoValue(value)", "!isPythonBuiltinClass(cls)"}) - Object getName(PythonClass cls, @SuppressWarnings("unused") PNone value, + @Specialization(guards = "isNoValue(value)") + Object getName(ManagedPythonClass cls, @SuppressWarnings("unused") PNone value, + @Cached("create()") IsBuiltinClassProfile profile, @Cached("create()") ReadAttributeFromObjectNode getName) { + // recursion anchor; since the metaclass of 'type' is 'type' + if (profile.profileClass(cls, PythonBuiltinClassType.PythonClass)) { + return getName.execute(cls, TYPE_BASICSIZE); + } return getName.execute(cls, __BASICSIZE__); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/SetAttributeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/SetAttributeNode.java index 165771f5bc..0c8f1c8010 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/SetAttributeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/SetAttributeNode.java @@ -62,6 +62,10 @@ public static final class Dynamic extends PNodeWithContext { public void execute(Object object, Object key, Object value) { call.execute(object, key, value); } + + public static Dynamic create() { + return new Dynamic(); + } } private final String key; From 09f920488716e289aca54b83586b2f218af690b7 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Jan 2019 17:05:33 +0100 Subject: [PATCH 085/202] Correctly distinguish between native object and native type. --- .../builtins/objects/cext/CExtNodes.java | 23 +++++++++---- .../objects/superobject/SuperBuiltins.java | 14 ++++++-- .../builtins/objects/type/TypeNodes.java | 34 +++++++++++++++++++ .../python/nodes/statement/ExceptNode.java | 12 ++++++- .../interop/PythonMessageResolution.java | 9 ++++- 5 files changed, 81 insertions(+), 11 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index aa73dce537..edbe8e7ae3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -334,7 +334,7 @@ Object doPythonClassUncached(ManagedPythonClass object, return PythonClassNativeWrapper.wrap(object, getNameNode.execute(object)); } - @Specialization(guards = {"cachedClass == object.getClass()", "!isPythonClass(object)", "!isNativeObject(object)", "!isNoValue(object)"}, limit = "3") + @Specialization(guards = {"cachedClass == object.getClass()", "!isClass(object)", "!isNativeObject(object)", "!isNoValue(object)"}, limit = "3") Object runAbstractObjectCached(PythonAbstractObject object, @Cached("createBinaryProfile()") ConditionProfile noWrapperProfile, @Cached("object.getClass()") Class cachedClass) { @@ -342,7 +342,7 @@ Object runAbstractObjectCached(PythonAbstractObject object, return PythonObjectNativeWrapper.wrap(CompilerDirectives.castExact(object, cachedClass), noWrapperProfile); } - @Specialization(guards = {"!isPythonClass(object)", "!isNativeObject(object)", "!isNoValue(object)"}, replaces = "runAbstractObjectCached") + @Specialization(guards = {"!isClass(object)", "!isNativeObject(object)", "!isNoValue(object)"}, replaces = "runAbstractObjectCached") Object runAbstractObject(PythonAbstractObject object, @Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) { assert object != PNone.NO_VALUE; @@ -360,10 +360,6 @@ Object run(Object obj) { return obj; } - protected static boolean isPythonClass(PythonAbstractObject o) { - return o instanceof AbstractPythonClass; - } - protected static PythonClassNativeWrapper wrapNativeClass(ManagedPythonClass object) { return PythonClassNativeWrapper.wrap(object, GetNameNode.doSlowPath(object)); } @@ -391,7 +387,7 @@ public static Object doSlowPath(Object o) { } else if (o instanceof ManagedPythonClass) { return wrapNativeClass((ManagedPythonClass) o); } else if (o instanceof PythonAbstractObject) { - assert !(o instanceof AbstractPythonClass); + assert !PGuards.isClass(o); return PythonObjectNativeWrapper.wrapSlowPath((PythonAbstractObject) o); } else if (PGuards.isForeignObject(o)) { return TruffleObjectNativeWrapper.wrap((TruffleObject) o); @@ -1616,6 +1612,9 @@ public static class GetTypeMemberNode extends GetNativeDictNode { @Child private ToSulongNode toSulong; @Child private AsPythonObjectNode toJava; @Child private PCallCapiFunction callGetTpDictNode; + @Child private GetLazyClassNode getNativeClassNode; + + @CompilationFinal private IsBuiltinClassProfile isTypeProfile; private GetTypeMemberNode(String memberName) { String getterFuncName = "get_" + memberName; @@ -1632,9 +1631,19 @@ public Object execute(Object self) { toSulong = insert(ToSulongNode.create()); toJava = insert(AsPythonObjectNode.create()); } + assert isNativeTypeObject(self); return toJava.execute(callGetTpDictNode.call(toSulong.execute(self))); } + private boolean isNativeTypeObject(Object self) { + if (getNativeClassNode == null || isTypeProfile == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getNativeClassNode = insert(GetLazyClassNode.create()); + isTypeProfile = IsBuiltinClassProfile.create(); + } + return isTypeProfile.profileClass(getNativeClassNode.execute(self), PythonBuiltinClassType.PythonClass); + } + @TruffleBoundary public static Object doSlowPath(Object self, String memberName) { String getterFuncName = "get_" + memberName; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java index 9cda6258c1..0c01ed8053 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java @@ -60,6 +60,7 @@ import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetTypeNodeGen; import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.SuperInitNodeFactory; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; import com.oracle.graal.python.nodes.SpecialAttributeNames; @@ -158,6 +159,7 @@ public abstract static class SuperInitNode extends PythonVarargsBuiltinNode { @Child private GetClassNode getClassNode; @Child private LookupAndCallBinaryNode getAttrNode; @Child private CellBuiltins.GetRefNode getRefNode; + @Child private TypeNodes.IsTypeNode isTypeNode; @Override public Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeyword[] keywords) throws VarargsBuiltinDirectInvocationNotSupported { @@ -321,6 +323,14 @@ private GetClassNode getGetClass() { return getClassNode; } + private TypeNodes.IsTypeNode ensureIsTypeNode() { + if (isTypeNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isTypeNode = insert(TypeNodes.IsTypeNode.create()); + } + return isTypeNode; + } + private LookupAndCallBinaryNode getGetAttr() { if (getAttrNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -345,7 +355,7 @@ private AbstractPythonClass supercheck(Object cls, Object object) { * not a subclass of type, but obj.__class__ is! This will allow using super() with a * proxy for obj. */ - if (object instanceof AbstractPythonClass) { + if (ensureIsTypeNode().execute(object)) { if (getIsSubtype().execute(object, cls)) { return (AbstractPythonClass) object; } @@ -356,7 +366,7 @@ private AbstractPythonClass supercheck(Object cls, Object object) { } else { try { Object classObject = getGetAttr().executeObject(object, SpecialAttributeNames.__CLASS__); - if (classObject instanceof AbstractPythonClass) { + if (ensureIsTypeNode().execute(classObject)) { if (getIsSubtype().execute(classObject, cls)) { return (AbstractPythonClass) classObject; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 264aa4193c..307b912bd4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -71,10 +71,13 @@ import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSuperClassNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetTypeFlagsNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.IsSameTypeNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.IsTypeNodeGen; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialMethodNames; +import com.oracle.graal.python.nodes.object.GetLazyClassNode; +import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.nodes.truffle.PythonTypes; import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage; import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage; @@ -665,4 +668,35 @@ private static AbstractPythonClass[] mergeMROs(MROMergeState[] toMerge, List Date: Thu, 24 Jan 2019 17:16:52 +0100 Subject: [PATCH 086/202] Return default value 0 for basicsize, itemsize, and dictoffset. --- .../objects/cext/PythonObjectNativeWrapperMR.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index c1b5512fb1..889de5bbb6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -503,12 +503,15 @@ Object doTpHash(ManagedPythonClass object, @SuppressWarnings("unused") String ke @Specialization(guards = "eq(TP_BASICSIZE, key)") Object doTpBasicsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, + @Cached("create()") CastToIndexNode castToIntNode, @Cached("create(__BASICSIZE__)") GetFixedAttributeNode getAttrNode) { - return getAttrNode.executeObject(object); + Object val = getAttrNode.executeObject(object); + return val != PNone.NO_VALUE ? castToIntNode.execute(val) : 0L; } @Specialization(guards = "eq(TP_ITEMSIZE, key)") - Object doTpItemsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, + long doTpItemsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, + @Cached("create()") CastToIndexNode castToIntNode, @Cached("create(__ITEMSIZE__)") GetFixedAttributeNode getAttrNode) { Object val = getAttrNode.executeObject(object); // If the attribute does not exist, this means that we take 'tp_itemsize' from the base @@ -516,11 +519,11 @@ Object doTpItemsize(ManagedPythonClass object, @SuppressWarnings("unused") Strin if (val == PNone.NO_VALUE) { return 0L; } - return val; + return val != PNone.NO_VALUE ? castToIntNode.execute(val) : 0L; } @Specialization(guards = "eq(TP_DICTOFFSET, key)") - Object doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") String key, + long doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") String key, @Cached("create()") CastToIndexNode castToIntNode, @Cached("create(__DICTOFFSET__)") GetFixedAttributeNode getAttrNode) { // TODO properly implement 'tp_dictoffset' for builtin classes @@ -528,7 +531,7 @@ Object doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") Str return 0L; } Object dictoffset = getAttrNode.executeObject(object); - return castToIntNode.execute(dictoffset); + return dictoffset != PNone.NO_VALUE ? castToIntNode.execute(dictoffset) : 0L; } @Specialization(guards = "eq(TP_WEAKLISTOFFSET, key)") From 51e9cd8f08489fca190bd3d9e49b22a7048232cb Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 12:18:43 +0100 Subject: [PATCH 087/202] Use 'Python(U|Bi|Ter)naryBuiltinNode' where possible. --- .../builtins/objects/dict/DictBuiltins.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java index 3f8d3045b3..acbcb3474e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java @@ -152,7 +152,7 @@ public Object setDefault(PDict dict, Object key, Object defaultValue, // pop(key[, default]) @Builtin(name = "pop", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3) @GenerateNodeFactory - public abstract static class PopNode extends PythonBuiltinNode { + public abstract static class PopNode extends PythonTernaryBuiltinNode { @Child private HashingStorageNodes.GetItemNode getItemNode; @Child private HashingStorageNodes.DelItemNode delItemNode; @@ -193,7 +193,7 @@ public Object popDefault(PDict dict, Object key, Object defaultValue) { // popitem() @Builtin(name = "popitem", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - public abstract static class PopItemNode extends PythonBuiltinNode { + public abstract static class PopItemNode extends PythonUnaryBuiltinNode { @Specialization @TruffleBoundary @@ -233,7 +233,7 @@ public PDictView items(PDict self) { // get(key[, default]) @Builtin(name = "get", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3) @GenerateNodeFactory - public abstract static class GetNode extends PythonBuiltinNode { + public abstract static class GetNode extends PythonTernaryBuiltinNode { @Child private HashingStorageNodes.GetItemNode getItemNode; @Specialization(guards = "!isNoValue(defaultValue)") @@ -274,7 +274,7 @@ Object getItem(PDict self, Object key, @Builtin(name = __MISSING__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - public abstract static class MissingNode extends PythonBuiltinNode { + public abstract static class MissingNode extends PythonBinaryBuiltinNode { @SuppressWarnings("unused") @Specialization Object run(Object self, PString key) { @@ -312,7 +312,7 @@ Object run(PDict self, Object key, Object value, @Builtin(name = __DELITEM__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - public abstract static class DelItemNode extends PythonBuiltinNode { + public abstract static class DelItemNode extends PythonBinaryBuiltinNode { @Specialization Object run(PDict self, Object key, @Cached("create()") HashingStorageNodes.DelItemNode delItemNode) { @@ -334,7 +334,7 @@ Object run(PDict self) { @Builtin(name = __EQ__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - public abstract static class EqNode extends PythonBuiltinNode { + public abstract static class EqNode extends PythonBinaryBuiltinNode { @Specialization Object doDictDict(PDict self, PDict other, @Cached("create()") HashingStorageNodes.EqualsNode equalsNode) { @@ -350,7 +350,7 @@ PNotImplemented doGeneric(Object self, Object other) { @Builtin(name = __CONTAINS__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - public abstract static class ContainsNode extends PythonBuiltinNode { + public abstract static class ContainsNode extends PythonBinaryBuiltinNode { @Child private HashingStorageNodes.ContainsKeyNode containsKeyNode; @SuppressWarnings("unused") @@ -391,7 +391,7 @@ public int len(PDict self, // copy() @Builtin(name = "copy", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - public abstract static class CopyNode extends PythonBuiltinNode { + public abstract static class CopyNode extends PythonUnaryBuiltinNode { @Specialization public PDict copy(PDict dict, @@ -403,7 +403,7 @@ public PDict copy(PDict dict, // clear() @Builtin(name = "clear", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - public abstract static class ClearNode extends PythonBuiltinNode { + public abstract static class ClearNode extends PythonUnaryBuiltinNode { @Specialization public PDict copy(PDict dict) { @@ -425,7 +425,7 @@ public PDictView values(PDict self) { @Builtin(name = __HASH__, fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - public abstract static class HashNode extends PythonBuiltinNode { + public abstract static class HashNode extends PythonUnaryBuiltinNode { @Specialization Object doGeneric(Object self) { throw raise(TypeError, "unhashable type: '%p'", self); From 2f45246ce68f3906302365002b9c74546f81eee1 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 12:19:39 +0100 Subject: [PATCH 088/202] Fix: delegate 'PythonAbstractNativeObject.hashCode' to pointer object. --- .../objects/cext/PythonAbstractNativeObject.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java index 6c2853f10b..f0596d70dc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java @@ -40,7 +40,10 @@ */ package com.oracle.graal.python.builtins.objects.cext; +import java.util.Objects; + import com.oracle.graal.python.builtins.objects.PythonAbstractObject; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.object.Shape; @@ -72,4 +75,10 @@ public TruffleObject getPtr() { return object; } + @Override + public int hashCode() { + CompilerAsserts.neverPartOfCompilation(); + // this is important for the default '__hash__' implementation + return Objects.hashCode(object); + } } From f83fe3413f1410b845840b04b3ff37eace4089b5 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 14:25:45 +0100 Subject: [PATCH 089/202] Fix: 'issubclass' must check arguments. --- .../builtins/objects/type/TypeBuiltins.java | 30 +++++++++++++++++-- .../builtins/objects/type/TypeNodes.java | 5 ++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 3b6359b80b..96ffadf888 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -528,10 +528,36 @@ public boolean isInstance(Object cls, Object instance) { @GenerateNodeFactory static abstract class SubclassCheckNode extends PythonBinaryBuiltinNode { @Child private IsSubtypeNode isSubtypeNode = IsSubtypeNode.create(); + @Child private TypeNodes.IsSameTypeNode isSameTypeNode = TypeNodes.IsSameTypeNode.create(); + + @Specialization(guards = {"!isNativeClass(cls)", "!isNativeClass(derived)"}) + boolean doManagedManaged(LazyPythonClass cls, LazyPythonClass derived) { + return isSameType(cls, derived) || isSubtypeNode.execute(derived, cls); + } @Specialization - boolean instanceCheck(LazyPythonClass cls, Object derived) { - return cls == derived || isSubtypeNode.execute(derived, cls); + boolean doObjectObject(Object cls, Object derived, + @Cached("create()") TypeNodes.IsTypeNode isClsTypeNode, + @Cached("create()") TypeNodes.IsTypeNode isDerivedTypeNode) { + if (isSameType(cls, derived)) { + return true; + } + + // no profiles required because IsTypeNode profiles already + if (isClsTypeNode.execute(cls) && isDerivedTypeNode.execute(derived)) { + return isSubtypeNode.execute(derived, cls); + } + if (!isDerivedTypeNode.execute(derived)) { + throw raise(PythonBuiltinClassType.TypeError, "issubclass() arg 1 must be a class"); + } + if (!isClsTypeNode.execute(cls)) { + throw raise(PythonBuiltinClassType.TypeError, "issubclass() arg 2 must be a class or tuple of classes"); + } + return false; + } + + protected boolean isSameType(Object a, Object b) { + return isSameTypeNode.execute(a, b); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 307b912bd4..49129c7eb9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -686,6 +686,11 @@ boolean doBuiltinType(@SuppressWarnings("unused") PythonBuiltinClassType obj) { boolean doManagedClass(PythonAbstractNativeObject obj, @Cached("create()") IsBuiltinClassProfile profile, @Cached("create()") GetLazyClassNode getClassNode) { + // TODO(fa): this check may not be enough since a type object may indirectly inherit + // from 'type' + // CPython has two different checks if some object is a type: + // 1. test if type flag 'Py_TPFLAGS_TYPE_SUBCLASS' is set + // 2. test if attribute '__bases__' is a tuple return profile.profileClass(getClassNode.execute(obj), PythonBuiltinClassType.PythonClass); } From 85180e9612aa272578eb22dded758834f9638e2c Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 14:29:08 +0100 Subject: [PATCH 090/202] Cleanup imports. --- .../oracle/graal/python/builtins/modules/BuiltinFunctions.java | 1 - .../graal/python/builtins/modules/PosixModuleBuiltins.java | 1 - .../graal/python/builtins/objects/cext/NativeWrappers.java | 1 - .../oracle/graal/python/builtins/objects/ints/IntBuiltins.java | 1 - 4 files changed, 4 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 372c719143..d122592670 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -115,7 +115,6 @@ import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeBuiltins; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.nodes.BuiltinNames; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index 1f2ae5401e..0069dd36ad 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -100,7 +100,6 @@ import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java index 608a5137a5..1de6d65413 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java @@ -47,7 +47,6 @@ import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.interop.ForeignAccess; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java index 80efbf463d..41b5074184 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java @@ -65,7 +65,6 @@ import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode; From 8bbd44a7d117396ab671a3dca9dee298b1f43f48 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 15:19:20 +0100 Subject: [PATCH 091/202] Fix: don't use 'PythonClass' as class param. --- .../objects/bytes/AbstractBytesBuiltins.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/AbstractBytesBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/AbstractBytesBuiltins.java index 97e72044ea..af6ca9ce18 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/AbstractBytesBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/AbstractBytesBuiltins.java @@ -41,6 +41,11 @@ package com.oracle.graal.python.builtins.objects.bytes; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import com.oracle.graal.python.builtins.Builtin; import com.oracle.graal.python.builtins.CoreFunctions; import com.oracle.graal.python.builtins.PythonBuiltinClassType; @@ -49,7 +54,7 @@ import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.list.ListBuiltins.ListAppendNode; import com.oracle.graal.python.builtins.objects.list.PList; -import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.argument.ReadArgumentNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; @@ -68,10 +73,6 @@ import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; @CoreFunctions(extendClasses = {PythonBuiltinClassType.PByteArray, PythonBuiltinClassType.PBytes}) public class AbstractBytesBuiltins extends PythonBuiltins { @@ -784,7 +785,7 @@ protected AbstractSplitNode createRecursiveNode() { public abstract static class MakeTransNode extends PythonBuiltinNode { @Specialization - public PBytes maketrans(@SuppressWarnings("unused") PythonClass cls, Object from, Object to, + public PBytes maketrans(@SuppressWarnings("unused") LazyPythonClass cls, Object from, Object to, @Cached("create()") BytesNodes.ToBytesNode toByteNode) { byte[] fromB = toByteNode.execute(from); byte[] toB = toByteNode.execute(to); From 30479055eeca7c437748894117fd2c7ccae9a628 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 15:28:57 +0100 Subject: [PATCH 092/202] Rename 'AbstractPythonClass' to 'PythonAbstractClass'. --- .../modules/BinasciiModuleBuiltins.java | 6 +- .../builtins/modules/BuiltinConstructors.java | 38 ++++---- .../builtins/modules/BuiltinFunctions.java | 6 +- .../builtins/modules/TruffleCextBuiltins.java | 10 +-- .../builtins/objects/cext/CExtNodes.java | 16 ++-- .../builtins/objects/cext/PThreadStateMR.java | 6 +- .../objects/cext/PyBufferProcsWrapper.java | 8 +- .../objects/cext/PyBufferProcsWrapperMR.java | 4 +- .../objects/cext/PythonNativeClass.java | 4 +- .../cext/PythonObjectNativeWrapperMR.java | 18 ++-- .../function/BuiltinFunctionBuiltins.java | 4 +- .../GetSetDescriptorTypeBuiltins.java | 8 +- .../objects/object/ObjectBuiltins.java | 14 +-- .../builtins/objects/object/PythonObject.java | 12 +-- .../objects/superobject/SuperBuiltins.java | 30 +++---- .../objects/superobject/SuperObject.java | 8 +- .../builtins/objects/type/MROMergeState.java | 8 +- .../objects/type/ManagedPythonClass.java | 32 +++---- ...honClass.java => PythonAbstractClass.java} | 2 +- .../objects/type/PythonBuiltinClass.java | 2 +- .../builtins/objects/type/PythonClass.java | 2 +- .../builtins/objects/type/TypeBuiltins.java | 26 +++--- .../builtins/objects/type/TypeNodes.java | 86 +++++++++---------- .../oracle/graal/python/nodes/PGuards.java | 4 +- .../graal/python/nodes/PNodeWithContext.java | 6 +- .../attributes/LookupAttributeInMRONode.java | 24 +++--- .../call/special/LookupAndCallBinaryNode.java | 6 +- .../special/LookupAndCallTernaryNode.java | 6 +- .../nodes/classes/IsFixedSubtypeMRONode.java | 4 +- .../nodes/classes/IsSubtypeMRONode.java | 10 +-- .../python/nodes/classes/IsSubtypeNode.java | 24 +++--- .../control/TopLevelExceptionHandler.java | 4 +- .../python/nodes/object/GetClassNode.java | 12 +-- .../nodes/object/IsBuiltinClassProfile.java | 4 +- .../python/nodes/statement/ExceptNode.java | 18 ++-- .../python/nodes/statement/RaiseNode.java | 12 +-- .../python/nodes/statement/WithNode.java | 4 +- .../python/nodes/subscript/SetItemNode.java | 6 +- .../interop/PythonMessageResolution.java | 14 +-- .../runtime/object/PythonObjectFactory.java | 4 +- .../sequence/storage/MroSequenceStorage.java | 26 +++--- 41 files changed, 269 insertions(+), 269 deletions(-) rename graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/{AbstractPythonClass.java => PythonAbstractClass.java} (57%) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java index 6304e64f89..364825de37 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java @@ -59,7 +59,7 @@ import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView; import com.oracle.graal.python.builtins.objects.module.PythonModule; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; @@ -96,9 +96,9 @@ protected List> getNodeFa public void initialize(PythonCore core) { super.initialize(core); String pre = "binascii."; - AbstractPythonClass[] errorBases = new AbstractPythonClass[]{core.lookupType(PythonBuiltinClassType.ValueError)}; + PythonAbstractClass[] errorBases = new PythonAbstractClass[]{core.lookupType(PythonBuiltinClassType.ValueError)}; builtinConstants.put(ERROR, core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, pre + ERROR, errorBases)); - AbstractPythonClass[] incompleteBases = new AbstractPythonClass[]{core.lookupType(PythonBuiltinClassType.Exception)}; + PythonAbstractClass[] incompleteBases = new PythonAbstractClass[]{core.lookupType(PythonBuiltinClassType.Exception)}; builtinConstants.put(INCOMPLETE, core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, pre + INCOMPLETE, incompleteBases)); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index 5e463cea4f..b2e35fca1e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -117,7 +117,7 @@ import com.oracle.graal.python.builtins.objects.set.SetNodes; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; @@ -1384,8 +1384,8 @@ Object doNativeObjectIndirect(PythonNativeClass self, Object[] varargs, PKeyword return callNativeGenericNewNode(self, varargs, kwargs); } - private static PythonNativeClass findFirstNativeBaseClass(AbstractPythonClass[] methodResolutionOrder) { - for (AbstractPythonClass cls : methodResolutionOrder) { + private static PythonNativeClass findFirstNativeBaseClass(PythonAbstractClass[] methodResolutionOrder) { + for (PythonAbstractClass cls : methodResolutionOrder) { if (PGuards.isNativeClass(cls)) { return PythonNativeClass.cast(cls); } @@ -1769,13 +1769,13 @@ public Object type(Object cls, Object obj, PNone bases, PNone dict, PKeyword[] k } @Specialization - public Object type(VirtualFrame frame, AbstractPythonClass cls, String name, PTuple bases, PDict namespace, PKeyword[] kwds, + public Object type(VirtualFrame frame, PythonAbstractClass cls, String name, PTuple bases, PDict namespace, PKeyword[] kwds, @Cached("create()") GetClassNode getMetaclassNode, @Cached("create(__NEW__)") LookupInheritedAttributeNode getNewFuncNode, @Cached("create()") CallDispatchNode callNewFuncNode, @Cached("create()") CreateArgumentsNode createArgs) { // Determine the proper metatype to deal with this - AbstractPythonClass metaclass = calculate_metaclass(cls, bases, getMetaclassNode); + PythonAbstractClass metaclass = calculate_metaclass(cls, bases, getMetaclassNode); if (metaclass != cls) { Object newFunc = getNewFuncNode.execute(metaclass); if (newFunc instanceof PBuiltinFunction && (((PBuiltinFunction) newFunc).getFunctionRootNode() == getRootNode())) { @@ -1823,22 +1823,22 @@ private String getModuleNameFromGlobals(PythonObject globals) { } @TruffleBoundary - private Object typeMetaclass(String name, PTuple bases, PDict namespace, AbstractPythonClass metaclass) { + private Object typeMetaclass(String name, PTuple bases, PDict namespace, PythonAbstractClass metaclass) { Object[] array = bases.getArray(); - AbstractPythonClass[] basesArray; + PythonAbstractClass[] basesArray; if (array.length == 0) { // Adjust for empty tuple bases - basesArray = new AbstractPythonClass[]{getCore().lookupType(PythonBuiltinClassType.PythonObject)}; + basesArray = new PythonAbstractClass[]{getCore().lookupType(PythonBuiltinClassType.PythonObject)}; } else { - basesArray = new AbstractPythonClass[array.length]; + basesArray = new PythonAbstractClass[array.length]; for (int i = 0; i < array.length; i++) { // TODO: deal with non-class bases - if (!(array[i] instanceof AbstractPythonClass)) { + if (!(array[i] instanceof PythonAbstractClass)) { throw raise(NotImplementedError, "creating a class with non-class bases"); } else { - basesArray[i] = (AbstractPythonClass) array[i]; + basesArray[i] = (PythonAbstractClass) array[i]; } } } @@ -2075,7 +2075,7 @@ private boolean addDictIfNative(ManagedPythonClass pythonClass) { return addedNewDict; } - private AbstractPythonClass[] getMro(AbstractPythonClass pythonClass) { + private PythonAbstractClass[] getMro(PythonAbstractClass pythonClass) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -2083,10 +2083,10 @@ private AbstractPythonClass[] getMro(AbstractPythonClass pythonClass) { return getMroNode.execute(pythonClass); } - private AbstractPythonClass calculate_metaclass(AbstractPythonClass cls, PTuple bases, GetClassNode getMetaclassNode) { - AbstractPythonClass winner = cls; + private PythonAbstractClass calculate_metaclass(PythonAbstractClass cls, PTuple bases, GetClassNode getMetaclassNode) { + PythonAbstractClass winner = cls; for (Object base : bases.getArray()) { - AbstractPythonClass typ = getMetaclassNode.execute(base); + PythonAbstractClass typ = getMetaclassNode.execute(base); if (isSubType(winner, typ)) { continue; } else if (isSubType(typ, winner)) { @@ -2099,7 +2099,7 @@ private AbstractPythonClass calculate_metaclass(AbstractPythonClass cls, PTuple return winner; } - private boolean isSubType(AbstractPythonClass subclass, AbstractPythonClass superclass) { + private boolean isSubType(PythonAbstractClass subclass, PythonAbstractClass superclass) { if (isSubtypeNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); isSubtypeNode = insert(IsSubtypeNode.create()); @@ -2519,14 +2519,14 @@ private void denyInstantiationAfterInitialization() { @Specialization(guards = {"!isNoValue(get)", "!isNoValue(set)"}) @TruffleBoundary - Object call(@SuppressWarnings("unused") LazyPythonClass getSetClass, Object get, Object set, String name, AbstractPythonClass owner) { + Object call(@SuppressWarnings("unused") LazyPythonClass getSetClass, Object get, Object set, String name, PythonAbstractClass owner) { denyInstantiationAfterInitialization(); return factory().createGetSetDescriptor(get, set, name, owner); } @Specialization(guards = {"!isNoValue(get)", "isNoValue(set)"}) @TruffleBoundary - Object call(@SuppressWarnings("unused") LazyPythonClass getSetClass, Object get, @SuppressWarnings("unused") PNone set, String name, AbstractPythonClass owner) { + Object call(@SuppressWarnings("unused") LazyPythonClass getSetClass, Object get, @SuppressWarnings("unused") PNone set, String name, PythonAbstractClass owner) { denyInstantiationAfterInitialization(); return factory().createGetSetDescriptor(get, null, name, owner); } @@ -2534,7 +2534,7 @@ Object call(@SuppressWarnings("unused") LazyPythonClass getSetClass, Object get, @Specialization(guards = {"isNoValue(get)", "isNoValue(set)"}) @TruffleBoundary @SuppressWarnings("unused") - Object call(LazyPythonClass getSetClass, PNone get, PNone set, String name, AbstractPythonClass owner) { + Object call(LazyPythonClass getSetClass, PNone get, PNone set, String name, PythonAbstractClass owner) { denyInstantiationAfterInitialization(); return factory().createGetSetDescriptor(null, null, name, owner); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index d122592670..8d2e053af0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -114,7 +114,7 @@ import com.oracle.graal.python.builtins.objects.set.PFrozenSet; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.TypeBuiltins; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.nodes.BuiltinNames; @@ -1037,10 +1037,10 @@ private boolean isInstanceCheckInternal(Object instance, Object cls) { public abstract boolean executeWith(Object instance, Object cls); @Specialization - public boolean isInstance(Object instance, AbstractPythonClass cls, + public boolean isInstance(Object instance, PythonAbstractClass cls, @Cached("create()") TypeNodes.IsSameTypeNode isSameTypeNode, @Cached("create()") IsSubtypeNode isSubtypeNode) { - AbstractPythonClass instanceClass = getClassNode.execute(instance); + PythonAbstractClass instanceClass = getClassNode.execute(instance); return isSameTypeNode.execute(instanceClass, cls) || isSubtypeNode.execute(instanceClass, cls) || isInstanceCheckInternal(instance, cls); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index ccc8835677..0ca7fe471c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -118,7 +118,7 @@ import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; @@ -205,7 +205,7 @@ protected List> getNodeFa public void initialize(PythonCore core) { super.initialize(core); PythonClass errorHandlerClass = core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, "CErrorHandler", - new AbstractPythonClass[]{core.lookupType(PythonBuiltinClassType.PythonObject)}); + new PythonAbstractClass[]{core.lookupType(PythonBuiltinClassType.PythonObject)}); builtinConstants.put("CErrorHandler", errorHandlerClass); builtinConstants.put(ERROR_HANDLER, core.factory().createPythonObject(errorHandlerClass)); builtinConstants.put(NATIVE_NULL, new PythonNativeNull()); @@ -1342,13 +1342,13 @@ abstract static class PyTruffle_GetTpFlags extends NativeBuiltin { @Specialization long doPythonObject(PythonNativeWrapper nativeWrapper) { - AbstractPythonClass pclass = getClassNode().execute(nativeWrapper.getDelegate()); + PythonAbstractClass pclass = getClassNode().execute(nativeWrapper.getDelegate()); return getTypeFlagsNode().execute(pclass); } @Specialization long doPythonObject(PythonAbstractObject object) { - AbstractPythonClass pclass = getClassNode().execute(object); + PythonAbstractClass pclass = getClassNode().execute(object); return getTypeFlagsNode().execute(pclass); } @@ -2318,7 +2318,7 @@ public abstract static class PyTruffle_Compute_Mro extends PythonUnaryBuiltinNod @Specialization Object doIt(PythonNativeObject self) { - AbstractPythonClass[] doSlowPath = TypeNodes.ComputeMroNode.doSlowPath(PythonNativeClass.cast(self)); + PythonAbstractClass[] doSlowPath = TypeNodes.ComputeMroNode.doSlowPath(PythonNativeClass.cast(self)); return factory().createTuple(new MroSequenceStorage(doSlowPath)); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index edbe8e7ae3..088463f4d8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -73,7 +73,7 @@ import com.oracle.graal.python.builtins.objects.function.PKeyword; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.str.PString; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; @@ -846,12 +846,12 @@ public abstract static class GetNativeClassNode extends CExtBaseNode { @CompilationFinal private TruffleObject func; - public abstract AbstractPythonClass execute(PythonAbstractNativeObject object); + public abstract PythonAbstractClass execute(PythonAbstractNativeObject object); @Specialization(guards = "object == cachedObject", limit = "1") - AbstractPythonClass getNativeClassCached(@SuppressWarnings("unused") PythonAbstractNativeObject object, + PythonAbstractClass getNativeClassCached(@SuppressWarnings("unused") PythonAbstractNativeObject object, @SuppressWarnings("unused") @Cached("object") PythonAbstractNativeObject cachedObject, - @Cached("getNativeClass(cachedObject)") AbstractPythonClass cachedClass) { + @Cached("getNativeClass(cachedObject)") PythonAbstractClass cachedClass) { // TODO: (tfel) is this really something we can do? It's so rare for this class to // change that it shouldn't be worth the effort, but in native code, anything can // happen. OTOH, CPython also has caches that can become invalid when someone just goes @@ -860,14 +860,14 @@ AbstractPythonClass getNativeClassCached(@SuppressWarnings("unused") PythonAbstr } @Specialization - AbstractPythonClass getNativeClass(PythonAbstractNativeObject object) { + PythonAbstractClass getNativeClass(PythonAbstractNativeObject object) { // do not convert wrap 'object.object' since that is really the native pointer object - return (AbstractPythonClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.object)); + return (PythonAbstractClass) getToJavaNode().execute(getCallGetObTypeNode().call(object.object)); } @TruffleBoundary - public static AbstractPythonClass doSlowPath(PythonAbstractNativeObject object) { - return (AbstractPythonClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.getPtr()), true); + public static PythonAbstractClass doSlowPath(PythonAbstractNativeObject object) { + return (PythonAbstractClass) AsPythonObjectNode.doSlowPath(PCallCapiFunction.doSlowPath(NativeCAPISymbols.FUN_GET_OB_TYPE, object.getPtr()), true); } private AsPythonObjectNode getToJavaNode() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java index 3f75ecb740..bb997a8f8e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java @@ -55,7 +55,7 @@ import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.exception.PBaseException; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; @@ -135,7 +135,7 @@ abstract static class ThreadStateReadNode extends PNodeWithContext { public abstract Object execute(Object key); @Specialization(guards = "eq(key, CUR_EXC_TYPE)") - AbstractPythonClass doCurExcType(@SuppressWarnings("unused") String key) { + PythonAbstractClass doCurExcType(@SuppressWarnings("unused") String key) { PythonContext context = getContext(); PException currentException = context.getCurrentException(); if (currentException != null) { @@ -168,7 +168,7 @@ PTraceback doCurExcTraceback(@SuppressWarnings("unused") String key) { } @Specialization(guards = "eq(key, EXC_TYPE)") - AbstractPythonClass doExcType(@SuppressWarnings("unused") String key) { + PythonAbstractClass doExcType(@SuppressWarnings("unused") String key) { PythonContext context = getContext(); PException currentException = context.getCaughtException(); if (currentException != null) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java index 510a2c528b..783ae6cae7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java @@ -41,13 +41,13 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonNativeWrapper; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.TruffleObject; public class PyBufferProcsWrapper extends PythonNativeWrapper { - public PyBufferProcsWrapper(AbstractPythonClass delegate) { + public PyBufferProcsWrapper(PythonAbstractClass delegate) { super(delegate); } @@ -60,7 +60,7 @@ public ForeignAccess getForeignAccess() { return PyBufferProcsWrapperMRForeign.ACCESS; } - public AbstractPythonClass getPythonClass() { - return (AbstractPythonClass) getDelegate(); + public PythonAbstractClass getPythonClass() { + return (PythonAbstractClass) getDelegate(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java index 0e98422442..4664ba2625 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java @@ -44,7 +44,7 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToSulongNode; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper; import com.oracle.graal.python.builtins.objects.cext.PyBufferProcsWrapperMRFactory.GetBufferProcsNodeGen; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.truffle.api.CompilerDirectives; @@ -73,7 +73,7 @@ public Object access(PyBufferProcsWrapper object, String key) { abstract static class GetBufferProcsNode extends PNodeWithContext { @Child private ToSulongNode toSulongNode; - public abstract Object execute(AbstractPythonClass clazz, String key); + public abstract Object execute(PythonAbstractClass clazz, String key); @Specialization Object doManagedClass(ManagedPythonClass clazz, String key) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java index ba97fc787a..bcdd3c85b4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonNativeClass.java @@ -40,7 +40,7 @@ */ package com.oracle.graal.python.builtins.objects.cext; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.truffle.api.interop.TruffleObject; /** @@ -49,7 +49,7 @@ * types are assumed to be mutated afterwards, so accessing the struct in native mode would work, * but our copy should just never become stale. */ -public interface PythonNativeClass extends AbstractPythonClass { +public interface PythonNativeClass extends PythonAbstractClass { TruffleObject getPtr(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index 889de5bbb6..273c072916 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -93,7 +93,7 @@ import com.oracle.graal.python.builtins.objects.set.PSet; import com.oracle.graal.python.builtins.objects.slice.PSlice; import com.oracle.graal.python.builtins.objects.str.PString; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; @@ -253,11 +253,11 @@ Object doManagedGeneric(ManagedPythonClass clazz, protected Object getSulongTypeForBuiltinClass(PythonBuiltinClassType clazz) { CompilerAsserts.neverPartOfCompilation(); - AbstractPythonClass pythonClass = getPythonClass(clazz, ConditionProfile.createBinaryProfile()); + PythonAbstractClass pythonClass = getPythonClass(clazz, ConditionProfile.createBinaryProfile()); return getSulongTypeForClass(pythonClass); } - protected static Object getSulongTypeForClass(AbstractPythonClass clazz) { + protected static Object getSulongTypeForClass(PythonAbstractClass clazz) { CompilerAsserts.neverPartOfCompilation(); Object sulongType = TypeNodes.GetSulongTypeNode.getSlowPath(clazz); if (sulongType == null) { @@ -268,7 +268,7 @@ protected static Object getSulongTypeForClass(AbstractPythonClass clazz) { } /** resolves the Sulong type */ - private static Object resolveSulongTypeForClass(AbstractPythonClass klass) { + private static Object resolveSulongTypeForClass(PythonAbstractClass klass) { Object sulongType = findBuiltinClass(klass); if (sulongType == null) { throw new IllegalStateException("sulong type for " + GetNameNode.doSlowPath(klass) + " was not registered"); @@ -277,10 +277,10 @@ private static Object resolveSulongTypeForClass(AbstractPythonClass klass) { } /** iterates over MRO and looks for the first builtin type with an existing Sulong type */ - private static Object findBuiltinClass(AbstractPythonClass klass) { - AbstractPythonClass[] mro = GetMroNode.doSlowPath(klass); + private static Object findBuiltinClass(PythonAbstractClass klass) { + PythonAbstractClass[] mro = GetMroNode.doSlowPath(klass); Object sulongType = null; - for (AbstractPythonClass superClass : mro) { + for (PythonAbstractClass superClass : mro) { sulongType = TypeNodes.GetSulongTypeNode.getSlowPath(superClass); if (sulongType != null) { TypeNodes.GetSulongTypeNode.setSlowPath(klass, sulongType); @@ -840,7 +840,7 @@ private int sizeofWchar() { return (int) sizeofWcharNode.execute(); } - private AbstractPythonClass getClass(Object obj) { + private PythonAbstractClass getClass(Object obj) { if (getClassNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getClassNode = insert(GetClassNode.create()); @@ -901,7 +901,7 @@ long doTpFlags(ManagedPythonClass object, @SuppressWarnings("unused") String key } @Specialization(guards = "eq(TP_BASICSIZE, key)") - long doTpBasicsize(AbstractPythonClass object, @SuppressWarnings("unused") String key, long basicsize, + long doTpBasicsize(PythonAbstractClass object, @SuppressWarnings("unused") String key, long basicsize, @Cached("create()") WriteAttributeToObjectNode writeAttrNode, @Cached("create()") IsBuiltinClassProfile profile) { if (profile.profileClass(object, PythonBuiltinClassType.PythonClass)) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java index 50268fe18a..61556fd023 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java @@ -34,7 +34,7 @@ import com.oracle.graal.python.builtins.CoreFunctions; import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.PythonBuiltins; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; @@ -85,7 +85,7 @@ Object objclassMissing(@SuppressWarnings("unused") PBuiltinFunction self) { @Specialization(guards = "self.getEnclosingType() != null") @TruffleBoundary - AbstractPythonClass objclass(PBuiltinFunction self, + PythonAbstractClass objclass(PBuiltinFunction self, @Cached("createBinaryProfile()") ConditionProfile profile) { return getPythonClass(self.getEnclosingType(), profile); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java index ca4b28cea3..4c578fbd1a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java @@ -53,7 +53,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.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; @@ -114,13 +114,13 @@ protected boolean descr_check(LazyPythonClass descrType, String name, Object obj } if (isBuiltinProfile.profile(descrType instanceof PythonBuiltinClassType)) { PythonBuiltinClassType builtinClassType = (PythonBuiltinClassType) descrType; - for (AbstractPythonClass o : getMro(type)) { + for (PythonAbstractClass o : getMro(type)) { if (isBuiltinClassProfile.profileClass(o, builtinClassType)) { return false; } } } else { - for (AbstractPythonClass o : getMro(type)) { + for (PythonAbstractClass o : getMro(type)) { if (isSameType(o, descrType)) { return false; } @@ -130,7 +130,7 @@ protected boolean descr_check(LazyPythonClass descrType, String name, Object obj throw raise(TypeError, "descriptor '%s' for '%s' objects doesn't apply to '%s' object", name, getTypeName(descrType), getTypeName(type)); } - private AbstractPythonClass[] getMro(LazyPythonClass clazz) { + private PythonAbstractClass[] getMro(LazyPythonClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java index 7f227823ff..6f2ce2418b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java @@ -65,7 +65,7 @@ import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction; import com.oracle.graal.python.builtins.objects.function.PKeyword; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; @@ -121,7 +121,7 @@ abstract static class ClassNode extends PythonBinaryBuiltinNode { private static final String ERROR_MESSAGE = "__class__ assignment only supported for heap types or ModuleType subclasses"; @Specialization(guards = "isNoValue(value)") - AbstractPythonClass getClass(Object self, @SuppressWarnings("unused") PNone value, + PythonAbstractClass getClass(Object self, @SuppressWarnings("unused") PNone value, @Cached("create()") GetClassNode getClass) { return getClass.execute(self); } @@ -137,7 +137,7 @@ LazyPythonClass setClass(@SuppressWarnings("unused") Object self, @SuppressWarni } @Specialization - PNone setClass(PythonObject self, AbstractPythonClass value, + PNone setClass(PythonObject self, PythonAbstractClass value, @Cached("create()") BranchProfile errorValueBranch, @Cached("create()") BranchProfile errorSelfBranch, @Cached("create()") BranchProfile errorSlotsBranch, @@ -188,7 +188,7 @@ private LookupAttributeInMRONode getLookupSlotsInOther() { } @Specialization(guards = "!isPythonObject(self)") - LazyPythonClass getClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") AbstractPythonClass value) { + LazyPythonClass getClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") PythonAbstractClass value) { throw raise(TypeError, ERROR_MESSAGE); } @@ -302,7 +302,7 @@ String repr(Object self, if (self == PNone.NONE) { return "None"; } - AbstractPythonClass type = getClass.execute(self); + PythonAbstractClass type = getClass.execute(self); Object moduleName = readModuleNode.executeObject(type); Object qualName = readQualNameNode.executeObject(type); if (moduleName != PNone.NO_VALUE && !moduleName.equals(getCore().getBuiltins().getModuleName())) { @@ -492,7 +492,7 @@ protected PNone doIt(Object object, Object key, Object value, LazyPythonClass type = getObjectClassNode.execute(object); Object descr = getExisting.execute(type, key); if (descr != PNone.NO_VALUE) { - AbstractPythonClass dataDescClass = getDataClassNode.execute(descr); + PythonAbstractClass dataDescClass = getDataClassNode.execute(descr); Object set = lookupSetNode.execute(dataDescClass); if (PGuards.isCallable(set)) { callSetNode.execute(set, descr, object, value); @@ -525,7 +525,7 @@ protected PNone doIt(Object object, Object key, LazyPythonClass type = getObjectClassNode.execute(object); Object descr = getExisting.execute(type, key); if (descr != PNone.NO_VALUE) { - AbstractPythonClass dataDescClass = getDataClassNode.execute(descr); + PythonAbstractClass dataDescClass = getDataClassNode.execute(descr); Object set = lookupDeleteNode.execute(dataDescClass); if (PGuards.isCallable(set)) { callSetNode.executeObject(set, descr, object); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java index 1acd01357e..975c039cce 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java @@ -33,7 +33,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PythonAbstractObject; import com.oracle.graal.python.builtins.objects.common.PHashingCollection; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; @@ -74,17 +74,17 @@ public PythonObject(LazyPythonClass pythonClass, Shape instanceShape) { storage = instanceShape.newInstance(); } - public final AbstractPythonClass getPythonClass() { + public final PythonAbstractClass getPythonClass() { CompilerAsserts.neverPartOfCompilation(); assert pythonClass != null; - if (pythonClass instanceof AbstractPythonClass) { - return (AbstractPythonClass) pythonClass; + if (pythonClass instanceof PythonAbstractClass) { + return (PythonAbstractClass) pythonClass; } else { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) pythonClass); } } - public final void setLazyPythonClass(AbstractPythonClass cls) { + public final void setLazyPythonClass(PythonAbstractClass cls) { pythonClass = cls; classStable.invalidate(); } @@ -155,7 +155,7 @@ public List getAttributeNames() { return keyList; } - public final AbstractPythonClass asPythonClass() { + public final PythonAbstractClass asPythonClass() { if (this instanceof ManagedPythonClass) { return (ManagedPythonClass) this; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java index 0c01ed8053..539be43309 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java @@ -59,7 +59,7 @@ import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetObjectTypeNodeGen; import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetTypeNodeGen; import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.SuperInitNodeFactory; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; @@ -120,17 +120,17 @@ Object uncached(SuperObject self) { } abstract static class GetObjectTypeNode extends Node { - abstract AbstractPythonClass execute(SuperObject self); + abstract PythonAbstractClass execute(SuperObject self); @Specialization(guards = "self == cachedSelf", assumptions = "cachedSelf.getNeverReinitializedAssumption()", limit = "1") - AbstractPythonClass cached(@SuppressWarnings("unused") SuperObject self, + PythonAbstractClass cached(@SuppressWarnings("unused") SuperObject self, @SuppressWarnings("unused") @Cached("self") SuperObject cachedSelf, - @Cached("self.getObjectType()") AbstractPythonClass type) { + @Cached("self.getObjectType()") PythonAbstractClass type) { return type; } @Specialization(replaces = "cached") - AbstractPythonClass uncached(SuperObject self) { + PythonAbstractClass uncached(SuperObject self) { return self.getObjectType(); } } @@ -198,7 +198,7 @@ public final Object execute(VirtualFrame frame, Object self, Object[] arguments, @Specialization(guards = {"!isNoValue(cls)", "!isNoValue(obj)"}) PNone init(SuperObject self, Object cls, Object obj) { if (obj != PNone.NONE) { - AbstractPythonClass type = supercheck(cls, obj); + PythonAbstractClass type = supercheck(cls, obj); self.init(cls, type, obj); } else { self.init(cls, null, null); @@ -339,7 +339,7 @@ private LookupAndCallBinaryNode getGetAttr() { return getAttrNode; } - private AbstractPythonClass supercheck(Object cls, Object object) { + private PythonAbstractClass supercheck(Object cls, Object object) { /* * Check that a super() call makes sense. Return a type object. * @@ -357,7 +357,7 @@ private AbstractPythonClass supercheck(Object cls, Object object) { */ if (ensureIsTypeNode().execute(object)) { if (getIsSubtype().execute(object, cls)) { - return (AbstractPythonClass) object; + return (PythonAbstractClass) object; } } @@ -368,7 +368,7 @@ private AbstractPythonClass supercheck(Object cls, Object object) { Object classObject = getGetAttr().executeObject(object, SpecialAttributeNames.__CLASS__); if (ensureIsTypeNode().execute(classObject)) { if (getIsSubtype().execute(classObject, cls)) { - return (AbstractPythonClass) classObject; + return (PythonAbstractClass) classObject; } } } catch (PException e) { @@ -429,7 +429,7 @@ private Object genericGetAttr(Object object, Object attr) { @Specialization public Object get(SuperObject self, Object attr) { - AbstractPythonClass startType = getObjectType.execute(self); + PythonAbstractClass startType = getObjectType.execute(self); if (startType == null) { return genericGetAttr(self, attr); } @@ -456,7 +456,7 @@ public Object get(SuperObject self, Object attr) { getType = insert(GetTypeNodeGen.create()); } - AbstractPythonClass[] mro = getMro(startType); + PythonAbstractClass[] mro = getMro(startType); /* No need to check the last one: it's gonna be skipped anyway. */ int i = 0; int n = mro.length; @@ -471,7 +471,7 @@ public Object get(SuperObject self, Object attr) { } for (; i < n; i++) { - AbstractPythonClass tmp = mro[i]; + PythonAbstractClass tmp = mro[i]; Object res = readFromDict.execute(tmp, attr); if (res != PNone.NO_VALUE) { Object get = readGet.execute(res); @@ -494,7 +494,7 @@ public Object get(SuperObject self, Object attr) { return genericGetAttr(self, attr); } - private boolean isSameType(Object execute, AbstractPythonClass abstractPythonClass) { + private boolean isSameType(Object execute, PythonAbstractClass abstractPythonClass) { if (isSameTypeNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); isSameTypeNode = insert(IsSameTypeNode.create()); @@ -502,7 +502,7 @@ private boolean isSameType(Object execute, AbstractPythonClass abstractPythonCla return isSameTypeNode.execute(execute, abstractPythonClass); } - private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { + private PythonAbstractClass[] getMro(PythonAbstractClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -548,7 +548,7 @@ public abstract static class SelfClassNode extends PythonUnaryBuiltinNode { @Specialization Object getClass(SuperObject self) { - AbstractPythonClass objectType = getObjectType.execute(self); + PythonAbstractClass objectType = getObjectType.execute(self); if (objectType == null) { return PNone.NONE; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java index e18389e6af..4941606e10 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java @@ -41,7 +41,7 @@ package com.oracle.graal.python.builtins.objects.superobject; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.Truffle; @@ -49,14 +49,14 @@ public class SuperObject extends PythonBuiltinObject { private final Assumption neverReinitialized = Truffle.getRuntime().createAssumption("super object was never reinitialized"); private Object type; - private AbstractPythonClass objecttype; + private PythonAbstractClass objecttype; private Object object; public SuperObject(LazyPythonClass cls) { super(cls); } - public void init(Object newType, AbstractPythonClass newObjecttype, Object newObject) { + public void init(Object newType, PythonAbstractClass newObjecttype, Object newObject) { if (this.type != null) { neverReinitialized.invalidate(); } @@ -65,7 +65,7 @@ public void init(Object newType, AbstractPythonClass newObjecttype, Object newOb this.object = newObject; } - public AbstractPythonClass getObjectType() { + public PythonAbstractClass getObjectType() { return objecttype; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java index b5ed327044..c42eab18ca 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java @@ -28,7 +28,7 @@ class MROMergeState { /** The mro of the base type we're representing. */ - public AbstractPythonClass[] mro; + public PythonAbstractClass[] mro; /** * The index of the next item to be merged from mro, or mro.length if this base has been @@ -40,14 +40,14 @@ public boolean isMerged() { return mro.length == next; } - public AbstractPythonClass getCandidate() { + public PythonAbstractClass getCandidate() { return mro[next]; } /** * Marks candidate as merged for this base if it's the next item to be merged. */ - public void noteMerged(AbstractPythonClass candidate) { + public void noteMerged(PythonAbstractClass candidate) { if (!isMerged() && getCandidate() == candidate) { next++; } @@ -56,7 +56,7 @@ public void noteMerged(AbstractPythonClass candidate) { /** * Returns true if candidate is in the items past this state's next item to be merged. */ - public boolean pastnextContains(AbstractPythonClass candidate) { + public boolean pastnextContains(PythonAbstractClass candidate) { for (int i = next + 1; i < mro.length; i++) { if (mro[i] == candidate) { return true; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java index 9f364e5495..20f66d0c88 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java @@ -27,12 +27,12 @@ import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.utilities.CyclicAssumption; -public abstract class ManagedPythonClass extends PythonObject implements AbstractPythonClass { +public abstract class ManagedPythonClass extends PythonObject implements PythonAbstractClass { private final String className; - @CompilationFinal(dimensions = 1) private AbstractPythonClass[] baseClasses; - @CompilationFinal(dimensions = 1) private AbstractPythonClass[] methodResolutionOrder; + @CompilationFinal(dimensions = 1) private PythonAbstractClass[] baseClasses; + @CompilationFinal(dimensions = 1) private PythonAbstractClass[] methodResolutionOrder; /** * This assumption will be invalidated whenever the mro changes. @@ -44,7 +44,7 @@ public abstract class ManagedPythonClass extends PythonObject implements Abstrac */ private final Map> attributesInMROFinalAssumptions = new HashMap<>(); - private final Set subClasses = Collections.newSetFromMap(new WeakHashMap()); + private final Set subClasses = Collections.newSetFromMap(new WeakHashMap()); private final Shape instanceShape; private final FlagsContainer flags; @@ -53,12 +53,12 @@ public abstract class ManagedPythonClass extends PythonObject implements Abstrac @CompilationFinal private Object sulongType; @TruffleBoundary - public ManagedPythonClass(LazyPythonClass typeClass, String name, Shape instanceShape, AbstractPythonClass... baseClasses) { + public ManagedPythonClass(LazyPythonClass typeClass, String name, Shape instanceShape, PythonAbstractClass... baseClasses) { super(typeClass, PythonLanguage.freshShape() /* do not inherit layout from the TypeClass */); this.className = name; if (baseClasses.length == 1 && baseClasses[0] == null) { - this.baseClasses = new AbstractPythonClass[]{}; + this.baseClasses = new PythonAbstractClass[]{}; } else { unsafeSetSuperClass(baseClasses); } @@ -135,7 +135,7 @@ public void lookupChanged() { } } lookupStableAssumption.invalidate(); - for (AbstractPythonClass subclass : getSubClasses()) { + for (PythonAbstractClass subclass : getSubClasses()) { if (subclass != null) { subclass.lookupChanged(); } @@ -146,11 +146,11 @@ public Shape getInstanceShape() { return instanceShape; } - AbstractPythonClass getSuperClass() { + PythonAbstractClass getSuperClass() { return getBaseClasses().length > 0 ? getBaseClasses()[0] : null; } - AbstractPythonClass[] getMethodResolutionOrder() { + PythonAbstractClass[] getMethodResolutionOrder() { return methodResolutionOrder; } @@ -159,7 +159,7 @@ String getName() { } private void computeNeedsNativeAllocation() { - for (AbstractPythonClass cls : getMethodResolutionOrder()) { + for (PythonAbstractClass cls : getMethodResolutionOrder()) { if (PGuards.isNativeClass(cls)) { needsNativeAllocation = true; return; @@ -181,7 +181,7 @@ public void setAttribute(Object key, Object value) { * This method supports initialization and solves boot-order problems and should not normally be * used. */ - private void unsafeSetSuperClass(AbstractPythonClass... newBaseClasses) { + private void unsafeSetSuperClass(PythonAbstractClass... newBaseClasses) { CompilerAsserts.neverPartOfCompilation(); // TODO: if this is used outside bootstrapping, it needs to call // computeMethodResolutionOrder for subclasses. @@ -189,7 +189,7 @@ private void unsafeSetSuperClass(AbstractPythonClass... newBaseClasses) { assert getBaseClasses() == null || getBaseClasses().length == 0; this.baseClasses = newBaseClasses; - for (AbstractPythonClass base : getBaseClasses()) { + for (PythonAbstractClass base : getBaseClasses()) { if (base != null) { GetSubclassesNode.doSlowPath(base).add(this); } @@ -197,7 +197,7 @@ private void unsafeSetSuperClass(AbstractPythonClass... newBaseClasses) { this.methodResolutionOrder = ComputeMroNode.doSlowPath(this); } - final Set getSubClasses() { + final Set getSubClasses() { return subClasses; } @@ -207,7 +207,7 @@ public String toString() { return String.format("", className); } - public AbstractPythonClass[] getBaseClasses() { + public PythonAbstractClass[] getBaseClasses() { return baseClasses; } @@ -224,10 +224,10 @@ FlagsContainer getFlagsContainer() { * created before the C API was initialized, i.e., flags were not set. */ static final class FlagsContainer { - AbstractPythonClass initialDominantBase; + PythonAbstractClass initialDominantBase; long flags; - public FlagsContainer(AbstractPythonClass superClass) { + public FlagsContainer(PythonAbstractClass superClass) { this.initialDominantBase = superClass; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/AbstractPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonAbstractClass.java similarity index 57% rename from graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/AbstractPythonClass.java rename to graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonAbstractClass.java index 272cab8158..21293eb6f1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/AbstractPythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonAbstractClass.java @@ -1,6 +1,6 @@ package com.oracle.graal.python.builtins.objects.type; -public interface AbstractPythonClass extends LazyPythonClass { +public interface PythonAbstractClass extends LazyPythonClass { void lookupChanged(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java index 198d81df7e..af4964e0ec 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java @@ -38,7 +38,7 @@ public final class PythonBuiltinClass extends ManagedPythonClass { private final PythonBuiltinClassType type; - public PythonBuiltinClass(PythonBuiltinClassType builtinClass, AbstractPythonClass base) { + public PythonBuiltinClass(PythonBuiltinClassType builtinClass, PythonAbstractClass base) { super(PythonBuiltinClassType.PythonClass, builtinClass.getName(), builtinClass.getInstanceShape(), base); this.type = builtinClass; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java index 5c83752a12..54e4ff88d7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java @@ -32,7 +32,7 @@ */ public final class PythonClass extends ManagedPythonClass { - public PythonClass(LazyPythonClass typeClass, String name, Shape instanceShape, AbstractPythonClass[] baseClasses) { + public PythonClass(LazyPythonClass typeClass, String name, Shape instanceShape, PythonAbstractClass[] baseClasses) { super(typeClass, name, instanceShape, baseClasses); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 96ffadf888..bd72af6122 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -133,7 +133,7 @@ protected List> getNodeFa public abstract static class ReprNode extends PythonUnaryBuiltinNode { @Specialization - String repr(AbstractPythonClass self, + String repr(PythonAbstractClass self, @Cached("create(__MODULE__)") GetFixedAttributeNode readModuleNode, @Cached("create(__QUALNAME__)") GetFixedAttributeNode readQualNameNode) { Object moduleName = readModuleNode.executeObject(self); @@ -164,9 +164,9 @@ Object doit(LazyPythonClass klass, @GenerateNodeFactory public abstract static class MroNode extends PythonBuiltinNode { @Specialization - Object doit(AbstractPythonClass klass, + Object doit(PythonAbstractClass klass, @Cached("create()") GetMroNode getMroNode) { - AbstractPythonClass[] mro = getMroNode.execute(klass); + PythonAbstractClass[] mro = getMroNode.execute(klass); return factory().createList(Arrays.copyOf(mro, mro.length, Object[].class)); } @@ -210,24 +210,24 @@ protected static boolean accept(Object[] ary, Object cachedSelf) { @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"accept(arguments, cachedSelf)"}) protected Object doItUnboxed(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords, @Cached("first(arguments)") Object cachedSelf) { - return op(frame, (AbstractPythonClass) cachedSelf, arguments, keywords, false); + return op(frame, (PythonAbstractClass) cachedSelf, arguments, keywords, false); } @Specialization(replaces = "doItUnboxed") protected Object doItUnboxedIndirect(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords) { Object self = arguments[0]; - return op(frame, (AbstractPythonClass) self, arguments, keywords, false); + return op(frame, (PythonAbstractClass) self, arguments, keywords, false); } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf"}) - protected Object doIt(VirtualFrame frame, @SuppressWarnings("unused") AbstractPythonClass self, Object[] arguments, PKeyword[] keywords, - @Cached("self") AbstractPythonClass cachedSelf) { + protected Object doIt(VirtualFrame frame, @SuppressWarnings("unused") PythonAbstractClass self, Object[] arguments, PKeyword[] keywords, + @Cached("self") PythonAbstractClass cachedSelf) { return op(frame, cachedSelf, arguments, keywords, true); } @Specialization(replaces = "doIt") - protected Object doItIndirect(VirtualFrame frame, AbstractPythonClass self, Object[] arguments, PKeyword[] keywords) { + protected Object doItIndirect(VirtualFrame frame, PythonAbstractClass self, Object[] arguments, PKeyword[] keywords) { return op(frame, self, arguments, keywords, true); } @@ -242,13 +242,13 @@ protected Object doItIndirect(VirtualFrame frame, PythonNativeObject self, Objec return op(frame, PythonNativeClass.cast(self), arguments, keywords, true); } - private Object op(VirtualFrame frame, AbstractPythonClass self, Object[] arguments, PKeyword[] keywords, boolean doCreateArgs) { + private Object op(VirtualFrame frame, PythonAbstractClass self, Object[] arguments, PKeyword[] keywords, boolean doCreateArgs) { Object newMethod = lookupNew.execute(self); if (newMethod != PNone.NO_VALUE) { CompilerAsserts.partialEvaluationConstant(doCreateArgs); Object[] newArgs = doCreateArgs ? PositionalArgumentsNode.prependArgument(self, arguments, arguments.length) : arguments; Object newInstance = dispatchNew.execute(frame, newMethod, newArgs, keywords); - AbstractPythonClass newInstanceKlass = getClass.execute(newInstance); + PythonAbstractClass newInstanceKlass = getClass.execute(newInstance); if (isSameType(newInstanceKlass, self)) { if (arguments.length == 2 && isClassClassProfile.profileClass(self, PythonBuiltinClassType.PythonClass)) { // do not call init if we are creating a new instance of type and we are @@ -278,7 +278,7 @@ private Object op(VirtualFrame frame, AbstractPythonClass self, Object[] argumen } } - private boolean isSameType(AbstractPythonClass left, AbstractPythonClass right) { + private boolean isSameType(PythonAbstractClass left, PythonAbstractClass right) { if (isSameTypeNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); isSameTypeNode = insert(TypeNodes.IsSameTypeNode.create()); @@ -286,7 +286,7 @@ private boolean isSameType(AbstractPythonClass left, AbstractPythonClass right) return isSameTypeNode.execute(left, right); } - private String getTypeName(AbstractPythonClass clazz) { + private String getTypeName(PythonAbstractClass clazz) { if (getNameNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getNameNode = insert(TypeNodes.GetNameNode.create()); @@ -502,7 +502,7 @@ private PythonObject getInstanceClassAttr(Object instance) { public abstract boolean executeWith(Object cls, Object instance); @Specialization - public boolean isInstance(AbstractPythonClass cls, Object instance, + public boolean isInstance(PythonAbstractClass cls, Object instance, @Cached("create()") IsSubtypeNode isSubtypeNode, @Cached("create()") GetClassNode getClass) { if (instance instanceof PythonObject && isSubtypeNode.execute(getClass.execute(instance), cls)) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 49129c7eb9..63bc275635 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -102,7 +102,7 @@ public abstract class TypeNodes { public abstract static class GetTypeFlagsNode extends PNodeWithContext { - public abstract long execute(AbstractPythonClass clazz); + public abstract long execute(PythonAbstractClass clazz); @Specialization(guards = "isInitialized(clazz)") long doInitialized(ManagedPythonClass clazz) { @@ -135,7 +135,7 @@ private static long getValue(FlagsContainer fc) { } @TruffleBoundary - public static long doSlowPath(AbstractPythonClass clazz) { + public static long doSlowPath(PythonAbstractClass clazz) { if (clazz instanceof ManagedPythonClass) { ManagedPythonClass mclazz = (ManagedPythonClass) clazz; if (isInitialized(mclazz)) { @@ -175,20 +175,20 @@ public static GetTypeFlagsNode create() { @ImportStatic(NativeMemberNames.class) public abstract static class GetMroNode extends PNodeWithContext { - public abstract AbstractPythonClass[] execute(Object obj); + public abstract PythonAbstractClass[] execute(Object obj); @Specialization - AbstractPythonClass[] doPythonClass(ManagedPythonClass obj) { + PythonAbstractClass[] doPythonClass(ManagedPythonClass obj) { return obj.getMethodResolutionOrder(); } @Specialization - AbstractPythonClass[] doPythonClass(PythonBuiltinClassType obj) { + PythonAbstractClass[] doPythonClass(PythonBuiltinClassType obj) { return getBuiltinPythonClass(obj).getMethodResolutionOrder(); } @Specialization - AbstractPythonClass[] doNativeClass(PythonNativeClass obj, + PythonAbstractClass[] doNativeClass(PythonNativeClass obj, @Cached("create(TP_MRO)") GetTypeMemberNode getTpMroNode) { Object tupleObj = getTpMroNode.execute(obj); if (tupleObj instanceof PTuple) { @@ -201,7 +201,7 @@ AbstractPythonClass[] doNativeClass(PythonNativeClass obj, } @TruffleBoundary - public static AbstractPythonClass[] doSlowPath(Object obj) { + public static PythonAbstractClass[] doSlowPath(Object obj) { if (obj instanceof ManagedPythonClass) { return ((ManagedPythonClass) obj).getMethodResolutionOrder(); } else if (obj instanceof PythonBuiltinClassType) { @@ -289,7 +289,7 @@ LazyPythonClass doNative(PythonNativeClass obj, @Cached("createBinaryProfile()") ConditionProfile profile) { Object tpBaseObj = getTpBaseNode.execute(obj); if (profile.profile(PGuards.isClass(tpBaseObj))) { - return (AbstractPythonClass) tpBaseObj; + return (PythonAbstractClass) tpBaseObj; } CompilerDirectives.transferToInterpreter(); throw raise(SystemError, "Invalid base type object for class %s (base type was '%p' object).", GetNameNode.doSlowPath(obj), tpBaseObj); @@ -304,7 +304,7 @@ public static LazyPythonClass doSlowPath(Object obj) { } else if (PGuards.isNativeClass(obj)) { Object tpBaseObj = GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_BASE); if (PGuards.isClass(tpBaseObj)) { - return (AbstractPythonClass) tpBaseObj; + return (PythonAbstractClass) tpBaseObj; } PythonLanguage.getCore().raise(SystemError, "Invalid base type object for class %s (base type was '%p' object).", GetNameNode.doSlowPath(obj), tpBaseObj); } @@ -321,21 +321,21 @@ public static GetSuperClassNode create() { @ImportStatic(NativeMemberNames.class) public abstract static class GetSubclassesNode extends PNodeWithContext { - public abstract Set execute(Object obj); + public abstract Set execute(Object obj); @Specialization - Set doPythonClass(ManagedPythonClass obj) { + Set doPythonClass(ManagedPythonClass obj) { return obj.getSubClasses(); } @Specialization - Set doPythonClass(PythonBuiltinClassType obj) { + Set doPythonClass(PythonBuiltinClassType obj) { return getBuiltinPythonClass(obj).getSubClasses(); } @Specialization @TruffleBoundary - Set doNativeClass(PythonNativeClass obj, + Set doNativeClass(PythonNativeClass obj, @Cached("create(TP_SUBCLASSES)") GetTypeMemberNode getTpSubclassesNode, @Cached("createClassProfile()") ValueProfile profile) { Object tpSubclasses = getTpSubclassesNode.execute(obj); @@ -349,7 +349,7 @@ Set doNativeClass(PythonNativeClass obj, } @TruffleBoundary - public static Set doSlowPath(Object obj) { + public static Set doSlowPath(Object obj) { if (obj instanceof ManagedPythonClass) { return ((ManagedPythonClass) obj).getSubClasses(); } else if (obj instanceof PythonBuiltinClassType) { @@ -364,8 +364,8 @@ public static Set doSlowPath(Object obj) { throw new IllegalStateException("unknown type " + obj.getClass().getName()); } - private static Set wrapDict(Object tpSubclasses) { - return new Set() { + private static Set wrapDict(Object tpSubclasses) { + return new Set() { private final PDict dict = (PDict) tpSubclasses; public int size() { @@ -388,8 +388,8 @@ public boolean contains(Object o) { } @SuppressWarnings("unchecked") - public Iterator iterator() { - return (Iterator) dict.getDictStorage().values(); + public Iterator iterator() { + return (Iterator) dict.getDictStorage().values(); } public Object[] toArray() { @@ -400,7 +400,7 @@ public T[] toArray(T[] a) { throw new UnsupportedOperationException(); } - public boolean add(AbstractPythonClass e) { + public boolean add(PythonAbstractClass e) { if (PGuards.isNativeClass(e)) { dict.setItem(PythonNativeClass.cast(e).getPtr(), e); } @@ -416,7 +416,7 @@ public boolean containsAll(Collection c) { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection c) { throw new UnsupportedOperationException(); } @@ -445,20 +445,20 @@ public static GetSubclassesNode create() { public abstract static class GetBaseClassesNode extends PNodeWithContext { // TODO(fa): this should not return a Java array; maybe a SequenceStorage would fit - public abstract AbstractPythonClass[] execute(Object obj); + public abstract PythonAbstractClass[] execute(Object obj); @Specialization - AbstractPythonClass[] doPythonClass(ManagedPythonClass obj) { + PythonAbstractClass[] doPythonClass(ManagedPythonClass obj) { return obj.getBaseClasses(); } @Specialization - AbstractPythonClass[] doPythonClass(PythonBuiltinClassType obj) { + PythonAbstractClass[] doPythonClass(PythonBuiltinClassType obj) { return getBuiltinPythonClass(obj).getBaseClasses(); } @Specialization - AbstractPythonClass[] doNative(PythonNativeClass obj, + PythonAbstractClass[] doNative(PythonNativeClass obj, @Cached("create(TP_BASES)") GetTypeMemberNode getTpBasesNode, @Cached("createClassProfile()") ValueProfile resultTypeProfile, @Cached("createToArray()") SequenceStorageNodes.ToArrayNode toArrayNode) { @@ -475,7 +475,7 @@ AbstractPythonClass[] doNative(PythonNativeClass obj, } @TruffleBoundary - public static AbstractPythonClass[] doSlowPath(Object obj) { + public static PythonAbstractClass[] doSlowPath(Object obj) { if (obj instanceof ManagedPythonClass) { return ((ManagedPythonClass) obj).getBaseClasses(); } else if (obj instanceof PythonBuiltinClassType) { @@ -504,10 +504,10 @@ public static GetBaseClassesNode create() { } // TODO: get rid of this - private static AbstractPythonClass[] cast(Object[] arr) { - AbstractPythonClass[] bases = new AbstractPythonClass[arr.length]; + private static PythonAbstractClass[] cast(Object[] arr) { + PythonAbstractClass[] bases = new PythonAbstractClass[arr.length]; for (int i = 0; i < arr.length; i++) { - bases[i] = (AbstractPythonClass) arr[i]; + bases[i] = (PythonAbstractClass) arr[i]; } return bases; } @@ -554,7 +554,7 @@ public static IsSameTypeNode create() { /** accesses the Sulong type of a class; does no recursive resolving */ public abstract static class GetSulongTypeNode extends Node { - public abstract Object execute(AbstractPythonClass clazz); + public abstract Object execute(PythonAbstractClass clazz); @Specialization Object doInitialized(ManagedPythonClass clazz) { @@ -567,7 +567,7 @@ Object doNative(@SuppressWarnings("unused") PythonNativeClass clazz) { } @TruffleBoundary - public static Object getSlowPath(AbstractPythonClass clazz) { + public static Object getSlowPath(PythonAbstractClass clazz) { if (clazz instanceof ManagedPythonClass) { return ((ManagedPythonClass) clazz).getSulongType(); } else if (PGuards.isNativeClass(clazz)) { @@ -577,7 +577,7 @@ public static Object getSlowPath(AbstractPythonClass clazz) { } @TruffleBoundary - public static void setSlowPath(AbstractPythonClass clazz, Object sulongType) { + public static void setSlowPath(PythonAbstractClass clazz, Object sulongType) { if (clazz instanceof ManagedPythonClass) { ((ManagedPythonClass) clazz).setSulongType(sulongType); } else { @@ -594,25 +594,25 @@ public static GetSulongTypeNode create() { public abstract static class ComputeMroNode extends Node { @TruffleBoundary - public static AbstractPythonClass[] doSlowPath(AbstractPythonClass cls) { + public static PythonAbstractClass[] doSlowPath(PythonAbstractClass cls) { return computeMethodResolutionOrder(cls); } - private static AbstractPythonClass[] computeMethodResolutionOrder(AbstractPythonClass cls) { + private static PythonAbstractClass[] computeMethodResolutionOrder(PythonAbstractClass cls) { CompilerAsserts.neverPartOfCompilation(); - AbstractPythonClass[] currentMRO = null; + PythonAbstractClass[] currentMRO = null; - AbstractPythonClass[] baseClasses = GetBaseClassesNode.doSlowPath(cls); + PythonAbstractClass[] baseClasses = GetBaseClassesNode.doSlowPath(cls); if (baseClasses.length == 0) { - currentMRO = new AbstractPythonClass[]{cls}; + currentMRO = new PythonAbstractClass[]{cls}; } else if (baseClasses.length == 1) { - AbstractPythonClass[] baseMRO = GetMroNode.doSlowPath(baseClasses[0]); + PythonAbstractClass[] baseMRO = GetMroNode.doSlowPath(baseClasses[0]); if (baseMRO == null) { - currentMRO = new AbstractPythonClass[]{cls}; + currentMRO = new PythonAbstractClass[]{cls}; } else { - currentMRO = new AbstractPythonClass[baseMRO.length + 1]; + currentMRO = new PythonAbstractClass[baseMRO.length + 1]; System.arraycopy(baseMRO, 0, currentMRO, 1, baseMRO.length); currentMRO[0] = cls; } @@ -626,21 +626,21 @@ private static AbstractPythonClass[] computeMethodResolutionOrder(AbstractPython toMerge[baseClasses.length] = new MROMergeState(); toMerge[baseClasses.length].mro = baseClasses; - ArrayList mro = new ArrayList<>(); + ArrayList mro = new ArrayList<>(); mro.add(cls); currentMRO = mergeMROs(toMerge, mro); } return currentMRO; } - private static AbstractPythonClass[] mergeMROs(MROMergeState[] toMerge, List mro) { + private static PythonAbstractClass[] mergeMROs(MROMergeState[] toMerge, List mro) { int idx; scan: for (idx = 0; idx < toMerge.length; idx++) { if (toMerge[idx].isMerged()) { continue scan; } - AbstractPythonClass candidate = toMerge[idx].getCandidate(); + PythonAbstractClass candidate = toMerge[idx].getCandidate(); for (MROMergeState mergee : toMerge) { if (mergee.pastnextContains(candidate)) { continue scan; @@ -663,7 +663,7 @@ private static AbstractPythonClass[] mergeMROs(MROMergeState[] toMerge, List keys = new HashSet<>(); - AbstractPythonClass klass = getClass.execute(object); - for (AbstractPythonClass o : getMro(klass)) { + PythonAbstractClass klass = getClass.execute(object); + for (PythonAbstractClass o : getMro(klass)) { // TODO PythonNativeClass if (o instanceof PythonObject) { addKeysFromObject(keys, (PythonObject) o, includeInternal); @@ -356,7 +356,7 @@ public Object execute(Object obj, boolean includeInternal) { return factory.createTuple(keys.toArray(new String[keys.size()])); } - private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { + private PythonAbstractClass[] getMro(PythonAbstractClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); @@ -803,8 +803,8 @@ public int access(Object object, Object fieldName) { int info = KeyInfo.NONE; Object attr = PNone.NO_VALUE; - AbstractPythonClass klass = getClassNode.execute(object); - for (AbstractPythonClass c : getMro(klass)) { + PythonAbstractClass klass = getClassNode.execute(object); + for (PythonAbstractClass c : getMro(klass)) { if (readTypeAttrNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); readTypeAttrNode = insert(ReadAttributeFromObjectNode.createForceType()); @@ -871,7 +871,7 @@ public int access(Object object, Object fieldName) { return info; } - private AbstractPythonClass[] getMro(AbstractPythonClass clazz) { + private PythonAbstractClass[] getMro(PythonAbstractClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getMroNode = insert(GetMroNode.create()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index b40bce9921..d97e8107d9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -109,7 +109,7 @@ import com.oracle.graal.python.builtins.objects.thread.PThread; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.zipimporter.PZipImporter; @@ -356,7 +356,7 @@ public PythonModule createPythonModule(LazyPythonClass cls, String name) { return trace(new PythonModule(cls, name)); } - public PythonClass createPythonClass(LazyPythonClass metaclass, String name, AbstractPythonClass[] bases) { + public PythonClass createPythonClass(LazyPythonClass metaclass, String name, PythonAbstractClass[] bases) { return trace(new PythonClass(metaclass, name, PythonLanguage.freshShape(), bases)); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java index af2d62da3a..6f4a72f702 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java @@ -27,27 +27,27 @@ import java.util.Arrays; -import com.oracle.graal.python.builtins.objects.type.AbstractPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.truffle.api.profiles.ConditionProfile; public final class MroSequenceStorage extends TypedSequenceStorage { - private AbstractPythonClass[] values; + private PythonAbstractClass[] values; - public MroSequenceStorage(AbstractPythonClass[] elements) { + public MroSequenceStorage(PythonAbstractClass[] elements) { this.values = elements; this.capacity = elements.length; this.length = elements.length; } - public MroSequenceStorage(AbstractPythonClass[] elements, int length) { + public MroSequenceStorage(PythonAbstractClass[] elements, int length) { this.values = elements; this.capacity = elements.length; this.length = length; } public MroSequenceStorage(int capacity) { - this.values = new AbstractPythonClass[capacity]; + this.values = new PythonAbstractClass[capacity]; this.capacity = capacity; this.length = 0; } @@ -59,14 +59,14 @@ public Object getItemNormalized(int idx) { @Override public void setItemNormalized(int idx, Object value) { - if (value instanceof AbstractPythonClass) { - setClassItemNormalized(idx, (AbstractPythonClass) value); + if (value instanceof PythonAbstractClass) { + setClassItemNormalized(idx, (PythonAbstractClass) value); } else { throw new SequenceStoreException(value); } } - public void setClassItemNormalized(int idx, AbstractPythonClass value) { + public void setClassItemNormalized(int idx, PythonAbstractClass value) { values[idx] = value; } @@ -90,7 +90,7 @@ public void copyItem(int idxTo, int idxFrom) { @Override public MroSequenceStorage getSliceInBound(int start, int stop, int step, int sliceLength) { - AbstractPythonClass[] newArray = new AbstractPythonClass[sliceLength]; + PythonAbstractClass[] newArray = new PythonAbstractClass[sliceLength]; if (step == 1) { System.arraycopy(values, start, newArray, 0, sliceLength); @@ -139,7 +139,7 @@ public Object[] getInternalArray() { return values; } - public AbstractPythonClass[] getInternalClassArray() { + public PythonAbstractClass[] getInternalClassArray() { return values; } @@ -151,7 +151,7 @@ public void increaseCapacityExactWithCopy(int newCapacity) { @Override public void increaseCapacityExact(int newCapacity) { - values = new AbstractPythonClass[newCapacity]; + values = new PythonAbstractClass[newCapacity]; capacity = values.length; } @@ -169,7 +169,7 @@ public void reverse() { int middle = (length - 1) / 2; for (; head <= middle; head++, tail--) { - AbstractPythonClass temp = values[head]; + PythonAbstractClass temp = values[head]; values[head] = values[tail]; values[tail] = temp; } @@ -212,7 +212,7 @@ public Object getCopyOfInternalArrayObject() { @Override public void setInternalArrayObject(Object arrayObject) { - this.values = (AbstractPythonClass[]) arrayObject; + this.values = (PythonAbstractClass[]) arrayObject; } @Override From fa2ddeeb118f692e7c42ad0c7a126aa11676e601 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 15:33:52 +0100 Subject: [PATCH 093/202] Rename 'ManagedPythonClass' to 'PythonManagedClass'. --- .../oracle/graal/python/PythonLanguage.java | 8 +-- .../builtins/modules/BuiltinConstructors.java | 14 ++--- .../builtins/modules/TruffleCextBuiltins.java | 6 +- .../builtins/objects/cext/CExtNodes.java | 14 ++--- .../builtins/objects/cext/NativeWrappers.java | 12 ++-- .../objects/cext/PyBufferProcsWrapperMR.java | 4 +- .../objects/cext/PyNumberMethodsWrapper.java | 8 +-- .../cext/PyNumberMethodsWrapperMR.java | 8 +-- .../cext/PySequenceMethodsWrapper.java | 8 +-- .../cext/PySequenceMethodsWrapperMR.java | 4 +- .../cext/PythonObjectNativeWrapperMR.java | 58 +++++++++---------- .../builtins/objects/object/PythonObject.java | 6 +- .../objects/type/PythonBuiltinClass.java | 2 +- .../builtins/objects/type/PythonClass.java | 2 +- ...thonClass.java => PythonManagedClass.java} | 4 +- .../builtins/objects/type/TypeBuiltins.java | 8 +-- .../builtins/objects/type/TypeNodes.java | 58 +++++++++---------- .../attributes/LookupAttributeInMRONode.java | 18 +++--- .../WriteAttributeToObjectNode.java | 8 +-- 19 files changed, 125 insertions(+), 125 deletions(-) rename graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/{ManagedPythonClass.java => PythonManagedClass.java} (98%) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index b5361ec5d7..2b4c4e81c4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -47,7 +47,7 @@ import com.oracle.graal.python.builtins.objects.method.PMethod; 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.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.NodeFactory; import com.oracle.graal.python.nodes.PGuards; @@ -398,9 +398,9 @@ protected SourceSection findSourceLocation(PythonContext context, Object value) return callable.getCallTarget().getRootNode().getSourceSection(); } else if (value instanceof PCode) { return ((PCode) value).getRootNode().getSourceSection(); - } else if (value instanceof ManagedPythonClass) { - for (String k : ((ManagedPythonClass) value).getAttributeNames()) { - Object attrValue = ReadAttributeFromDynamicObjectNode.doSlowPath(((ManagedPythonClass) value).getStorage(), k); + } else if (value instanceof PythonManagedClass) { + for (String k : ((PythonManagedClass) value).getAttributeNames()) { + Object attrValue = ReadAttributeFromDynamicObjectNode.doSlowPath(((PythonManagedClass) value).getStorage(), k); SourceSection attrSourceLocation = findSourceLocation(context, attrValue); if (attrSourceLocation != null) { return attrSourceLocation; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index b2e35fca1e..a4f3165e22 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -119,7 +119,7 @@ import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; @@ -1353,13 +1353,13 @@ Object doDirectConstruct(@SuppressWarnings("unused") PNone ignored, Object[] arg } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf", "!self.needsNativeAllocation()"}) - Object doObjectDirect(@SuppressWarnings("unused") ManagedPythonClass self, Object[] varargs, PKeyword[] kwargs, - @Cached("self") ManagedPythonClass cachedSelf) { + Object doObjectDirect(@SuppressWarnings("unused") PythonManagedClass self, Object[] varargs, PKeyword[] kwargs, + @Cached("self") PythonManagedClass cachedSelf) { return doObjectIndirect(cachedSelf, varargs, kwargs); } @Specialization(guards = "!self.needsNativeAllocation()", replaces = "doObjectDirect") - Object doObjectIndirect(ManagedPythonClass self, Object[] varargs, PKeyword[] kwargs) { + Object doObjectIndirect(PythonManagedClass self, Object[] varargs, PKeyword[] kwargs) { if (varargs.length > 0 || kwargs.length > 0) { // TODO: tfel: this should throw an error only if init isn't overridden } @@ -1367,7 +1367,7 @@ Object doObjectIndirect(ManagedPythonClass self, Object[] varargs, PKeyword[] kw } @Specialization(guards = "self.needsNativeAllocation()") - Object doNativeObjectIndirect(ManagedPythonClass self, Object[] varargs, PKeyword[] kwargs, + Object doNativeObjectIndirect(PythonManagedClass self, Object[] varargs, PKeyword[] kwargs, @Cached("create()") GetMroNode getMroNode) { if (varargs.length > 0 || kwargs.length > 0) { // TODO: tfel: this should throw an error only if init isn't overridden @@ -2030,7 +2030,7 @@ private ReadCallerFrameNode getReadCallerFrameNode() { return readCallerFrameNode; } - private void addNativeSlots(ManagedPythonClass pythonClass, PTuple slots) { + private void addNativeSlots(PythonManagedClass pythonClass, PTuple slots) { if (callAddNativeSlotsNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); callAddNativeSlotsNode = insert(CExtNodes.PCallCapiFunction.create(NativeCAPISymbols.FUN_ADD_NATIVE_SLOTS)); @@ -2046,7 +2046,7 @@ private CastToListNode getCastToListNode() { return castToList; } - private boolean addDictIfNative(ManagedPythonClass pythonClass) { + private boolean addDictIfNative(PythonManagedClass pythonClass) { boolean addedNewDict = false; if (pythonClass.needsNativeAllocation()) { for (Object cls : getMro(pythonClass)) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 0ca7fe471c..b33f289d84 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -120,7 +120,7 @@ import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; @@ -1375,7 +1375,7 @@ abstract static class PyTruffle_Set_SulongType extends NativeBuiltin { @Specialization Object doPythonObject(PythonClassNativeWrapper klass, Object ptr) { - ((ManagedPythonClass) klass.getPythonObject()).setSulongType(ptr); + ((PythonManagedClass) klass.getPythonObject()).setSulongType(ptr); return ptr; } } @@ -1392,7 +1392,7 @@ Object doNativeWrapper(PythonClassNativeWrapper nativeWrapper, Object getBufferP } @Specialization - Object doPythonObject(ManagedPythonClass obj, Object getBufferProc, Object releaseBufferProc) { + Object doPythonObject(PythonManagedClass obj, Object getBufferProc, Object releaseBufferProc) { return doNativeWrapper(obj.getNativeWrapper(), getBufferProc, releaseBufferProc); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index 088463f4d8..7edd6255f4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -74,7 +74,7 @@ import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; @@ -322,14 +322,14 @@ Object doNativeNull(PythonNativeNull object) { } @Specialization(guards = "object == cachedObject", limit = "3") - Object doPythonClass(@SuppressWarnings("unused") ManagedPythonClass object, - @SuppressWarnings("unused") @Cached("object") ManagedPythonClass cachedObject, + Object doPythonClass(@SuppressWarnings("unused") PythonManagedClass object, + @SuppressWarnings("unused") @Cached("object") PythonManagedClass cachedObject, @Cached("wrapNativeClass(object)") PythonClassNativeWrapper wrapper) { return wrapper; } @Specialization(replaces = "doPythonClass") - Object doPythonClassUncached(ManagedPythonClass object, + Object doPythonClassUncached(PythonManagedClass object, @Cached("create()") TypeNodes.GetNameNode getNameNode) { return PythonClassNativeWrapper.wrap(object, getNameNode.execute(object)); } @@ -360,7 +360,7 @@ Object run(Object obj) { return obj; } - protected static PythonClassNativeWrapper wrapNativeClass(ManagedPythonClass object) { + protected static PythonClassNativeWrapper wrapNativeClass(PythonManagedClass object) { return PythonClassNativeWrapper.wrap(object, GetNameNode.doSlowPath(object)); } @@ -384,8 +384,8 @@ public static Object doSlowPath(Object o) { return PythonNativeObject.cast(o).getPtr(); } else if (o instanceof PythonNativeNull) { return ((PythonNativeNull) o).getPtr(); - } else if (o instanceof ManagedPythonClass) { - return wrapNativeClass((ManagedPythonClass) o); + } else if (o instanceof PythonManagedClass) { + return wrapNativeClass((PythonManagedClass) o); } else if (o instanceof PythonAbstractObject) { assert !PGuards.isClass(o); return PythonObjectNativeWrapper.wrapSlowPath((PythonAbstractObject) o); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java index 1de6d65413..89472e9bfe 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java @@ -46,7 +46,7 @@ import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.str.PString; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.interop.ForeignAccess; @@ -277,7 +277,7 @@ public static PrimitiveNativeWrapper createDouble(double val) { } /** - * Used to wrap {@link ManagedPythonClass} when used in native code. This wrapper mimics the + * Used to wrap {@link PythonManagedClass} when used in native code. This wrapper mimics the * correct shape of the corresponding native type {@code struct _typeobject}. */ public static class PythonClassNativeWrapper extends PythonObjectNativeWrapper { @@ -285,7 +285,7 @@ public static class PythonClassNativeWrapper extends PythonObjectNativeWrapper { private Object getBufferProc; private Object releaseBufferProc; - public PythonClassNativeWrapper(ManagedPythonClass object, String typeName) { + public PythonClassNativeWrapper(PythonManagedClass object, String typeName) { super(object); this.nameWrapper = new CStringWrapper(typeName); } @@ -310,7 +310,7 @@ public void setReleaseBufferProc(Object releaseBufferProc) { this.releaseBufferProc = releaseBufferProc; } - public static PythonClassNativeWrapper wrap(ManagedPythonClass obj, String typeName) { + public static PythonClassNativeWrapper wrap(PythonManagedClass obj, String typeName) { // important: native wrappers are cached PythonClassNativeWrapper nativeWrapper = obj.getNativeWrapper(); if (nativeWrapper == null) { @@ -327,13 +327,13 @@ public String toString() { } /** - * Used to wrap {@link ManagedPythonClass} just for the time when a natively defined type is + * Used to wrap {@link PythonManagedClass} just for the time when a natively defined type is * processed in {@code PyType_Ready} and we need to pass the mirroring managed class to native * to marry these two objects. */ public static class PythonClassInitNativeWrapper extends PythonObjectNativeWrapper { - public PythonClassInitNativeWrapper(ManagedPythonClass object) { + public PythonClassInitNativeWrapper(PythonManagedClass object) { super(object); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java index 4664ba2625..ed43f33def 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java @@ -45,7 +45,7 @@ import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper; import com.oracle.graal.python.builtins.objects.cext.PyBufferProcsWrapperMRFactory.GetBufferProcsNodeGen; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; @@ -76,7 +76,7 @@ abstract static class GetBufferProcsNode extends PNodeWithContext { public abstract Object execute(PythonAbstractClass clazz, String key); @Specialization - Object doManagedClass(ManagedPythonClass clazz, String key) { + Object doManagedClass(PythonManagedClass clazz, String key) { // translate key to attribute name PythonClassNativeWrapper nativeWrapper = clazz.getNativeWrapper(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java index 32e0d3724d..0102be1c99 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java @@ -41,7 +41,7 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonNativeWrapper; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.TruffleObject; @@ -50,7 +50,7 @@ */ public class PyNumberMethodsWrapper extends PythonNativeWrapper { - public PyNumberMethodsWrapper(ManagedPythonClass delegate) { + public PyNumberMethodsWrapper(PythonManagedClass delegate) { super(delegate); } @@ -63,7 +63,7 @@ public ForeignAccess getForeignAccess() { return PyNumberMethodsWrapperMRForeign.ACCESS; } - public ManagedPythonClass getPythonClass() { - return (ManagedPythonClass) getDelegate(); + public PythonManagedClass getPythonClass() { + return (PythonManagedClass) getDelegate(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java index 7bb867be77..e6aa99353e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java @@ -57,7 +57,7 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToSulongNode; import com.oracle.graal.python.builtins.objects.cext.PyNumberMethodsWrapperMRFactory.ReadMethodNodeGen; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.truffle.api.CompilerDirectives; @@ -78,7 +78,7 @@ abstract static class ReadNode extends Node { public Object access(PyNumberMethodsWrapper object, String key) { // translate key to attribute name - ManagedPythonClass delegate = object.getPythonClass(); + PythonManagedClass delegate = object.getPythonClass(); return getToSulongNode().execute(readMethodNode.execute(delegate, key)); } @@ -93,10 +93,10 @@ private ToSulongNode getToSulongNode() { abstract static class ReadMethodNode extends PNodeWithContext { - public abstract Object execute(ManagedPythonClass clazz, String key); + public abstract Object execute(PythonManagedClass clazz, String key); @Specialization(limit = "99", guards = {"eq(cachedKey, key)"}) - Object getMethod(ManagedPythonClass clazz, @SuppressWarnings("unused") String key, + Object getMethod(PythonManagedClass clazz, @SuppressWarnings("unused") String key, @Cached("key") @SuppressWarnings("unused") String cachedKey, @Cached("createLookupNode(cachedKey)") LookupAttributeInMRONode lookupNode) { if (lookupNode != null) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java index e5c654d713..b58d3e0806 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java @@ -41,7 +41,7 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonNativeWrapper; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.TruffleObject; @@ -50,7 +50,7 @@ */ public class PySequenceMethodsWrapper extends PythonNativeWrapper { - public PySequenceMethodsWrapper(ManagedPythonClass delegate) { + public PySequenceMethodsWrapper(PythonManagedClass delegate) { super(delegate); } @@ -63,7 +63,7 @@ public ForeignAccess getForeignAccess() { return PySequenceMethodsWrapperMRForeign.ACCESS; } - public ManagedPythonClass getPythonClass() { - return (ManagedPythonClass) getDelegate(); + public PythonManagedClass getPythonClass() { + return (PythonManagedClass) getDelegate(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java index df052987f2..a57c92eb0b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java @@ -41,7 +41,7 @@ package com.oracle.graal.python.builtins.objects.cext; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToSulongNode; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; import com.oracle.truffle.api.CompilerDirectives; @@ -60,7 +60,7 @@ abstract static class ReadNode extends Node { @Child private ToSulongNode toSulongNode; public Object access(PySequenceMethodsWrapper object, String key) { - ManagedPythonClass delegate = object.getPythonClass(); + PythonManagedClass delegate = object.getPythonClass(); Object result; switch (key) { case NativeMemberNames.SQ_REPEAT: diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index 273c072916..ea07d7cab5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -95,7 +95,7 @@ import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.TypeBuiltins; @@ -233,14 +233,14 @@ Object doBuiltinGeneric(PythonBuiltinClassType clazz, } @Specialization(assumptions = "singleContextAssumption()", guards = "clazz == cachedClass") - Object doManagedCached(@SuppressWarnings("unused") ManagedPythonClass clazz, - @Cached("clazz") @SuppressWarnings("unused") ManagedPythonClass cachedClass, + Object doManagedCached(@SuppressWarnings("unused") PythonManagedClass clazz, + @Cached("clazz") @SuppressWarnings("unused") PythonManagedClass cachedClass, @Cached("getSulongTypeForClass(cachedClass)") Object sulongType) { return sulongType; } @Specialization(replaces = "doManagedCached") - Object doManagedGeneric(ManagedPythonClass clazz, + Object doManagedGeneric(PythonManagedClass clazz, @Cached("create()") TypeNodes.GetSulongTypeNode getSulongTypeNode, @Cached("createBinaryProfile()") ConditionProfile hasSulongTypeProfile) { Object sulongType = getSulongTypeNode.execute(clazz); @@ -412,19 +412,19 @@ Object doObFval(Object object, @SuppressWarnings("unused") String key, } @Specialization(guards = "eq(TP_FLAGS, key)") - long doTpFlags(ManagedPythonClass object, @SuppressWarnings("unused") String key, + long doTpFlags(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create()") GetTypeFlagsNode getTypeFlagsNode) { return getTypeFlagsNode.execute(object); } @Specialization(guards = "eq(TP_NAME, key)") - Object doTpName(ManagedPythonClass object, @SuppressWarnings("unused") String key) { + Object doTpName(PythonManagedClass object, @SuppressWarnings("unused") String key) { // return a C string wrapper that really allocates 'char*' on TO_NATIVE return object.getNativeWrapper().getNameWrapper(); } @Specialization(guards = "eq(TP_BASE, key)") - Object doTpBase(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpBase(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create()") GetSuperClassNode getSuperClassNode, @Cached("createBinaryProfile()") ConditionProfile profile) { LazyPythonClass superClass = getSuperClassNode.execute(object); @@ -435,20 +435,20 @@ Object doTpBase(ManagedPythonClass object, @SuppressWarnings("unused") String ke } @Specialization(guards = "eq(TP_ALLOC, key)") - Object doTpAlloc(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpAlloc(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create(__ALLOC__)") LookupAttributeInMRONode getAllocNode) { Object result = getAllocNode.execute(object); return getToSulongNode().execute(result); } @Specialization(guards = "eq(TP_AS_NUMBER, key)") - Object doTpAsNumber(ManagedPythonClass object, @SuppressWarnings("unused") String key) { + Object doTpAsNumber(PythonManagedClass object, @SuppressWarnings("unused") String key) { // TODO check for type and return 'NULL' return new PyNumberMethodsWrapper(object); } @Specialization(guards = "eq(TP_AS_BUFFER, key)") - Object doTpAsBuffer(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpAsBuffer(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create()") IsSubtypeNode isSubtype, @Cached("create()") BranchProfile notBytes, @Cached("create()") BranchProfile notBytearray, @@ -480,7 +480,7 @@ Object doTpAsBuffer(ManagedPythonClass object, @SuppressWarnings("unused") Strin } @Specialization(guards = "eq(TP_AS_SEQUENCE, key)") - Object doTpAsSequence(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpAsSequence(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create(__LEN__)") LookupAttributeInMRONode getAttrNode) { if (getAttrNode.execute(object) != PNone.NO_VALUE) { return new PySequenceMethodsWrapper(object); @@ -490,19 +490,19 @@ Object doTpAsSequence(ManagedPythonClass object, @SuppressWarnings("unused") Str } @Specialization(guards = "eq(TP_NEW, key)") - Object doTpNew(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpNew(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create(__NEW__)") LookupAttributeInMRONode getAttrNode) { return ManagedMethodWrappers.createKeywords(getAttrNode.execute(object)); } @Specialization(guards = "eq(TP_HASH, key)") - Object doTpHash(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpHash(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create(__HASH__)") LookupAttributeInMRONode getHashNode) { return getToSulongNode().execute(getHashNode.execute(object)); } @Specialization(guards = "eq(TP_BASICSIZE, key)") - Object doTpBasicsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpBasicsize(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create()") CastToIndexNode castToIntNode, @Cached("create(__BASICSIZE__)") GetFixedAttributeNode getAttrNode) { Object val = getAttrNode.executeObject(object); @@ -510,7 +510,7 @@ Object doTpBasicsize(ManagedPythonClass object, @SuppressWarnings("unused") Stri } @Specialization(guards = "eq(TP_ITEMSIZE, key)") - long doTpItemsize(ManagedPythonClass object, @SuppressWarnings("unused") String key, + long doTpItemsize(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create()") CastToIndexNode castToIntNode, @Cached("create(__ITEMSIZE__)") GetFixedAttributeNode getAttrNode) { Object val = getAttrNode.executeObject(object); @@ -523,7 +523,7 @@ long doTpItemsize(ManagedPythonClass object, @SuppressWarnings("unused") String } @Specialization(guards = "eq(TP_DICTOFFSET, key)") - long doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") String key, + long doTpDictoffset(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create()") CastToIndexNode castToIntNode, @Cached("create(__DICTOFFSET__)") GetFixedAttributeNode getAttrNode) { // TODO properly implement 'tp_dictoffset' for builtin classes @@ -535,7 +535,7 @@ long doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") Strin } @Specialization(guards = "eq(TP_WEAKLISTOFFSET, key)") - Object doTpWeaklistoffset(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpWeaklistoffset(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create(__WEAKLISTOFFSET__)") LookupAttributeInMRONode getAttrNode) { Object val = getAttrNode.execute(object); // If the attribute does not exist, this means that we take 'tp_itemsize' from the base @@ -547,44 +547,44 @@ Object doTpWeaklistoffset(ManagedPythonClass object, @SuppressWarnings("unused") } @Specialization(guards = "eq(TP_RICHCOMPARE, key)") - Object doTpRichcompare(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpRichcompare(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create(RICHCMP)") LookupAttributeInMRONode getCmpNode) { return getToSulongNode().execute(getCmpNode.execute(object)); } @Specialization(guards = "eq(TP_SUBCLASSES, key)") - Object doTpSubclasses(@SuppressWarnings("unused") ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpSubclasses(@SuppressWarnings("unused") PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) { // TODO create dict view on subclasses set return PythonObjectNativeWrapper.wrap(factory().createDict(), noWrapperProfile); } @Specialization(guards = "eq(TP_GETATTR, key)") - Object doTpGetattr(@SuppressWarnings("unused") ManagedPythonClass object, @SuppressWarnings("unused") String key) { + Object doTpGetattr(@SuppressWarnings("unused") PythonManagedClass object, @SuppressWarnings("unused") String key) { // we do not provide 'tp_getattr'; code will usually then use 'tp_getattro' return getToSulongNode().execute(PNone.NO_VALUE); } @Specialization(guards = "eq(TP_SETATTR, key)") - Object doTpSetattr(@SuppressWarnings("unused") ManagedPythonClass object, @SuppressWarnings("unused") String key) { + Object doTpSetattr(@SuppressWarnings("unused") PythonManagedClass object, @SuppressWarnings("unused") String key) { // we do not provide 'tp_setattr'; code will usually then use 'tp_setattro' return getToSulongNode().execute(PNone.NO_VALUE); } @Specialization(guards = "eq(TP_GETATTRO, key)") - Object doTpGetattro(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpGetattro(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create(__GETATTRIBUTE__)") LookupAttributeInMRONode lookupAttrNode) { return PyProcsWrapper.createGetAttrWrapper(lookupAttrNode.execute(object)); } @Specialization(guards = "eq(TP_SETATTRO, key)") - Object doTpSetattro(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpSetattro(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create(__SETATTR__)") LookupAttributeInMRONode lookupAttrNode) { return PyProcsWrapper.createSetAttrWrapper(lookupAttrNode.execute(object)); } @Specialization(guards = "eq(TP_ITERNEXT, key)") - Object doTpIternext(ManagedPythonClass object, @SuppressWarnings("unused") String key, + Object doTpIternext(PythonManagedClass object, @SuppressWarnings("unused") String key, @Cached("create(__NEXT__)") LookupAttributeInMRONode lookupAttrNode) { return getToSulongNode().execute(lookupAttrNode.execute(object)); } @@ -888,14 +888,14 @@ abstract static class WriteNativeMemberNode extends PNodeWithContext { abstract Object execute(Object receiver, String key, Object value); @Specialization(guards = "eq(OB_TYPE, key)") - Object doObType(PythonObject object, @SuppressWarnings("unused") String key, @SuppressWarnings("unused") ManagedPythonClass value, + Object doObType(PythonObject object, @SuppressWarnings("unused") String key, @SuppressWarnings("unused") PythonManagedClass value, @Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) { // At this point, we do not support changing the type of an object. return PythonObjectNativeWrapper.wrap(object, noWrapperProfile); } @Specialization(guards = "eq(TP_FLAGS, key)") - long doTpFlags(ManagedPythonClass object, @SuppressWarnings("unused") String key, long flags) { + long doTpFlags(PythonManagedClass object, @SuppressWarnings("unused") String key, long flags) { object.setFlags(flags); return flags; } @@ -914,7 +914,7 @@ long doTpBasicsize(PythonAbstractClass object, @SuppressWarnings("unused") Strin @Specialization(guards = "eq(TP_SUBCLASSES, key)") @TruffleBoundary - Object doTpSubclasses(ManagedPythonClass object, @SuppressWarnings("unused") String key, PythonObjectNativeWrapper value) { + Object doTpSubclasses(PythonManagedClass object, @SuppressWarnings("unused") String key, PythonObjectNativeWrapper value) { // TODO more type checking; do fast path PDict dict = (PDict) value.getPythonObject(); for (Object item : dict.items()) { @@ -932,7 +932,7 @@ Object doMdDef(PythonObject object, @SuppressWarnings("unused") String key, Obje } @Specialization(guards = "eq(TP_DICT, key)") - Object doTpDict(ManagedPythonClass object, @SuppressWarnings("unused") String key, Object nativeValue, + Object doTpDict(PythonManagedClass object, @SuppressWarnings("unused") String key, Object nativeValue, @Cached("create()") CExtNodes.AsPythonObjectNode asPythonObjectNode, @Cached("create()") HashingStorageNodes.GetItemNode getItem, @Cached("create()") WriteAttributeToObjectNode writeAttrNode, @@ -958,7 +958,7 @@ Object doTpDict(ManagedPythonClass object, @SuppressWarnings("unused") String ke } @Specialization(guards = "eq(TP_DICTOFFSET, key)") - Object doTpDictoffset(ManagedPythonClass object, @SuppressWarnings("unused") String key, Object value, + Object doTpDictoffset(PythonManagedClass object, @SuppressWarnings("unused") String key, Object value, @Cached("create()") CastToIntegerFromIntNode castToIntNode, @Cached("create(__SETATTR__)") LookupAndCallTernaryNode call) { // TODO properly implement 'tp_dictoffset' for builtin classes diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java index 975c039cce..5e7753908e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java @@ -35,7 +35,7 @@ import com.oracle.graal.python.builtins.objects.common.PHashingCollection; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.truffle.api.Assumption; @@ -156,8 +156,8 @@ public List getAttributeNames() { } public final PythonAbstractClass asPythonClass() { - if (this instanceof ManagedPythonClass) { - return (ManagedPythonClass) this; + if (this instanceof PythonManagedClass) { + return (PythonManagedClass) this; } return getPythonClass(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java index af4964e0ec..6908d2fda4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java @@ -35,7 +35,7 @@ /** * A Python built-in class that is immutable. */ -public final class PythonBuiltinClass extends ManagedPythonClass { +public final class PythonBuiltinClass extends PythonManagedClass { private final PythonBuiltinClassType type; public PythonBuiltinClass(PythonBuiltinClassType builtinClass, PythonAbstractClass base) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java index 54e4ff88d7..a2014c9221 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java @@ -30,7 +30,7 @@ /** * Mutable class. */ -public final class PythonClass extends ManagedPythonClass { +public final class PythonClass extends PythonManagedClass { public PythonClass(LazyPythonClass typeClass, String name, Shape instanceShape, PythonAbstractClass[] baseClasses) { super(typeClass, name, instanceShape, baseClasses); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java similarity index 98% rename from graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java rename to graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java index 20f66d0c88..be6226801e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/ManagedPythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java @@ -27,7 +27,7 @@ import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.utilities.CyclicAssumption; -public abstract class ManagedPythonClass extends PythonObject implements PythonAbstractClass { +public abstract class PythonManagedClass extends PythonObject implements PythonAbstractClass { private final String className; @@ -53,7 +53,7 @@ public abstract class ManagedPythonClass extends PythonObject implements PythonA @CompilationFinal private Object sulongType; @TruffleBoundary - public ManagedPythonClass(LazyPythonClass typeClass, String name, Shape instanceShape, PythonAbstractClass... baseClasses) { + public PythonManagedClass(LazyPythonClass typeClass, String name, Shape instanceShape, PythonAbstractClass... baseClasses) { super(typeClass, PythonLanguage.freshShape() /* do not inherit layout from the TypeClass */); this.className = name; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index bd72af6122..cef205f05c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -458,7 +458,7 @@ Object bases(LazyPythonClass self, @ImportStatic(NativeMemberNames.class) static abstract class DictNode extends PythonUnaryBuiltinNode { @Specialization - Object doManaged(ManagedPythonClass self) { + Object doManaged(PythonManagedClass self) { PHashingCollection dict = self.getDict(); if (dict == null) { dict = factory().createMappingproxy(self); @@ -736,7 +736,7 @@ private static String getQualName(String fqname) { static abstract class DictoffsetNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") - Object getName(ManagedPythonClass cls, @SuppressWarnings("unused") PNone value, + Object getName(PythonManagedClass cls, @SuppressWarnings("unused") PNone value, @Cached("create()") IsBuiltinClassProfile profile, @Cached("create()") ReadAttributeFromObjectNode getName) { // recursion anchor; since the metaclass of 'type' is 'type' @@ -773,7 +773,7 @@ Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @Su static abstract class ItemsizeNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") - Object getName(ManagedPythonClass cls, @SuppressWarnings("unused") PNone value, + Object getName(PythonManagedClass cls, @SuppressWarnings("unused") PNone value, @Cached("create()") IsBuiltinClassProfile profile, @Cached("create()") ReadAttributeFromObjectNode getName) { // recursion anchor; since the metaclass of 'type' is 'type' @@ -810,7 +810,7 @@ Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @Su static abstract class BasicsizeNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") - Object getName(ManagedPythonClass cls, @SuppressWarnings("unused") PNone value, + Object getName(PythonManagedClass cls, @SuppressWarnings("unused") PNone value, @Cached("create()") IsBuiltinClassProfile profile, @Cached("create()") ReadAttributeFromObjectNode getName) { // recursion anchor; since the metaclass of 'type' is 'type' diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 63bc275635..ccdeaea4ce 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -62,7 +62,7 @@ import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass.FlagsContainer; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass.FlagsContainer; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetBaseClassesNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetNameNodeGen; @@ -105,12 +105,12 @@ public abstract static class GetTypeFlagsNode extends PNodeWithContext { public abstract long execute(PythonAbstractClass clazz); @Specialization(guards = "isInitialized(clazz)") - long doInitialized(ManagedPythonClass clazz) { + long doInitialized(PythonManagedClass clazz) { return clazz.getFlagsContainer().flags; } @Specialization - long doGeneric(ManagedPythonClass clazz) { + long doGeneric(PythonManagedClass clazz) { if (!isInitialized(clazz)) { return getValue(clazz.getFlagsContainer()); } @@ -136,8 +136,8 @@ private static long getValue(FlagsContainer fc) { @TruffleBoundary public static long doSlowPath(PythonAbstractClass clazz) { - if (clazz instanceof ManagedPythonClass) { - ManagedPythonClass mclazz = (ManagedPythonClass) clazz; + if (clazz instanceof PythonManagedClass) { + PythonManagedClass mclazz = (PythonManagedClass) clazz; if (isInitialized(mclazz)) { return mclazz.getFlagsContainer().flags; } else { @@ -159,7 +159,7 @@ static long doNativeGeneric(PythonNativeClass clazz, Node readNode) { } } - protected static boolean isInitialized(ManagedPythonClass clazz) { + protected static boolean isInitialized(PythonManagedClass clazz) { return clazz.getFlagsContainer().initialDominantBase == null; } @@ -178,7 +178,7 @@ public abstract static class GetMroNode extends PNodeWithContext { public abstract PythonAbstractClass[] execute(Object obj); @Specialization - PythonAbstractClass[] doPythonClass(ManagedPythonClass obj) { + PythonAbstractClass[] doPythonClass(PythonManagedClass obj) { return obj.getMethodResolutionOrder(); } @@ -202,8 +202,8 @@ PythonAbstractClass[] doNativeClass(PythonNativeClass obj, @TruffleBoundary public static PythonAbstractClass[] doSlowPath(Object obj) { - if (obj instanceof ManagedPythonClass) { - return ((ManagedPythonClass) obj).getMethodResolutionOrder(); + if (obj instanceof PythonManagedClass) { + return ((PythonManagedClass) obj).getMethodResolutionOrder(); } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getMethodResolutionOrder(); } else if (PGuards.isNativeClass(obj)) { @@ -230,7 +230,7 @@ public abstract static class GetNameNode extends PNodeWithContext { public abstract String execute(Object obj); @Specialization - String doManagedClass(ManagedPythonClass obj) { + String doManagedClass(PythonManagedClass obj) { return obj.getName(); } @@ -247,8 +247,8 @@ String doNativeClass(PythonNativeClass obj, @TruffleBoundary public static String doSlowPath(Object obj) { - if (obj instanceof ManagedPythonClass) { - return ((ManagedPythonClass) obj).getName(); + if (obj instanceof PythonManagedClass) { + return ((PythonManagedClass) obj).getName(); } else if (obj instanceof PythonBuiltinClassType) { // TODO(fa): remove this special case if (obj == PythonBuiltinClassType.TruffleObject) { @@ -274,7 +274,7 @@ public abstract static class GetSuperClassNode extends PNodeWithContext { public abstract LazyPythonClass execute(Object obj); @Specialization - LazyPythonClass doManaged(ManagedPythonClass obj) { + LazyPythonClass doManaged(PythonManagedClass obj) { return obj.getSuperClass(); } @@ -297,8 +297,8 @@ LazyPythonClass doNative(PythonNativeClass obj, @TruffleBoundary public static LazyPythonClass doSlowPath(Object obj) { - if (obj instanceof ManagedPythonClass) { - return ((ManagedPythonClass) obj).getSuperClass(); + if (obj instanceof PythonManagedClass) { + return ((PythonManagedClass) obj).getSuperClass(); } else if (obj instanceof PythonBuiltinClassType) { return ((PythonBuiltinClassType) obj).getBase(); } else if (PGuards.isNativeClass(obj)) { @@ -324,7 +324,7 @@ public abstract static class GetSubclassesNode extends PNodeWithContext { public abstract Set execute(Object obj); @Specialization - Set doPythonClass(ManagedPythonClass obj) { + Set doPythonClass(PythonManagedClass obj) { return obj.getSubClasses(); } @@ -350,8 +350,8 @@ Set doNativeClass(PythonNativeClass obj, @TruffleBoundary public static Set doSlowPath(Object obj) { - if (obj instanceof ManagedPythonClass) { - return ((ManagedPythonClass) obj).getSubClasses(); + if (obj instanceof PythonManagedClass) { + return ((PythonManagedClass) obj).getSubClasses(); } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getSubClasses(); } else if (PGuards.isNativeClass(obj)) { @@ -448,7 +448,7 @@ public abstract static class GetBaseClassesNode extends PNodeWithContext { public abstract PythonAbstractClass[] execute(Object obj); @Specialization - PythonAbstractClass[] doPythonClass(ManagedPythonClass obj) { + PythonAbstractClass[] doPythonClass(PythonManagedClass obj) { return obj.getBaseClasses(); } @@ -476,8 +476,8 @@ PythonAbstractClass[] doNative(PythonNativeClass obj, @TruffleBoundary public static PythonAbstractClass[] doSlowPath(Object obj) { - if (obj instanceof ManagedPythonClass) { - return ((ManagedPythonClass) obj).getBaseClasses(); + if (obj instanceof PythonManagedClass) { + return ((PythonManagedClass) obj).getBaseClasses(); } else if (obj instanceof PythonBuiltinClassType) { return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getBaseClasses(); } else if (PGuards.isNativeClass(obj)) { @@ -520,7 +520,7 @@ public abstract static class IsSameTypeNode extends PNodeWithContext { public abstract boolean execute(Object left, Object right); @Specialization - boolean doManaged(ManagedPythonClass left, ManagedPythonClass right) { + boolean doManaged(PythonManagedClass left, PythonManagedClass right) { return left == right; } @@ -537,7 +537,7 @@ boolean doOther(@SuppressWarnings("unused") Object left, @SuppressWarnings("unus @TruffleBoundary public static boolean doSlowPath(Object left, Object right) { - if (left instanceof ManagedPythonClass && right instanceof ManagedPythonClass) { + if (left instanceof PythonManagedClass && right instanceof PythonManagedClass) { return left == right; } else if (left instanceof PythonAbstractNativeObject && right instanceof PythonAbstractNativeObject) { return CExtNodes.PointerCompareNode.create(__EQ__).execute((PythonAbstractNativeObject) left, (PythonAbstractNativeObject) right); @@ -557,7 +557,7 @@ public abstract static class GetSulongTypeNode extends Node { public abstract Object execute(PythonAbstractClass clazz); @Specialization - Object doInitialized(ManagedPythonClass clazz) { + Object doInitialized(PythonManagedClass clazz) { return clazz.getSulongType(); } @@ -568,8 +568,8 @@ Object doNative(@SuppressWarnings("unused") PythonNativeClass clazz) { @TruffleBoundary public static Object getSlowPath(PythonAbstractClass clazz) { - if (clazz instanceof ManagedPythonClass) { - return ((ManagedPythonClass) clazz).getSulongType(); + if (clazz instanceof PythonManagedClass) { + return ((PythonManagedClass) clazz).getSulongType(); } else if (PGuards.isNativeClass(clazz)) { return null; } @@ -578,8 +578,8 @@ public static Object getSlowPath(PythonAbstractClass clazz) { @TruffleBoundary public static void setSlowPath(PythonAbstractClass clazz, Object sulongType) { - if (clazz instanceof ManagedPythonClass) { - ((ManagedPythonClass) clazz).setSulongType(sulongType); + if (clazz instanceof PythonManagedClass) { + ((PythonManagedClass) clazz).setSulongType(sulongType); } else { throw new IllegalStateException("cannot set Sulong type for " + clazz.getClass().getName()); } @@ -673,7 +673,7 @@ public abstract static class IsTypeNode extends Node { public abstract boolean execute(Object obj); @Specialization - boolean doManagedClass(@SuppressWarnings("unused") ManagedPythonClass obj) { + boolean doManagedClass(@SuppressWarnings("unused") PythonManagedClass obj) { return true; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index 7f72e0f88d..ecf7aec322 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -45,7 +45,7 @@ import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; @@ -149,14 +149,14 @@ final static class PythonClassAssumptionPair { } } - protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(ManagedPythonClass klass) { + protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonManagedClass klass) { PythonAbstractClass[] mro = getMro(klass); Assumption attrAssumption = klass.createAttributeInMROFinalAssumption(key); for (int i = 0; i < mro.length; i++) { PythonAbstractClass clsObj = mro[i]; // TODO(fa): that's just a first approach and needs to be implemented properly - if (clsObj instanceof ManagedPythonClass) { - ManagedPythonClass cls = (ManagedPythonClass) clsObj; + if (clsObj instanceof PythonManagedClass) { + PythonManagedClass cls = (PythonManagedClass) clsObj; if (i > 0) { assert cls != klass : "MRO chain is incorrect: '" + klass + "' was found at position " + i; cls.addAttributeInMROFinalAssumption(key, attrAssumption); @@ -178,8 +178,8 @@ protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(ManagedPytho @Specialization(guards = {"klass == cachedKlass", "cachedClassInMROInfo != null"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = { "cachedClassInMROInfo.assumption"}) - protected Object lookupConstantMROCached(@SuppressWarnings("unused") ManagedPythonClass klass, - @Cached("klass") @SuppressWarnings("unused") ManagedPythonClass cachedKlass, + protected Object lookupConstantMROCached(@SuppressWarnings("unused") PythonManagedClass klass, + @Cached("klass") @SuppressWarnings("unused") PythonManagedClass cachedKlass, @Cached("findAttrClassAndAssumptionInMRO(cachedKlass)") PythonClassAssumptionPair cachedClassInMROInfo) { return cachedClassInMROInfo.value; } @@ -194,8 +194,8 @@ protected ReadAttributeFromObjectNode[] create(int size) { @Specialization(guards = {"klass == cachedKlass", "mroLength < 32"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = "lookupStable") @ExplodeLoop(kind = ExplodeLoop.LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN) - protected Object lookupConstantMRO(@SuppressWarnings("unused") ManagedPythonClass klass, - @Cached("klass") @SuppressWarnings("unused") ManagedPythonClass cachedKlass, + protected Object lookupConstantMRO(@SuppressWarnings("unused") PythonManagedClass klass, + @Cached("klass") @SuppressWarnings("unused") PythonManagedClass cachedKlass, @Cached("cachedKlass.getLookupStableAssumption()") @SuppressWarnings("unused") Assumption lookupStable, @Cached(value = "getMro(cachedKlass)", dimensions = 1) PythonAbstractClass[] mro, @Cached("mro.length") @SuppressWarnings("unused") int mroLength, @@ -211,7 +211,7 @@ protected Object lookupConstantMRO(@SuppressWarnings("unused") ManagedPythonClas } @Specialization(replaces = {"lookupConstantMROCached", "lookupConstantMRO"}) - protected Object lookup(ManagedPythonClass klass, + protected Object lookup(PythonManagedClass klass, @Cached("create()") GetMroNode getMroNode, @Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode) { return lookupSlow(klass, key, getMroNode, readAttrNode); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java index 42d187e12b..3fc936547a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java @@ -54,7 +54,7 @@ import com.oracle.graal.python.builtins.objects.method.PMethod; 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.type.ManagedPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.runtime.PythonOptions; import com.oracle.truffle.api.Assumption; @@ -90,16 +90,16 @@ public static WriteAttributeToObjectNode createForceType() { } protected boolean isAttrWritable(PythonObject self, Object key) { - if (isHiddenKey(key) || self instanceof ManagedPythonClass || self instanceof PFunction || self instanceof PMethod || self instanceof PythonModule || self instanceof PBaseException) { + if (isHiddenKey(key) || self instanceof PythonManagedClass || self instanceof PFunction || self instanceof PMethod || self instanceof PythonModule || self instanceof PBaseException) { return true; } return !exactBuiltinInstanceProfile.profileIsAnyBuiltinObject(self); } private void handlePythonClass(PythonObject object, Object key) { - if (isClassProfile.profile(object instanceof ManagedPythonClass)) { + if (isClassProfile.profile(object instanceof PythonManagedClass)) { if (key instanceof String) { - ((ManagedPythonClass) object).invalidateAttributeInMROFinalAssumptions((String) key); + ((PythonManagedClass) object).invalidateAttributeInMROFinalAssumptions((String) key); } } } From 1385f6104836962f3186c64b1b4141a5267477cb Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 15:35:20 +0100 Subject: [PATCH 094/202] Cleanup warnings. --- .../builtins/modules/WeakRefModuleBuiltins.java | 15 +++++---------- .../runtime/object/PythonObjectFactory.java | 3 +-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java index 693467a03a..d911060e18 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java @@ -50,36 +50,31 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.cext.CExtNodes; -import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetTypeMemberNode; +import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames; import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.dict.PDict; 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.referencetype.PReferenceType; import com.oracle.graal.python.builtins.objects.referencetype.PReferenceType.WeakRefStorage; -import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.PGuards; +import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; +import com.oracle.graal.python.nodes.object.GetLazyClassNode; +import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.runtime.AsyncHandler; import com.oracle.graal.python.runtime.PythonCore; import com.oracle.graal.python.runtime.exception.PythonErrorType; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.graal.python.nodes.object.GetLazyClassNode; -import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; -import com.oracle.graal.python.nodes.truffle.PythonTypes; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.object.HiddenKey; -import com.oracle.truffle.api.dsl.TypeSystemReference; @CoreFunctions(defineModule = "_weakref") public class WeakRefModuleBuiltins extends PythonBuiltins { @@ -171,7 +166,7 @@ public PReferenceType refType(LazyPythonClass cls, PythonAbstractNativeObject py } @Fallback - public PReferenceType refType(Object cls, Object object, Object callback) { + public PReferenceType refType(@SuppressWarnings("unused") Object cls, Object object, @SuppressWarnings("unused") Object callback) { throw raise(PythonErrorType.TypeError, "cannot create weak reference to '%p' object", object); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index d97e8107d9..b5cdac55b1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -33,7 +33,6 @@ import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.PythonBuiltinClassType; -import com.oracle.graal.python.builtins.objects.PythonAbstractObject; import com.oracle.graal.python.builtins.objects.array.PArray; import com.oracle.graal.python.builtins.objects.bytes.PByteArray; import com.oracle.graal.python.builtins.objects.bytes.PBytes; @@ -109,8 +108,8 @@ import com.oracle.graal.python.builtins.objects.thread.PThread; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.zipimporter.PZipImporter; import com.oracle.graal.python.parser.ExecutionCellSlots; From 355b41f24fa2bd470de057d70bbf83dcaab030c6 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 16:02:34 +0100 Subject: [PATCH 095/202] Fix copyrights. --- .../src/moduleobject.c | 2 +- .../src/typeobject.c | 2 +- .../builtins/modules/ArrayModuleBuiltins.java | 2 +- .../builtins/modules/ImpModuleBuiltins.java | 2 +- .../modules/RandomModuleBuiltins.java | 2 +- .../modules/ThreadModuleBuiltins.java | 2 +- .../modules/ZipImportModuleBuiltins.java | 2 +- .../objects/cext/NativeMemberNames.java | 2 +- .../builtins/objects/cext/NativeWrappers.java | 2 +- .../builtins/objects/cext/PThreadStateMR.java | 2 +- .../objects/cext/PyBufferProcsWrapper.java | 2 +- .../objects/cext/PyBufferProcsWrapperMR.java | 2 +- .../objects/cext/PyNumberMethodsWrapper.java | 2 +- .../cext/PyNumberMethodsWrapperMR.java | 2 +- .../cext/PySequenceMethodsWrapper.java | 2 +- .../cext/PySequenceMethodsWrapperMR.java | 2 +- .../builtins/objects/dict/DictBuiltins.java | 2 +- .../objects/enumerate/PEnumerate.java | 2 +- .../function/BuiltinFunctionBuiltins.java | 2 +- .../builtins/objects/iterator/PZip.java | 2 +- .../builtins/objects/random/PRandom.java | 2 +- .../reversed/PSequenceReverseIterator.java | 2 +- .../reversed/PStringReverseIterator.java | 2 +- .../objects/type/LazyPythonClass.java | 2 +- .../builtins/objects/type/MROMergeState.java | 2 +- .../objects/type/PythonAbstractClass.java | 40 ++++++++++++++ .../objects/type/PythonManagedClass.java | 25 +++++++++ .../oracle/graal/python/nodes/PGuards.java | 2 +- .../nodes/attributes/ObjectAttributeNode.java | 2 +- .../ReadAttributeFromDynamicObjectNode.java | 2 +- .../ReadAttributeFromObjectNode.java | 2 +- .../nodes/attributes/SetAttributeNode.java | 2 +- .../WriteAttributeToObjectNode.java | 2 +- .../special/LookupAndCallTernaryNode.java | 2 +- .../control/TopLevelExceptionHandler.java | 2 +- .../nodes/object/IsBuiltinClassProfile.java | 2 +- .../python/nodes/statement/WithNode.java | 2 +- .../python/nodes/subscript/SetItemNode.java | 2 +- .../nodes/truffle/PythonArithmeticTypes.java | 2 +- .../python/nodes/truffle/PythonTypes.java | 2 +- .../formatting/ErrorMessageFormatter.java | 2 +- .../sequence/storage/MroSequenceStorage.java | 53 ++++++++++++------- mx.graalpython/copyrights/overrides | 2 +- 43 files changed, 139 insertions(+), 59 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/moduleobject.c b/graalpython/com.oracle.graal.python.cext/src/moduleobject.c index be4dfda6dc..080282f142 100644 --- a/graalpython/com.oracle.graal.python.cext/src/moduleobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/moduleobject.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python.cext/src/typeobject.c b/graalpython/com.oracle.graal.python.cext/src/typeobject.c index 94fc410037..b3443c071e 100644 --- a/graalpython/com.oracle.graal.python.cext/src/typeobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/typeobject.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java index df83aa6937..97541bb61c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java index 1e63a76a34..181ef06674 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/RandomModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/RandomModuleBuiltins.java index 420f8fc236..2f4ec1d50a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/RandomModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/RandomModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java index 9b044c226e..09247948d9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZipImportModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZipImportModuleBuiltins.java index 345d3d8515..150cd969f0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZipImportModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZipImportModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java index 823c34accf..b821e55dd9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java index 89472e9bfe..0b3e067cb9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeWrappers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java index bb997a8f8e..1c106be8ef 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadStateMR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java index 783ae6cae7..79a61f223e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java index ed43f33def..ac384895b2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyBufferProcsWrapperMR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java index 0102be1c99..1f73e4642d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java index e6aa99353e..13e7606807 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyNumberMethodsWrapperMR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java index b58d3e0806..fd769b70c8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java index a57c92eb0b..edf7a2335d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceMethodsWrapperMR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java index acbcb3474e..cfb5c94949 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/enumerate/PEnumerate.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/enumerate/PEnumerate.java index 2689e275b5..e18d088a79 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/enumerate/PEnumerate.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/enumerate/PEnumerate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java index 61556fd023..0b9b7b2573 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/BuiltinFunctionBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PZip.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PZip.java index dc163a55ed..a0e295eb83 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PZip.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PZip.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/PRandom.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/PRandom.java index 0c4813b785..dd9d1b8eb5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/PRandom.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/random/PRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PSequenceReverseIterator.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PSequenceReverseIterator.java index f716c66a9e..3f451ae17a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PSequenceReverseIterator.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PSequenceReverseIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PStringReverseIterator.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PStringReverseIterator.java index 1e1006294d..73c9117734 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PStringReverseIterator.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/reversed/PStringReverseIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java index 675aafd300..18fad54529 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java index c42eab18ca..59f00841cf 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonAbstractClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonAbstractClass.java index 21293eb6f1..f0bdbb52cb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonAbstractClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonAbstractClass.java @@ -1,3 +1,43 @@ +/* + * Copyright (c) 2019, 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 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ package com.oracle.graal.python.builtins.objects.type; public interface PythonAbstractClass extends LazyPythonClass { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java index be6226801e..27572fd52f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. + * Copyright (c) 2013, Regents of the University of California + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.oracle.graal.python.builtins.objects.type; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DOC__; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java index bf88d5711d..1627082475 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ObjectAttributeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ObjectAttributeNode.java index 57cefdad5c..877304c26a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ObjectAttributeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ObjectAttributeNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromDynamicObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromDynamicObjectNode.java index 475b7d8208..7de390d91f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromDynamicObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromDynamicObjectNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java index 2d4d89d0b4..0e159dfd23 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromObjectNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/SetAttributeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/SetAttributeNode.java index 0c8f1c8010..07186ccc29 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/SetAttributeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/SetAttributeNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java index 3fc936547a..6db1169710 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallTernaryNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallTernaryNode.java index 4b55b19e8e..ef93fd08fa 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallTernaryNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallTernaryNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/TopLevelExceptionHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/TopLevelExceptionHandler.java index 96e6ea3db3..9d6934bada 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/TopLevelExceptionHandler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/TopLevelExceptionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/IsBuiltinClassProfile.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/IsBuiltinClassProfile.java index d705c6d32c..34bac03df8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/IsBuiltinClassProfile.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/IsBuiltinClassProfile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java index b45795a6f0..e9e4cd56bc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/SetItemNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/SetItemNode.java index 2531fdedb5..f5f3844743 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/SetItemNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/SetItemNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonArithmeticTypes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonArithmeticTypes.java index 74b64c0ee0..37c3ca2791 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonArithmeticTypes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonArithmeticTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypes.java index 1f466c2cdc..7a11e6446b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/ErrorMessageFormatter.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/ErrorMessageFormatter.java index 4e69a26e07..837c98c3a3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/ErrorMessageFormatter.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/ErrorMessageFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java index 6f4a72f702..dc13255a92 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java @@ -1,27 +1,42 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. - * Copyright (c) 2013, Regents of the University of California + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * All rights reserved. + * The Universal Permissive License (UPL), Version 1.0 * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other materials provided - * with the distribution. + * (a) the Software, and * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ package com.oracle.graal.python.runtime.sequence.storage; diff --git a/mx.graalpython/copyrights/overrides b/mx.graalpython/copyrights/overrides index 99b3462024..7c1949ba73 100644 --- a/mx.graalpython/copyrights/overrides +++ b/mx.graalpython/copyrights/overrides @@ -358,6 +358,7 @@ graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/MROMergeState.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonBuiltinClass.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java,zippy.copyright +graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/zipimporter/PZipImporter.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/zipimporter/ZipImporterBuiltins.java,zippy.copyright @@ -461,7 +462,6 @@ graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/ graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/subscript/SliceLiteralNode.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonArithmeticTypes.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypes.java,zippy.copyright -graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/truffle/PythonTypesUtil.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/AssignmentTranslator.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/CellFrameSlotSupplier.java,zippy.copyright graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/CellSlots.java,zippy.copyright From 3f4d72a44d1046f92d091f0e13f38f26d4001a12 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 21:47:19 +0100 Subject: [PATCH 096/202] Move 'attributeInMroFinal' assumptions to 'MroSequenceStorage'. --- .../src/typeobject.c | 2 +- .../builtins/modules/TruffleCextBuiltins.java | 13 +- .../objects/common/DynamicObjectStorage.java | 38 +- .../objects/common/HashingStorageNodes.java | 371 ++++++++---------- .../objects/type/PythonManagedClass.java | 84 +--- .../builtins/objects/type/TypeNodes.java | 53 ++- .../attributes/LookupAttributeInMRONode.java | 92 ++--- .../WriteAttributeToObjectNode.java | 4 +- .../sequence/storage/MroSequenceStorage.java | 122 +++++- 9 files changed, 415 insertions(+), 364 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/typeobject.c b/graalpython/com.oracle.graal.python.cext/src/typeobject.c index b3443c071e..cc0db093e9 100644 --- a/graalpython/com.oracle.graal.python.cext/src/typeobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/typeobject.c @@ -383,7 +383,7 @@ int PyType_Ready(PyTypeObject* cls) { } /* initialize mro */ - cls->tp_mro = UPCALL_CEXT_O(_jls_PyTruffle_Compute_Mro, cls); + cls->tp_mro = UPCALL_CEXT_O(_jls_PyTruffle_Compute_Mro, cls, polyglot_from_string(cls->tp_name, SRC_CS)); /* Inherit special flags from dominant base */ if (cls->tp_base != NULL) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index b33f289d84..2aa8ee2a77 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -118,11 +118,11 @@ import com.oracle.graal.python.builtins.objects.str.PString; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; import com.oracle.graal.python.builtins.objects.tuple.PTuple; -import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; @@ -2312,14 +2312,15 @@ int add(Object self, @SuppressWarnings("unused") Object o) { } - @Builtin(name = "PyTruffle_Compute_Mro", fixedNumOfPositionalArgs = 1) + @Builtin(name = "PyTruffle_Compute_Mro", fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - public abstract static class PyTruffle_Compute_Mro extends PythonUnaryBuiltinNode { + @TypeSystemReference(PythonArithmeticTypes.class) + public abstract static class PyTruffle_Compute_Mro extends PythonBinaryBuiltinNode { @Specialization - Object doIt(PythonNativeObject self) { + Object doIt(PythonNativeObject self, String className) { PythonAbstractClass[] doSlowPath = TypeNodes.ComputeMroNode.doSlowPath(PythonNativeClass.cast(self)); - return factory().createTuple(new MroSequenceStorage(doSlowPath)); + return factory().createTuple(new MroSequenceStorage(className, doSlowPath)); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java index 158ec3faaf..5416543db7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java @@ -42,6 +42,7 @@ import java.util.ArrayList; +import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.object.DynamicObject; @@ -143,7 +144,7 @@ public DynamicObject getStore() { return store; } - public static class FastDictStorage extends DynamicObjectStorage { + public static final class FastDictStorage extends DynamicObjectStorage { public FastDictStorage() { } @@ -159,7 +160,7 @@ public HashingStorage copy(Equivalence eq) { } } - public static class PythonObjectDictStorage extends DynamicObjectStorage { + public static final class PythonObjectDictStorage extends DynamicObjectStorage { private final Assumption dictUnsetOrSameAsStorage; public PythonObjectDictStorage(DynamicObject store) { @@ -179,11 +180,40 @@ public Assumption getDictUnsetOrSameAsStorage() { @TruffleBoundary public HashingStorage copy(Equivalence eq) { assert eq == HashingStorage.DEFAULT_EQIVALENCE; - return new PythonObjectDictStorage(getStore().copy(getStore().getShape())); + return new FastDictStorage(getStore().copy(getStore().getShape())); + } + } + + /** + * Special storage that is used in the type dict (i.e. {@code tp_dict}) of native types. Writing + * to this storage will cause the appropriate attribute final assumptions to be + * invalidated. Therefore, this storage links to the {@link MroSequenceStorage} of the type. + */ + public static final class PythonNativeObjectDictStorage extends DynamicObjectStorage { + private final MroSequenceStorage mro; + + public PythonNativeObjectDictStorage(DynamicObject store, MroSequenceStorage mro) { + super(store); + this.mro = mro; + } + + public MroSequenceStorage getMro() { + return mro; + } + + public void invalidateAttributeInMROFinalAssumptions(String name) { + mro.invalidateAttributeInMROFinalAssumptions(name); + } + + @Override + @TruffleBoundary + public HashingStorage copy(Equivalence eq) { + assert eq == HashingStorage.DEFAULT_EQIVALENCE; + return new FastDictStorage(getStore().copy(getStore().getShape())); } } - public static class PythonObjectHybridDictStorage extends DynamicObjectStorage { + public static final class PythonObjectHybridDictStorage extends DynamicObjectStorage { private final EconomicMapStorage nonAttributesStorage; public PythonObjectHybridDictStorage(PythonObjectDictStorage storage) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java index 746d45fe5a..5a92836d47 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java @@ -49,8 +49,10 @@ import java.util.ArrayList; import java.util.Arrays; +import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage.FastDictStorage; +import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage.PythonNativeObjectDictStorage; import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage.PythonObjectDictStorage; import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage.PythonObjectHybridDictStorage; import com.oracle.graal.python.builtins.objects.common.HashingStorage.Equivalence; @@ -59,9 +61,11 @@ import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.CopyNodeGen; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.DelItemNodeGen; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.DiffNodeGen; +import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.DynamicObjectSetItemNodeGen; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.EqualsNodeGen; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.GetItemNodeGen; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.InitNodeGen; +import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.InvalidateMroNodeGen; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.KeysEqualsNodeGen; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.KeysIsSubsetNodeGen; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.LenNodeGen; @@ -87,6 +91,7 @@ import com.oracle.graal.python.nodes.expression.CastToBooleanNode; import com.oracle.graal.python.nodes.object.GetLazyClassNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; +import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.exception.PythonErrorType; import com.oracle.graal.python.runtime.sequence.PSequence; @@ -100,6 +105,7 @@ import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.object.DynamicObject; @@ -182,6 +188,8 @@ abstract static class DictStorageBaseNode extends PNodeWithContext { @Child private IsHashableNode isHashableNode; @Child private Equivalence equivalenceNode; + @CompilationFinal private IsBuiltinClassProfile isBuiltinClassProfile; + protected Equivalence getEquivalence() { if (equivalenceNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -224,7 +232,11 @@ protected PException unhashable(Object key) { } protected boolean wrappedString(PString s) { - return PGuards.cannotBeOverridden(getClass(s)); + if (isBuiltinClassProfile == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isBuiltinClassProfile = IsBuiltinClassProfile.create(); + } + return isBuiltinClassProfile.profileClass(getClass(s), PythonBuiltinClassType.PString); } protected EconomicMapStorage switchToEconomicMap(HashingStorage storage) { @@ -258,6 +270,10 @@ protected static Location lookupLocation(Shape shape, Object name) { } return null; } + + protected static boolean exceedsLimit(DynamicObjectStorage storage) { + return storage instanceof FastDictStorage && storage.length() + 1 >= DynamicObjectStorage.SIZE_THRESHOLD; + } } @ImportStatic(SpecialMethodNames.class) @@ -616,20 +632,52 @@ public static ContainsValueNode create() { } } - public abstract static class SetItemNode extends DictStorageBaseNode { + abstract static class SetItemBaseNode extends DictStorageBaseNode { + + /** + * Try to find the given property in the shape. Also returns null when the value cannot be + * store into the location. + */ + protected static Location lookupLocation(Shape shape, Object name, Object value) { + Location location = DictStorageBaseNode.lookupLocation(shape, name); + if (location == null || !location.canSet(value)) { + /* Existing property has an incompatible type, so a shape change is necessary. */ + return null; + } + + return location; + } + + protected static Shape defineProperty(Shape oldShape, Object name, Object value) { + return oldShape.defineProperty(name, value, 0); + } + + protected static boolean canSet(Location location, Object value) { + return location.canSet(value); + } + + protected static boolean canStore(Location location, Object value) { + return location.canStore(value); + } + + } + + public abstract static class SetItemNode extends SetItemBaseNode { + + @Child private DynamicObjectSetItemNode dynamicObjectSetItemNode; public abstract HashingStorage execute(HashingStorage storage, Object key, Object value); @Specialization protected HashingStorage doEmptyStorage(EmptyStorage storage, String key, Object value) { // immediately replace storage since empty storage is immutable - return doDynamicObjectUpdateShape(switchToFastDictStorage(storage), key, value); + return ensureDynamicObjectSetItemNode().execute(switchToFastDictStorage(storage), key, value); } @Specialization(guards = "wrappedString(key)") protected HashingStorage doEmptyStorage(EmptyStorage storage, PString key, Object value) { // immediately replace storage since empty storage is immutable - return doDynamicObjectUpdateShape(switchToFastDictStorage(storage), key.getValue(), value); + return ensureDynamicObjectSetItemNode().execute(switchToFastDictStorage(storage), key.getValue(), value); } @Specialization(guards = {"!isJavaString(key)", "isHashable(key)"}) @@ -640,187 +688,14 @@ protected HashingStorage doEmptyStorage(@SuppressWarnings("unused") EmptyStorage return newStorage; } - /** - * Polymorphic inline cache for writing a property that already exists (no shape change is - * necessary). - */ - @Specialization(limit = "3", // - guards = { - "cachedName.equals(name)", - "shapeCheck(shape, storage.getStore())", - "location != null", - "canSet(location, value)" - }, // - assumptions = { - "shape.getValidAssumption()" - }) - protected static HashingStorage doDynamicObjectExistingCached(DynamicObjectStorage storage, @SuppressWarnings("unused") String name, - Object value, - @SuppressWarnings("unused") @Cached("name") String cachedName, - @Cached("lookupShape(storage.getStore())") Shape shape, - @Cached("lookupLocation(shape, name, value)") Location location) { - try { - location.set(storage.getStore(), value, shape); - return storage; - } catch (IncompatibleLocationException | FinalLocationException ex) { - /* Our guards ensure that the value can be stored, so this cannot happen. */ - throw new IllegalStateException(ex); - } - } - - /** - * Polymorphic inline cache for writing a property that does not exist yet (shape change is - * necessary). - */ - @Specialization(limit = "3", // - guards = { - "cachedName.equals(name)", - "shapeCheck(oldShape, storage.getStore())", - "oldLocation == null", - "canStore(newLocation, value)" - }, // - assumptions = { - "oldShape.getValidAssumption()", - "newShape.getValidAssumption()" - }) - @SuppressWarnings("unused") - protected static HashingStorage doDynamicObjectNewCached(DynamicObjectStorage storage, String name, Object value, - @Cached("name") String cachedName, - @Cached("lookupShape(storage.getStore())") Shape oldShape, - @Cached("lookupLocation(oldShape, name, value)") Location oldLocation, - @Cached("defineProperty(oldShape, name, value)") Shape newShape, - @Cached("lookupLocation(newShape, name)") Location newLocation) { - try { - newLocation.set(storage.getStore(), value, oldShape, newShape); - return storage; - } catch (IncompatibleLocationException ex) { - /* Our guards ensure that the value can be stored, so this cannot happen. */ - throw new IllegalStateException(ex); - } - } - - /** - * The generic case is used if the number of shapes accessed overflows the limit of the - * polymorphic inline cache. - */ - @TruffleBoundary - @Specialization(replaces = {"doDynamicObjectExistingCached", "doDynamicObjectNewCached"}, guards = {"storage.getStore().getShape().isValid()", "!exceedsLimit(storage)"}) - protected static HashingStorage doDynamicObjectUncached(DynamicObjectStorage storage, String name, Object value) { - storage.getStore().define(name, value); - return storage; - } - - @Specialization(guards = {"storage.getStore().getShape().isValid()", "exceedsLimit(storage)"}) - protected HashingStorage doDynamicObjectGeneralize(FastDictStorage storage, String name, Object value) { - HashingStorage newStorage = switchToEconomicMap(storage); - newStorage.setItem(name, value, getEquivalence()); - return newStorage; - } - - @TruffleBoundary - @Specialization(guards = {"!storage.getStore().getShape().isValid()"}) - protected HashingStorage doDynamicObjectUpdateShape(DynamicObjectStorage storage, String name, Object value) { - storage.getStore().updateShape(); - return doDynamicObjectUncached(storage, name, value); - } - - /** - * Polymorphic inline cache for writing a property that already exists (no shape change is - * necessary). - */ - @Specialization(limit = "3", // - guards = { - "wrappedString(name)", - "cachedName.equals(name.getValue())", - "shapeCheck(shape, storage.getStore())", - "location != null", - "canSet(location, value)" - }, // - assumptions = { - "shape.getValidAssumption()" - }) - @SuppressWarnings("unused") - protected static HashingStorage doDynamicObjectExistingPStringCached(DynamicObjectStorage storage, PString name, - Object value, - @Cached("name.getValue()") String cachedName, - @Cached("lookupShape(storage.getStore())") Shape shape, - @Cached("lookupLocation(shape, cachedName, value)") Location location) { - try { - location.set(storage.getStore(), value, shape); - return storage; - } catch (IncompatibleLocationException | FinalLocationException ex) { - /* Our guards ensure that the value can be stored, so this cannot happen. */ - throw new IllegalStateException(ex); - } - } - - /** - * Polymorphic inline cache for writing a property that does not exist yet (shape change is - * necessary). - */ - @Specialization(limit = "3", // - guards = { - "cachedName.equals(name.getValue())", - "shapeCheck(oldShape, storage.getStore())", - "oldLocation == null", - "canStore(newLocation, value)" - }, // - assumptions = { - "oldShape.getValidAssumption()", - "newShape.getValidAssumption()" - }) - @SuppressWarnings("unused") - protected static HashingStorage doDynamicObjectNewPStringCached(DynamicObjectStorage storage, PString name, Object value, - @Cached("name.getValue()") String cachedName, - @Cached("lookupShape(storage.getStore())") Shape oldShape, - @Cached("lookupLocation(oldShape, cachedName, value)") Location oldLocation, - @Cached("defineProperty(oldShape, cachedName, value)") Shape newShape, - @Cached("lookupLocation(newShape, cachedName)") Location newLocation) { - try { - newLocation.set(storage.getStore(), value, oldShape, newShape); - return storage; - } catch (IncompatibleLocationException ex) { - /* Our guards ensure that the value can be stored, so this cannot happen. */ - throw new IllegalStateException(ex); - } - } - - /** - * The generic case is used if the number of shapes accessed overflows the limit of the - * polymorphic inline cache. - */ - @TruffleBoundary - @Specialization(guards = { - "wrappedString(name)", - "storage.getStore().getShape().isValid()", - "!exceedsLimit(storage)" - }, // - replaces = { - "doDynamicObjectExistingPStringCached", - "doDynamicObjectNewPStringCached" - }) - protected static HashingStorage doDynamicObjectPStringUncached(DynamicObjectStorage storage, PString name, Object value) { - storage.getStore().define(name.getValue(), value); - return storage; - } - - @Specialization(guards = {"wrappedString(name)", "storage.getStore().getShape().isValid()", "exceedsLimit(storage)"}) - protected HashingStorage doDynamicObjectPStringGeneralize(DynamicObjectStorage storage, PString name, Object value) { - HashingStorage newStorage = switchToEconomicMap(storage); - newStorage.setItem(name.getValue(), value, getEquivalence()); - return newStorage; + @Specialization + protected HashingStorage doDynamicObject(DynamicObjectStorage storage, String key, Object value) { + return ensureDynamicObjectSetItemNode().execute(storage, key, value); } - @TruffleBoundary - @Specialization(guards = {"wrappedString(name)", "!storage.getStore().getShape().isValid()"}) - protected HashingStorage doDynamicObjectPStringUpdateShape(DynamicObjectStorage storage, PString name, Object value) { - /* - * Slow path that we do not handle in compiled code. But no need to invalidate compiled - * code. - */ - CompilerDirectives.transferToInterpreter(); - storage.getStore().updateShape(); - return doDynamicObjectPStringUncached(storage, name, value); + @Specialization(guards = "wrappedString(key)") + protected HashingStorage doDynamicObjectPString(DynamicObjectStorage storage, PString key, Object value) { + return ensureDynamicObjectSetItemNode().execute(storage, key.getValue(), value); } @Specialization @@ -899,38 +774,128 @@ protected HashingStorage doUnhashable(HashingStorage storage, Object key, Object throw unhashable(key); } - /** - * Try to find the given property in the shape. Also returns null when the value cannot be - * store into the location. - */ - protected static Location lookupLocation(Shape shape, Object name, Object value) { - Location location = DictStorageBaseNode.lookupLocation(shape, name); - if (location == null || !location.canSet(value)) { - /* Existing property has an incompatible type, so a shape change is necessary. */ - return null; + private DynamicObjectSetItemNode ensureDynamicObjectSetItemNode() { + if (dynamicObjectSetItemNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + dynamicObjectSetItemNode = insert(DynamicObjectSetItemNode.create()); } + return dynamicObjectSetItemNode; + } - return location; + public static SetItemNode create() { + return SetItemNodeGen.create(); } + } - protected static Shape defineProperty(Shape oldShape, Object name, Object value) { - return oldShape.defineProperty(name, value, 0); + protected abstract static class InvalidateMroNode extends Node { + public abstract void execute(DynamicObjectStorage s, String key, Object val); + + @Specialization + void doPythonNativeObjectDictStorage(PythonNativeObjectDictStorage storage, String key, @SuppressWarnings("unused") Object val) { + storage.invalidateAttributeInMROFinalAssumptions(key); } - protected static boolean canSet(Location location, Object value) { - return location.canSet(value); + @Fallback + @SuppressWarnings("unused") + void doPythonNativeObjectDictStorage(DynamicObjectStorage storage, String key, Object val) { + // do nothing } - protected static boolean canStore(Location location, Object value) { - return location.canStore(value); + public static InvalidateMroNode create() { + return InvalidateMroNodeGen.create(); } + } - protected static boolean exceedsLimit(DynamicObjectStorage storage) { - return storage instanceof FastDictStorage && storage.length() + 1 >= DynamicObjectStorage.SIZE_THRESHOLD; + @TypeSystemReference(PythonArithmeticTypes.class) + abstract static class DynamicObjectSetItemNode extends SetItemBaseNode { + + @Child private InvalidateMroNode actionNode = InvalidateMroNode.create(); + + public abstract HashingStorage execute(DynamicObjectStorage s, Object key, Object val); + + // write to existing property; no shape change + @Specialization(limit = "3", // + guards = { + "cachedName.equals(name)", + "shapeCheck(shape, storage.getStore())", + "location != null", + "canSet(location, value)" + }, // + assumptions = { + "shape.getValidAssumption()" + }) + protected HashingStorage doDynamicObjectExistingCached(DynamicObjectStorage storage, @SuppressWarnings("unused") String name, + Object value, + @SuppressWarnings("unused") @Cached("name") String cachedName, + @Cached("lookupShape(storage.getStore())") Shape shape, + @Cached("lookupLocation(shape, name, value)") Location location) { + try { + location.set(storage.getStore(), value, shape); + actionNode.execute(storage, name, value); + return storage; + } catch (IncompatibleLocationException | FinalLocationException ex) { + /* Our guards ensure that the value can be stored, so this cannot happen. */ + throw new IllegalStateException(ex); + } } - public static SetItemNode create() { - return SetItemNodeGen.create(); + // add new property; shape change + @Specialization(limit = "3", // + guards = { + "cachedName.equals(name)", + "shapeCheck(oldShape, storage.getStore())", + "oldLocation == null", + "canStore(newLocation, value)" + }, // + assumptions = { + "oldShape.getValidAssumption()", + "newShape.getValidAssumption()" + }) + @SuppressWarnings("unused") + protected HashingStorage doDynamicObjectNewCached(DynamicObjectStorage storage, String name, Object value, + @Cached("name") String cachedName, + @Cached("lookupShape(storage.getStore())") Shape oldShape, + @Cached("lookupLocation(oldShape, name, value)") Location oldLocation, + @Cached("defineProperty(oldShape, name, value)") Shape newShape, + @Cached("lookupLocation(newShape, name)") Location newLocation) { + try { + newLocation.set(storage.getStore(), value, oldShape, newShape); + actionNode.execute(storage, name, value); + return storage; + } catch (IncompatibleLocationException ex) { + /* Our guards ensure that the value can be stored, so this cannot happen. */ + throw new IllegalStateException(ex); + } + } + + /** + * The generic case is used if the number of shapes accessed overflows the limit of the + * polymorphic inline cache. + */ + @TruffleBoundary + @Specialization(replaces = {"doDynamicObjectExistingCached", "doDynamicObjectNewCached"}, guards = {"storage.getStore().getShape().isValid()", "!exceedsLimit(storage)"}) + protected HashingStorage doDynamicObjectUncached(DynamicObjectStorage storage, String name, Object value) { + storage.getStore().define(name, value); + actionNode.execute(storage, name, value); + return storage; + } + + @Specialization(guards = {"storage.getStore().getShape().isValid()", "exceedsLimit(storage)"}) + protected HashingStorage doDynamicObjectGeneralize(FastDictStorage storage, String name, Object value) { + HashingStorage newStorage = switchToEconomicMap(storage); + newStorage.setItem(name, value, getEquivalence()); + return newStorage; + } + + @TruffleBoundary + @Specialization(guards = {"!storage.getStore().getShape().isValid()"}) + protected HashingStorage doDynamicObjectUpdateShape(DynamicObjectStorage storage, String name, Object value) { + storage.getStore().updateShape(); + return doDynamicObjectUncached(storage, name, value); + } + + public static DynamicObjectSetItemNode create() { + return DynamicObjectSetItemNodeGen.create(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java index 27572fd52f..d9d6450cb0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java @@ -29,11 +29,7 @@ import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__; import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__; -import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.Set; import java.util.WeakHashMap; @@ -44,30 +40,21 @@ import com.oracle.graal.python.builtins.objects.type.TypeNodes.ComputeMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode; import com.oracle.graal.python.nodes.PGuards; +import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.object.Shape; -import com.oracle.truffle.api.utilities.CyclicAssumption; public abstract class PythonManagedClass extends PythonObject implements PythonAbstractClass { private final String className; @CompilationFinal(dimensions = 1) private PythonAbstractClass[] baseClasses; - @CompilationFinal(dimensions = 1) private PythonAbstractClass[] methodResolutionOrder; +// @CompilationFinal(dimensions = 1) private PythonAbstractClass[] methodResolutionOrder; - /** - * This assumption will be invalidated whenever the mro changes. - */ - private final CyclicAssumption lookupStableAssumption; - /** - * These assumptions will be invalidated whenever the value of the given slot changes. All - * assumptions will be invalidated if the mro changes. - */ - private final Map> attributesInMROFinalAssumptions = new HashMap<>(); + private final MroSequenceStorage methodResolutionOrder; private final Set subClasses = Collections.newSetFromMap(new WeakHashMap()); private final Shape instanceShape; @@ -82,6 +69,8 @@ public PythonManagedClass(LazyPythonClass typeClass, String name, Shape instance super(typeClass, PythonLanguage.freshShape() /* do not inherit layout from the TypeClass */); this.className = name; + this.methodResolutionOrder = new MroSequenceStorage(name, 0); + if (baseClasses.length == 1 && baseClasses[0] == null) { this.baseClasses = new PythonAbstractClass[]{}; } else { @@ -89,10 +78,9 @@ public PythonManagedClass(LazyPythonClass typeClass, String name, Shape instance } this.flags = new FlagsContainer(getSuperClass()); - this.lookupStableAssumption = new CyclicAssumption(className); // Compute MRO - this.methodResolutionOrder = ComputeMroNode.doSlowPath(this); + this.methodResolutionOrder.setInternalArrayObject(ComputeMroNode.doSlowPath(this)); computeNeedsNativeAllocation(); setAttribute(__NAME__, getBaseName(name)); @@ -111,42 +99,7 @@ private static String getBaseName(String qname) { } public Assumption getLookupStableAssumption() { - return lookupStableAssumption.getAssumption(); - } - - public Assumption createAttributeInMROFinalAssumption(String name) { - CompilerAsserts.neverPartOfCompilation(); - List attrAssumptions = attributesInMROFinalAssumptions.getOrDefault(name, null); - if (attrAssumptions == null) { - attrAssumptions = new ArrayList<>(); - attributesInMROFinalAssumptions.put(name, attrAssumptions); - } - - Assumption assumption = Truffle.getRuntime().createAssumption(name.toString()); - attrAssumptions.add(assumption); - return assumption; - } - - public void addAttributeInMROFinalAssumption(String name, Assumption assumption) { - CompilerAsserts.neverPartOfCompilation(); - List attrAssumptions = attributesInMROFinalAssumptions.getOrDefault(name, null); - if (attrAssumptions == null) { - attrAssumptions = new ArrayList<>(); - attributesInMROFinalAssumptions.put(name, attrAssumptions); - } - - attrAssumptions.add(assumption); - } - - @TruffleBoundary - public void invalidateAttributeInMROFinalAssumptions(String name) { - List assumptions = attributesInMROFinalAssumptions.getOrDefault(name, new ArrayList<>()); - if (!assumptions.isEmpty()) { - String message = className + "." + name; - for (Assumption assumption : assumptions) { - assumption.invalidate(message); - } - } + return methodResolutionOrder.getLookupStableAssumption(); } /** @@ -154,12 +107,7 @@ public void invalidateAttributeInMROFinalAssumptions(String name) { */ public void lookupChanged() { CompilerAsserts.neverPartOfCompilation(); - for (List list : attributesInMROFinalAssumptions.values()) { - for (Assumption assumption : list) { - assumption.invalidate(); - } - } - lookupStableAssumption.invalidate(); + methodResolutionOrder.lookupChanged(); for (PythonAbstractClass subclass : getSubClasses()) { if (subclass != null) { subclass.lookupChanged(); @@ -175,7 +123,7 @@ PythonAbstractClass getSuperClass() { return getBaseClasses().length > 0 ? getBaseClasses()[0] : null; } - PythonAbstractClass[] getMethodResolutionOrder() { + MroSequenceStorage getMethodResolutionOrder() { return methodResolutionOrder; } @@ -184,7 +132,7 @@ String getName() { } private void computeNeedsNativeAllocation() { - for (PythonAbstractClass cls : getMethodResolutionOrder()) { + for (PythonAbstractClass cls : getMethodResolutionOrder().getInternalClassArray()) { if (PGuards.isNativeClass(cls)) { needsNativeAllocation = true; return; @@ -196,10 +144,16 @@ private void computeNeedsNativeAllocation() { @Override @TruffleBoundary public void setAttribute(Object key, Object value) { + invalidateFinalAttribute(key); + super.setAttribute(key, value); + } + + @TruffleBoundary + public void invalidateFinalAttribute(Object key) { + CompilerAsserts.neverPartOfCompilation(); if (key instanceof String) { - invalidateAttributeInMROFinalAssumptions((String) key); + methodResolutionOrder.invalidateAttributeInMROFinalAssumptions((String) key); } - super.setAttribute(key, value); } /** @@ -219,7 +173,7 @@ private void unsafeSetSuperClass(PythonAbstractClass... newBaseClasses) { GetSubclassesNode.doSlowPath(base).add(this); } } - this.methodResolutionOrder = ComputeMroNode.doSlowPath(this); + this.methodResolutionOrder.setInternalArrayObject(ComputeMroNode.doSlowPath(this)); } final Set getSubClasses() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index ccdeaea4ce..83a3227c57 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -64,7 +64,7 @@ import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.PythonManagedClass.FlagsContainer; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetBaseClassesNodeGen; -import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroStorageNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetNameNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSubclassesNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSulongTypeNodeGen; @@ -172,36 +172,60 @@ public static GetTypeFlagsNode create() { } } + public static class GetMroNode extends Node { + @Child private GetMroStorageNode getMroStorageNode; + + public PythonAbstractClass[] execute(Object obj) { + if (getMroStorageNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getMroStorageNode = insert(GetMroStorageNode.create()); + } + return getMroStorageNode.execute(obj).getInternalClassArray(); + } + + @TruffleBoundary + public static PythonAbstractClass[] doSlowPath(Object obj) { + MroSequenceStorage mroStorage = GetMroStorageNode.doSlowPath(obj); + return mroStorage.getInternalClassArray(); + } + + public static GetMroNode create() { + return new GetMroNode(); + } + } + @ImportStatic(NativeMemberNames.class) - public abstract static class GetMroNode extends PNodeWithContext { + public abstract static class GetMroStorageNode extends PNodeWithContext { - public abstract PythonAbstractClass[] execute(Object obj); + public abstract MroSequenceStorage execute(Object obj); @Specialization - PythonAbstractClass[] doPythonClass(PythonManagedClass obj) { + MroSequenceStorage doPythonClass(PythonManagedClass obj) { return obj.getMethodResolutionOrder(); } @Specialization - PythonAbstractClass[] doPythonClass(PythonBuiltinClassType obj) { + MroSequenceStorage doPythonClass(PythonBuiltinClassType obj) { return getBuiltinPythonClass(obj).getMethodResolutionOrder(); } @Specialization - PythonAbstractClass[] doNativeClass(PythonNativeClass obj, - @Cached("create(TP_MRO)") GetTypeMemberNode getTpMroNode) { - Object tupleObj = getTpMroNode.execute(obj); + MroSequenceStorage doNativeClass(PythonNativeClass obj, + @Cached("create(TP_MRO)") GetTypeMemberNode getTpMroNode, + @Cached("createClassProfile()") ValueProfile tpMroProfile, + @Cached("createClassProfile()") ValueProfile storageProfile) { + Object tupleObj = tpMroProfile.profile(getTpMroNode.execute(obj)); if (tupleObj instanceof PTuple) { - SequenceStorage sequenceStorage = ((PTuple) tupleObj).getSequenceStorage(); + SequenceStorage sequenceStorage = storageProfile.profile(((PTuple) tupleObj).getSequenceStorage()); if (sequenceStorage instanceof MroSequenceStorage) { - return ((MroSequenceStorage) sequenceStorage).getInternalClassArray(); + return (MroSequenceStorage) sequenceStorage; } } throw raise(PythonBuiltinClassType.SystemError, "invalid mro object"); } @TruffleBoundary - public static PythonAbstractClass[] doSlowPath(Object obj) { + public static MroSequenceStorage doSlowPath(Object obj) { if (obj instanceof PythonManagedClass) { return ((PythonManagedClass) obj).getMethodResolutionOrder(); } else if (obj instanceof PythonBuiltinClassType) { @@ -211,7 +235,7 @@ public static PythonAbstractClass[] doSlowPath(Object obj) { if (tupleObj instanceof PTuple) { SequenceStorage sequenceStorage = ((PTuple) tupleObj).getSequenceStorage(); if (sequenceStorage instanceof MroSequenceStorage) { - return ((MroSequenceStorage) sequenceStorage).getInternalClassArray(); + return (MroSequenceStorage) sequenceStorage; } } throw PythonLanguage.getCore().raise(PythonBuiltinClassType.SystemError, "invalid mro object"); @@ -219,8 +243,8 @@ public static PythonAbstractClass[] doSlowPath(Object obj) { throw new IllegalStateException("unknown type " + obj.getClass().getName()); } - public static GetMroNode create() { - return GetMroNodeGen.create(); + public static GetMroStorageNode create() { + return GetMroStorageNodeGen.create(); } } @@ -703,5 +727,4 @@ public static IsTypeNode create() { return IsTypeNodeGen.create(); } } - } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index ecf7aec322..41eb074767 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -42,16 +42,16 @@ import com.oracle.graal.python.builtins.PythonBuiltinClassType; import com.oracle.graal.python.builtins.objects.PNone; -import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; -import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; -import com.oracle.graal.python.nodes.PGuards; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroStorageNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.runtime.PythonCore; import com.oracle.graal.python.runtime.PythonOptions; +import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage; import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; @@ -89,14 +89,14 @@ protected Object lookup(PythonBuiltinClassType klass, Object key) { @Specialization(replaces = "lookupConstantMRO") protected Object lookup(PythonAbstractClass klass, Object key, - @Cached("create()") GetMroNode getMroNode, + @Cached("create()") GetMroStorageNode getMroNode, @Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode) { return LookupAttributeInMRONode.lookupSlow(klass, key, getMroNode, readAttrNode); } } protected final String key; - @Child private GetMroNode getMroNode; + @Child private GetMroStorageNode getMroNode; public LookupAttributeInMRONode(String key) { this.key = key; @@ -149,28 +149,20 @@ final static class PythonClassAssumptionPair { } } - protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonManagedClass klass) { - PythonAbstractClass[] mro = getMro(klass); - Assumption attrAssumption = klass.createAttributeInMROFinalAssumption(key); - for (int i = 0; i < mro.length; i++) { - PythonAbstractClass clsObj = mro[i]; - // TODO(fa): that's just a first approach and needs to be implemented properly - if (clsObj instanceof PythonManagedClass) { - PythonManagedClass cls = (PythonManagedClass) clsObj; - if (i > 0) { - assert cls != klass : "MRO chain is incorrect: '" + klass + "' was found at position " + i; - cls.addAttributeInMROFinalAssumption(key, attrAssumption); - } + protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonAbstractClass klass) { + CompilerAsserts.neverPartOfCompilation(); + MroSequenceStorage mro = getMro(klass); + Assumption attrAssumption = mro.createAttributeInMROFinalAssumption(key); + for (int i = 0; i < mro.length(); i++) { + PythonAbstractClass clsObj = mro.getItemNormalized(i); + if (i > 0) { + assert clsObj != klass : "MRO chain is incorrect: '" + klass + "' was found at position " + i; + mro.addAttributeInMROFinalAssumption(key, attrAssumption); + } - if (cls.getStorage().containsKey(key)) { - Object value = cls.getStorage().get(key); - if (value != PNone.NO_VALUE) { - return new PythonClassAssumptionPair(attrAssumption, value); - } - } - } else { - assert PGuards.isNativeClass(clsObj); - return null; + Object value = ReadAttributeFromObjectNode.doSlowPath(clsObj, key, true); + if (value != PNone.NO_VALUE) { + return new PythonClassAssumptionPair(attrAssumption, value); } } return new PythonClassAssumptionPair(attrAssumption, PNone.NO_VALUE); @@ -178,8 +170,8 @@ protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonManage @Specialization(guards = {"klass == cachedKlass", "cachedClassInMROInfo != null"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = { "cachedClassInMROInfo.assumption"}) - protected Object lookupConstantMROCached(@SuppressWarnings("unused") PythonManagedClass klass, - @Cached("klass") @SuppressWarnings("unused") PythonManagedClass cachedKlass, + protected Object lookupConstantMROCached(@SuppressWarnings("unused") PythonAbstractClass klass, + @Cached("klass") @SuppressWarnings("unused") PythonAbstractClass cachedKlass, @Cached("findAttrClassAndAssumptionInMRO(cachedKlass)") PythonClassAssumptionPair cachedClassInMROInfo) { return cachedClassInMROInfo.value; } @@ -194,14 +186,14 @@ protected ReadAttributeFromObjectNode[] create(int size) { @Specialization(guards = {"klass == cachedKlass", "mroLength < 32"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = "lookupStable") @ExplodeLoop(kind = ExplodeLoop.LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN) - protected Object lookupConstantMRO(@SuppressWarnings("unused") PythonManagedClass klass, - @Cached("klass") @SuppressWarnings("unused") PythonManagedClass cachedKlass, - @Cached("cachedKlass.getLookupStableAssumption()") @SuppressWarnings("unused") Assumption lookupStable, - @Cached(value = "getMro(cachedKlass)", dimensions = 1) PythonAbstractClass[] mro, - @Cached("mro.length") @SuppressWarnings("unused") int mroLength, + protected Object lookupConstantMRO(@SuppressWarnings("unused") PythonAbstractClass klass, + @Cached("klass") @SuppressWarnings("unused") PythonAbstractClass cachedKlass, + @Cached("getMro(cachedKlass)") MroSequenceStorage mro, + @Cached("mro.getLookupStableAssumption()") @SuppressWarnings("unused") Assumption lookupStable, + @Cached("mro.length()") int mroLength, @Cached("create(mroLength)") ReadAttributeFromObjectNode[] readAttrNodes) { - for (int i = 0; i < mro.length; i++) { - PythonAbstractClass kls = mro[i]; + for (int i = 0; i < mroLength; i++) { + PythonAbstractClass kls = mro.getItemNormalized(i); Object value = readAttrNodes[i].execute(kls, key); if (value != PNone.NO_VALUE) { return value; @@ -211,31 +203,27 @@ protected Object lookupConstantMRO(@SuppressWarnings("unused") PythonManagedClas } @Specialization(replaces = {"lookupConstantMROCached", "lookupConstantMRO"}) - protected Object lookup(PythonManagedClass klass, - @Cached("create()") GetMroNode getMroNode, + protected Object lookup(PythonAbstractClass klass, @Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode) { return lookupSlow(klass, key, getMroNode, readAttrNode); } - @Specialization - protected Object lookup(PythonNativeClass klass, - @Cached("create()") GetMroNode getMroNode, - @Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode) { - return lookupSlow(klass, key, getMroNode, readAttrNode); - } - - protected PythonAbstractClass[] getMro(PythonAbstractClass clazz) { + protected GetMroStorageNode ensureGetMroNode() { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - getMroNode = insert(GetMroNode.create()); + getMroNode = insert(GetMroStorageNode.create()); } - return getMroNode.execute(clazz); + return getMroNode; } - protected static Object lookupSlow(PythonAbstractClass klass, Object key, GetMroNode getMroNode, ReadAttributeFromObjectNode readAttrNode) { - PythonAbstractClass[] mro = getMroNode.execute(klass); - for (int i = 0; i < mro.length; i++) { - PythonAbstractClass kls = mro[i]; + protected MroSequenceStorage getMro(PythonAbstractClass clazz) { + return ensureGetMroNode().execute(clazz); + } + + protected static Object lookupSlow(PythonAbstractClass klass, Object key, GetMroStorageNode getMroNode, ReadAttributeFromObjectNode readAttrNode) { + MroSequenceStorage mro = getMroNode.execute(klass); + for (int i = 0; i < mro.length(); i++) { + PythonAbstractClass kls = mro.getItemNormalized(i); Object value = readAttrNode.execute(kls, key); if (value != PNone.NO_VALUE) { return value; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java index 6db1169710..f1fb74bca6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java @@ -98,9 +98,7 @@ protected boolean isAttrWritable(PythonObject self, Object key) { private void handlePythonClass(PythonObject object, Object key) { if (isClassProfile.profile(object instanceof PythonManagedClass)) { - if (key instanceof String) { - ((PythonManagedClass) object).invalidateAttributeInMROFinalAssumptions((String) key); - } + ((PythonManagedClass) object).invalidateFinalAttribute(key); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java index dc13255a92..ed9eaf6906 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java @@ -40,35 +40,52 @@ */ package com.oracle.graal.python.runtime.sequence.storage; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.utilities.CyclicAssumption; public final class MroSequenceStorage extends TypedSequenceStorage { - private PythonAbstractClass[] values; + /** + * This assumption will be invalidated whenever the mro changes. + */ + private final CyclicAssumption lookupStableAssumption; - public MroSequenceStorage(PythonAbstractClass[] elements) { - this.values = elements; - this.capacity = elements.length; - this.length = elements.length; - } + /** + * These assumptions will be invalidated whenever the value of the given slot changes. All + * assumptions will be invalidated if the mro changes. + */ + private final Map> attributesInMROFinalAssumptions = new HashMap<>(); + + @CompilationFinal(dimensions = 1) private PythonAbstractClass[] values; - public MroSequenceStorage(PythonAbstractClass[] elements, int length) { + public MroSequenceStorage(String className, PythonAbstractClass[] elements) { this.values = elements; this.capacity = elements.length; - this.length = length; + this.length = elements.length; + this.lookupStableAssumption = new CyclicAssumption(className); } - public MroSequenceStorage(int capacity) { + public MroSequenceStorage(String className, int capacity) { this.values = new PythonAbstractClass[capacity]; this.capacity = capacity; this.length = 0; + this.lookupStableAssumption = new CyclicAssumption(className); } @Override - public Object getItemNormalized(int idx) { + public PythonAbstractClass getItemNormalized(int idx) { return values[idx]; } @@ -82,6 +99,9 @@ public void setItemNormalized(int idx, Object value) { } public void setClassItemNormalized(int idx, PythonAbstractClass value) { + if (values[idx] != value) { + lookupChanged("direct assignment to MRO"); + } values[idx] = value; } @@ -100,6 +120,9 @@ public void insertItem(int idx, Object value) { @Override public void copyItem(int idxTo, int idxFrom) { + if (idxTo != idxFrom) { + lookupChanged("item move within MRO"); + } values[idxTo] = values[idxFrom]; } @@ -109,14 +132,14 @@ public MroSequenceStorage getSliceInBound(int start, int stop, int step, int sli if (step == 1) { System.arraycopy(values, start, newArray, 0, sliceLength); - return new MroSequenceStorage(newArray); + return new MroSequenceStorage(getClassName(), newArray); } for (int i = start, j = 0; j < sliceLength; i += step, j++) { newArray[j] = values[i]; } - return new MroSequenceStorage(newArray); + return new MroSequenceStorage(getClassName(), newArray); } public void setObjectSliceInBound(int start, int stop, int step, MroSequenceStorage sequence, ConditionProfile sameLengthProfile) { @@ -137,16 +160,21 @@ public void setObjectSliceInBound(int start, int stop, int step, MroSequenceStor } length = length > stop ? length : stop; + lookupChanged("slice assignment to MRO"); + } + + public String getClassName() { + return lookupStableAssumption.getAssumption().getName(); } @Override public SequenceStorage copy() { - return new MroSequenceStorage(Arrays.copyOf(values, length)); + return new MroSequenceStorage(getClassName(), Arrays.copyOf(values, length)); } @Override public SequenceStorage createEmpty(int newCapacity) { - return new MroSequenceStorage(newCapacity); + return new MroSequenceStorage(getClassName(), newCapacity); } @Override @@ -188,6 +216,7 @@ public void reverse() { values[head] = values[tail]; values[tail] = temp; } + lookupChanged("MRO reversed"); } } @@ -227,11 +256,74 @@ public Object getCopyOfInternalArrayObject() { @Override public void setInternalArrayObject(Object arrayObject) { - this.values = (PythonAbstractClass[]) arrayObject; + PythonAbstractClass[] classArray = (PythonAbstractClass[]) arrayObject; + this.values = classArray; + this.length = classArray.length; + this.capacity = classArray.length; } @Override public ListStorageType getElementType() { return ListStorageType.Generic; } + + public Assumption getLookupStableAssumption() { + return lookupStableAssumption.getAssumption(); + } + + public Assumption createAttributeInMROFinalAssumption(String name) { + CompilerAsserts.neverPartOfCompilation(); + List attrAssumptions = attributesInMROFinalAssumptions.getOrDefault(name, null); + if (attrAssumptions == null) { + attrAssumptions = new ArrayList<>(); + attributesInMROFinalAssumptions.put(name, attrAssumptions); + } + + Assumption assumption = Truffle.getRuntime().createAssumption(name.toString()); + attrAssumptions.add(assumption); + return assumption; + } + + public void addAttributeInMROFinalAssumption(String name, Assumption assumption) { + CompilerAsserts.neverPartOfCompilation(); + List attrAssumptions = attributesInMROFinalAssumptions.getOrDefault(name, null); + if (attrAssumptions == null) { + attrAssumptions = new ArrayList<>(); + attributesInMROFinalAssumptions.put(name, attrAssumptions); + } + + attrAssumptions.add(assumption); + } + + @TruffleBoundary + public void invalidateAttributeInMROFinalAssumptions(String name) { + List assumptions = attributesInMROFinalAssumptions.getOrDefault(name, new ArrayList<>()); + if (!assumptions.isEmpty()) { + String message = getClassName() + "." + name; + for (Assumption assumption : assumptions) { + assumption.invalidate(message); + } + } + } + + public void lookupChanged() { + CompilerAsserts.neverPartOfCompilation(); + for (List list : attributesInMROFinalAssumptions.values()) { + for (Assumption assumption : list) { + assumption.invalidate(); + } + } + lookupStableAssumption.invalidate(); + } + + public void lookupChanged(String msg) { + CompilerAsserts.neverPartOfCompilation(); + for (List list : attributesInMROFinalAssumptions.values()) { + for (Assumption assumption : list) { + assumption.invalidate(); + } + } + lookupStableAssumption.invalidate(msg); + } + } From 05978991ec5af5e505a41d804f20215ad6ddd4c1 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 22:41:31 +0100 Subject: [PATCH 097/202] Fix: 'issubclass' checks if arguments have attribute '__bases__'. --- .../builtins/objects/type/TypeBuiltins.java | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index cef205f05c..66fa11a48f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -99,9 +99,11 @@ import com.oracle.graal.python.nodes.object.GetLazyClassNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.nodes.truffle.PythonTypes; +import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.exception.PythonErrorType; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -529,6 +531,11 @@ public boolean isInstance(Object cls, Object instance) { static abstract class SubclassCheckNode extends PythonBinaryBuiltinNode { @Child private IsSubtypeNode isSubtypeNode = IsSubtypeNode.create(); @Child private TypeNodes.IsSameTypeNode isSameTypeNode = TypeNodes.IsSameTypeNode.create(); + @Child private GetFixedAttributeNode getBasesAttrNode; + @Child private GetLazyClassNode getClassNode; + + @CompilationFinal private IsBuiltinClassProfile isAttrErrorProfile; + @CompilationFinal private IsBuiltinClassProfile isTupleProfile; @Specialization(guards = {"!isNativeClass(cls)", "!isNativeClass(derived)"}) boolean doManagedManaged(LazyPythonClass cls, LazyPythonClass derived) { @@ -547,15 +554,35 @@ boolean doObjectObject(Object cls, Object derived, if (isClsTypeNode.execute(cls) && isDerivedTypeNode.execute(derived)) { return isSubtypeNode.execute(derived, cls); } - if (!isDerivedTypeNode.execute(derived)) { + if (!checkClass(derived)) { throw raise(PythonBuiltinClassType.TypeError, "issubclass() arg 1 must be a class"); } - if (!isClsTypeNode.execute(cls)) { + if (!checkClass(cls)) { throw raise(PythonBuiltinClassType.TypeError, "issubclass() arg 2 must be a class or tuple of classes"); } return false; } + // checks if object has '__bases__' (see CPython 'abstract.c' function + // 'recursive_issubclass') + private boolean checkClass(Object obj) { + if (getBasesAttrNode == null || isAttrErrorProfile == null || isTupleProfile == null || getClassNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getBasesAttrNode = insert(GetFixedAttributeNode.create(SpecialAttributeNames.__BASES__)); + isAttrErrorProfile = IsBuiltinClassProfile.create(); + isTupleProfile = IsBuiltinClassProfile.create(); + getClassNode = insert(GetLazyClassNode.create()); + } + Object basesObj; + try { + basesObj = getBasesAttrNode.executeObject(obj); + } catch (PException e) { + e.expectAttributeError(isAttrErrorProfile); + return false; + } + return isTupleProfile.profileClass(getClassNode.execute(basesObj), PythonBuiltinClassType.PTuple); + } + protected boolean isSameType(Object a, Object b) { return isSameTypeNode.execute(a, b); } From 5bfae8cdd2f2869a637c0f171ef49577f6c0ff3b Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 22:42:08 +0100 Subject: [PATCH 098/202] Fix: added assumption to wrong class. --- .../graal/python/nodes/attributes/LookupAttributeInMRONode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index 41eb074767..9b3d50b76e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -157,7 +157,7 @@ protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonAbstra PythonAbstractClass clsObj = mro.getItemNormalized(i); if (i > 0) { assert clsObj != klass : "MRO chain is incorrect: '" + klass + "' was found at position " + i; - mro.addAttributeInMROFinalAssumption(key, attrAssumption); + getMro(clsObj).addAttributeInMROFinalAssumption(key, attrAssumption); } Object value = ReadAttributeFromObjectNode.doSlowPath(clsObj, key, true); From 663ab3ac735f1335e8733d23fc47758e78fbb790 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 23:29:38 +0100 Subject: [PATCH 099/202] Fix: generic case of 'FloatNode' did not cover bytes-like objects. --- .../src/tests/test_float.py | 6 ++++++ .../python/builtins/modules/BuiltinConstructors.java | 11 +++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_float.py b/graalpython/com.oracle.graal.python.test/src/tests/test_float.py index d1d87c2ea9..880f8f71e8 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_float.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_float.py @@ -94,11 +94,17 @@ def __round__(x, n): assert round(C(), a) == a def test_create(self): + class Obj: + def __float__(self): + return 1.123 + assert [float(x) for x in [Obj(), b"0.123"]] == [1.123, 0.123] + assert float(99) == 99 assert float(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999) == 1e+132 assert float(b"0.001") == 0.001 assert float("0.001") == 0.001 + def test_hex(self): data = [ ('nan', 'nan'), diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index a4f3165e22..96215da2f8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -717,15 +717,20 @@ public Object floatFromString(LazyPythonClass cls, String arg) { } @Specialization(guards = "!isNativeClass(cls)") - @TruffleBoundary public Object floatFromBytes(LazyPythonClass cls, PIBytesLike arg) { - double value = convertStringToDouble(new String(getByteArray(arg))); + double value = convertBytesToDouble(arg); if (isPrimitiveFloat(cls)) { return value; } return factory().createFloat(cls, value); } + @TruffleBoundary + private double convertBytesToDouble(PIBytesLike arg) { + double value = convertStringToDouble(new String(getByteArray(arg))); + return value; + } + // Taken from Jython PyString's atof() method // The last statement throw Py.ValueError is modified @TruffleBoundary @@ -785,6 +790,8 @@ public Object floatFromNone(LazyPythonClass cls, @SuppressWarnings("unused") PNo return convertStringToDouble(((PString) obj).getValue()); } else if (obj instanceof PNone) { return 0.0; + } else if (obj instanceof PIBytesLike) { + return convertBytesToDouble((PIBytesLike) obj); } try { return callFloatNode.executeDouble(obj); From 481a518f03a8305e166ddb1a45dce8ab4490810f Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 31 Jan 2019 10:40:15 +0100 Subject: [PATCH 100/202] Fix: 'divmod' builtin did not handle error case. --- .../src/tests/test_binary_arithmetic.py | 15 +++++++++++++ .../builtins/modules/BuiltinFunctions.java | 21 +++++-------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_binary_arithmetic.py b/graalpython/com.oracle.graal.python.test/src/tests/test_binary_arithmetic.py index 5c21818a99..9f32c9e023 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_binary_arithmetic.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_binary_arithmetic.py @@ -133,6 +133,21 @@ def test_floor_div(): assert_exception(lambda: 5.4 // 0.0, ZeroDivisionError) +def test_divmod(): + class Floatable: + def __init__(self, val): + self.val = val + def __float__(self): + return self.val + + def doDivmod(a, b): + return divmod(a, b) + + argList = [(Floatable(3), Floatable(4)), (complex(1,2), complex(3,4))] + for args in argList: + assert_exception(lambda: doDivmod(*args), TypeError) + + def test_subclass_ordered_binop(): class A(int): def __add__(self, other): diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 8d2e053af0..eff0fbaaab 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -98,7 +98,6 @@ import com.oracle.graal.python.builtins.objects.common.PHashingCollection; import com.oracle.graal.python.builtins.objects.common.SequenceNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; -import com.oracle.graal.python.builtins.objects.complex.PComplex; import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.frame.FrameBuiltins.GetLocalsNode; import com.oracle.graal.python.builtins.objects.function.Arity; @@ -176,6 +175,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.Frame; @@ -498,7 +498,8 @@ private ListAppendNode getAppendNode() { @Builtin(name = DIVMOD, fixedNumOfPositionalArgs = 2) @TypeSystemReference(PythonArithmeticTypes.class) @GenerateNodeFactory - public abstract static class DivModNode extends PythonBuiltinNode { + @ImportStatic(BinaryArithmetic.class) + public abstract static class DivModNode extends PythonBinaryBuiltinNode { @Specialization(guards = "b != 0") public PTuple doLong(long a, long b) { return factory().createTuple(new Object[]{Math.floorDiv(a, b), Math.floorMod(a, b)}); @@ -518,22 +519,10 @@ public PTuple doDouble(double a, double b) { return factory().createTuple(new Object[]{q, a % b}); } - @Specialization - @SuppressWarnings("unused") - public PTuple doComplex(PComplex c, Object o) { - throw raise(PythonErrorType.TypeError, "can't take floor or mod of complex number."); - } - - @Specialization - @SuppressWarnings("unused") - public PTuple doComplex(Object o, PComplex c) { - throw raise(PythonErrorType.TypeError, "can't take floor or mod of complex number."); - } - @Specialization public PTuple doObject(Object a, Object b, - @Cached("create(__FLOORDIV__)") LookupAndCallBinaryNode floordivNode, - @Cached("create(__MOD__)") LookupAndCallBinaryNode modNode) { + @Cached("FloorDiv.create()") LookupAndCallBinaryNode floordivNode, + @Cached("Mod.create()") LookupAndCallBinaryNode modNode) { Object div = floordivNode.executeObject(a, b); Object mod = modNode.executeObject(a, b); return factory().createTuple(new Object[]{div, mod}); From fc6199340737de4cf1971d57eb6d304192ce62d7 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 31 Jan 2019 11:04:35 +0100 Subject: [PATCH 101/202] Fix style. --- .../graal/python/builtins/objects/type/PythonManagedClass.java | 1 - 1 file changed, 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java index d9d6450cb0..a0942d1112 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java @@ -52,7 +52,6 @@ public abstract class PythonManagedClass extends PythonObject implements PythonA private final String className; @CompilationFinal(dimensions = 1) private PythonAbstractClass[] baseClasses; -// @CompilationFinal(dimensions = 1) private PythonAbstractClass[] methodResolutionOrder; private final MroSequenceStorage methodResolutionOrder; From b751e1775f3207bab6c501ab856b239c972caaef Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 31 Jan 2019 14:42:29 +0100 Subject: [PATCH 102/202] Remove unnecessary memset. --- graalpython/com.oracle.graal.python.cext/src/object.c | 1 - 1 file changed, 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/object.c b/graalpython/com.oracle.graal.python.cext/src/object.c index 3f921f309b..bff28e0963 100644 --- a/graalpython/com.oracle.graal.python.cext/src/object.c +++ b/graalpython/com.oracle.graal.python.cext/src/object.c @@ -141,7 +141,6 @@ PyObject _Py_NotImplementedStruct = { PyObject* PyType_GenericAlloc(PyTypeObject* cls, Py_ssize_t nitems) { Py_ssize_t size = cls->tp_basicsize + cls->tp_itemsize * nitems; PyObject* newObj = (PyObject*)PyObject_Malloc(size); - memset(newObj, 0, size); if(cls->tp_dictoffset) { *((PyObject **) ((char *)newObj + cls->tp_dictoffset)) = NULL; } From 1348ede7c85b1af150516ba579a900f87e6f5e18 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 31 Jan 2019 16:53:15 +0100 Subject: [PATCH 103/202] Fix: IsSubtypeNode cached on MRO without assumption. --- .../python/nodes/classes/IsSubtypeNode.java | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java index db4bf7500b..b0ab1689d8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java @@ -41,11 +41,12 @@ package com.oracle.graal.python.nodes.classes; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; -import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroStorageNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.runtime.PythonOptions; import com.oracle.graal.python.runtime.exception.PythonErrorType; +import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -61,7 +62,7 @@ public abstract class IsSubtypeNode extends PNodeWithContext { @Child private AbstractObjectGetBasesNode getBasesNode = AbstractObjectGetBasesNode.create(); @Child private AbstractObjectIsSubclassNode abstractIsSubclassNode = AbstractObjectIsSubclassNode.create(); - @Child private GetMroNode getMroNode; + @Child private GetMroStorageNode getMroNode; @Child private IsSameTypeNode isSameTypeNode; private final ConditionProfile exceptionDerivedProfile = ConditionProfile.createBinaryProfile(); @@ -73,12 +74,19 @@ public static IsSubtypeNode create() { public abstract boolean execute(Object derived, Object cls); - @Specialization(guards = {"derived == cachedDerived", "cls == cachedCls"}, limit = "getVariableArgumentInlineCacheLimit()") + @Specialization(guards = { // + "derived == cachedDerived", // + "cls == cachedCls", // + "mro.length() < 32" // + }, // + limit = "getVariableArgumentInlineCacheLimit()", // + assumptions = "mro.getLookupStableAssumption()") @ExplodeLoop boolean isSubtypeOfConstantType(@SuppressWarnings("unused") PythonAbstractClass derived, @SuppressWarnings("unused") PythonAbstractClass cls, - @Cached("derived") PythonAbstractClass cachedDerived, - @Cached("cls") PythonAbstractClass cachedCls) { - for (PythonAbstractClass n : getMro(cachedDerived)) { + @Cached("derived") @SuppressWarnings("unused") PythonAbstractClass cachedDerived, + @Cached("cls") PythonAbstractClass cachedCls, + @Cached("getMro(cachedDerived)") MroSequenceStorage mro) { + for (PythonAbstractClass n : mro.getInternalClassArray()) { if (isSameType(n, cachedCls)) { return true; } @@ -86,11 +94,19 @@ boolean isSubtypeOfConstantType(@SuppressWarnings("unused") PythonAbstractClass return false; } - @Specialization(guards = {"derived == cachedDerived"}, limit = "getVariableArgumentInlineCacheLimit()", replaces = "isSubtypeOfConstantType") + @Specialization(guards = { // + "derived == cachedDerived", // + "mro.length() < 32" // + }, // + limit = "getVariableArgumentInlineCacheLimit()", // + replaces = "isSubtypeOfConstantType", // + assumptions = "mro.getLookupStableAssumption()" // + ) @ExplodeLoop boolean isSubtypeOfVariableType(@SuppressWarnings("unused") PythonAbstractClass derived, PythonAbstractClass cls, - @Cached("derived") PythonAbstractClass cachedDerived) { - for (PythonAbstractClass n : getMro(cachedDerived)) { + @Cached("derived") @SuppressWarnings("unused") PythonAbstractClass cachedDerived, + @Cached("getMro(cachedDerived)") MroSequenceStorage mro) { + for (PythonAbstractClass n : mro.getInternalClassArray()) { if (isSameType(n, cls)) { return true; } @@ -100,7 +116,7 @@ boolean isSubtypeOfVariableType(@SuppressWarnings("unused") PythonAbstractClass @Specialization(replaces = {"isSubtypeOfConstantType", "isSubtypeOfVariableType"}) boolean issubTypeGeneric(PythonAbstractClass derived, PythonAbstractClass cls) { - for (PythonAbstractClass n : getMro(derived)) { + for (PythonAbstractClass n : getMro(derived).getInternalClassArray()) { if (isSameType(n, cls)) { return true; } @@ -121,10 +137,10 @@ public boolean isSubclass(Object derived, Object cls) { return abstractIsSubclassNode.execute(derived, cls); } - private PythonAbstractClass[] getMro(PythonAbstractClass clazz) { + protected MroSequenceStorage getMro(PythonAbstractClass clazz) { if (getMroNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - getMroNode = insert(GetMroNode.create()); + getMroNode = insert(GetMroStorageNode.create()); } return getMroNode.execute(clazz); } From 75e45716d56f8131199fa7f99b9369b7ea13d0b2 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 31 Jan 2019 18:11:40 +0100 Subject: [PATCH 104/202] Fix copyrights. --- graalpython/com.oracle.graal.python.cext/src/object.c | 2 +- .../src/tests/test_binary_arithmetic.py | 2 +- .../com.oracle.graal.python.test/src/tests/test_float.py | 2 +- .../python/builtins/objects/common/DynamicObjectStorage.java | 2 +- .../python/builtins/objects/common/HashingStorageNodes.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/object.c b/graalpython/com.oracle.graal.python.cext/src/object.c index bff28e0963..950d784b90 100644 --- a/graalpython/com.oracle.graal.python.cext/src/object.c +++ b/graalpython/com.oracle.graal.python.cext/src/object.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_binary_arithmetic.py b/graalpython/com.oracle.graal.python.test/src/tests/test_binary_arithmetic.py index 9f32c9e023..7df85b7c47 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_binary_arithmetic.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_binary_arithmetic.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. # Copyright (c) 2013, Regents of the University of California # # All rights reserved. diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_float.py b/graalpython/com.oracle.graal.python.test/src/tests/test_float.py index 880f8f71e8..b7ae1f338a 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_float.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_float.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java index 5416543db7..9c268b9dca 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java index 5a92836d47..7b1d912788 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 From f2248ccd5ae69d67771009614a930a3aba080942 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 1 Feb 2019 10:04:56 +0100 Subject: [PATCH 105/202] Use 'IsBuiltinClassProfile' in 'GlobalNode'. --- .../graal/python/nodes/frame/GlobalNode.java | 10 ++++------ .../nodes/frame/ReadGlobalOrBuiltinNode.java | 7 ++++--- .../graal/python/nodes/frame/WriteGlobalNode.java | 14 ++++++++------ 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/GlobalNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/GlobalNode.java index 16d0b7b0ce..b61aff4f33 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/GlobalNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/GlobalNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -44,8 +44,7 @@ import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.function.PArguments; import com.oracle.graal.python.builtins.objects.module.PythonModule; -import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; +import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.truffle.api.frame.VirtualFrame; public interface GlobalNode { @@ -53,11 +52,10 @@ default boolean isInModule(VirtualFrame frame) { return PArguments.getGlobals(frame) instanceof PythonModule; } - default boolean isInBuiltinDict(VirtualFrame frame) { + default boolean isInBuiltinDict(VirtualFrame frame, IsBuiltinClassProfile profile) { Object globals = PArguments.getGlobals(frame); if (globals instanceof PDict) { - LazyPythonClass clazz = ((PDict) globals).getLazyPythonClass(); - return clazz == PythonBuiltinClassType.PDict || (clazz instanceof PythonBuiltinClass && ((PythonBuiltinClass) clazz).getType() == PythonBuiltinClassType.PDict); + return profile.profileObject((PDict) globals, PythonBuiltinClassType.PDict); } return false; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/ReadGlobalOrBuiltinNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/ReadGlobalOrBuiltinNode.java index 22a5a32a84..2a4cc52e4f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/ReadGlobalOrBuiltinNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/ReadGlobalOrBuiltinNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -80,9 +80,10 @@ protected Object readGlobal(VirtualFrame frame) { return returnGlobalOrBuiltin(result); } - @Specialization(guards = "isInBuiltinDict(frame)") + @Specialization(guards = "isInBuiltinDict(frame, builtinProfile)") protected Object readGlobalDict(VirtualFrame frame, - @Cached("create()") HashingStorageNodes.GetItemNode getItemNode) { + @Cached("create()") HashingStorageNodes.GetItemNode getItemNode, + @Cached("create()") @SuppressWarnings("unused") IsBuiltinClassProfile builtinProfile) { PythonObject globals = PArguments.getGlobals(frame); Object result = getItemNode.execute(((PDict) globals).getDictStorage(), attributeId); return returnGlobalOrBuiltin(result == null ? PNone.NO_VALUE : result); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteGlobalNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteGlobalNode.java index 2fc99bb52d..2ca3c8ff5d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteGlobalNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteGlobalNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -45,6 +45,7 @@ import com.oracle.graal.python.builtins.objects.function.PArguments; import com.oracle.graal.python.nodes.attributes.SetAttributeNode; import com.oracle.graal.python.nodes.expression.ExpressionNode; +import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.nodes.statement.StatementNode; import com.oracle.graal.python.nodes.subscript.SetItemNode; import com.oracle.truffle.api.dsl.Cached; @@ -55,6 +56,7 @@ @NodeChild(value = "rhs", type = ExpressionNode.class) public abstract class WriteGlobalNode extends StatementNode implements GlobalNode, WriteNode { protected final String attributeId; + protected final IsBuiltinClassProfile builtinProfile = IsBuiltinClassProfile.create(); WriteGlobalNode(String attributeId) { this.attributeId = attributeId; @@ -102,31 +104,31 @@ private static PDict getGlobalsDict(VirtualFrame frame) { return (PDict) PArguments.getGlobals(frame); } - @Specialization(guards = "isInBuiltinDict(frame)") + @Specialization(guards = "isInBuiltinDict(frame, builtinProfile)") void writeDictBoolean(VirtualFrame frame, boolean value, @Cached("create()") HashingCollectionNodes.SetItemNode storeNode) { storeNode.execute(getGlobalsDict(frame), attributeId, value); } - @Specialization(guards = "isInBuiltinDict(frame)") + @Specialization(guards = "isInBuiltinDict(frame, builtinProfile)") void writeDictInt(VirtualFrame frame, int value, @Cached("create()") HashingCollectionNodes.SetItemNode storeNode) { storeNode.execute(getGlobalsDict(frame), attributeId, value); } - @Specialization(guards = "isInBuiltinDict(frame)") + @Specialization(guards = "isInBuiltinDict(frame, builtinProfile)") void writeDictLong(VirtualFrame frame, long value, @Cached("create()") HashingCollectionNodes.SetItemNode storeNode) { storeNode.execute(getGlobalsDict(frame), attributeId, value); } - @Specialization(guards = "isInBuiltinDict(frame)") + @Specialization(guards = "isInBuiltinDict(frame, builtinProfile)") void writeDictDouble(VirtualFrame frame, double value, @Cached("create()") HashingCollectionNodes.SetItemNode storeNode) { storeNode.execute(getGlobalsDict(frame), attributeId, value); } - @Specialization(replaces = {"writeDictBoolean", "writeDictInt", "writeDictLong", "writeDictDouble"}, guards = "isInBuiltinDict(frame)") + @Specialization(replaces = {"writeDictBoolean", "writeDictInt", "writeDictLong", "writeDictDouble"}, guards = "isInBuiltinDict(frame, builtinProfile)") void writeDictObject(VirtualFrame frame, Object value, @Cached("create()") HashingCollectionNodes.SetItemNode storeNode) { storeNode.execute(getGlobalsDict(frame), attributeId, value); From 7d014705b71d1ed6e740386c7409f0f6d1ed24f8 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 1 Feb 2019 15:15:45 +0100 Subject: [PATCH 106/202] Use fast identity check node in guards of 'LookupAttributeInMRONode'. --- .../builtins/objects/type/TypeNodes.java | 24 ++++++++++++++++--- .../attributes/LookupAttributeInMRONode.java | 10 ++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 83a3227c57..8ffef819ea 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -541,6 +541,12 @@ private static PythonAbstractClass[] cast(Object[] arr) { @ImportStatic(SpecialMethodNames.class) public abstract static class IsSameTypeNode extends PNodeWithContext { + protected final boolean fastCheck; + + public IsSameTypeNode(boolean fastCheck) { + this.fastCheck = fastCheck; + } + public abstract boolean execute(Object left, Object right); @Specialization @@ -548,8 +554,16 @@ boolean doManaged(PythonManagedClass left, PythonManagedClass right) { return left == right; } - @Specialization - boolean doNative(PythonAbstractNativeObject left, PythonAbstractNativeObject right, + @Specialization(guards = "fastCheck") + boolean doNativeFast(PythonAbstractNativeObject left, PythonAbstractNativeObject right) { + // This check is a bit dangerous since we cannot be sure about the code that is running. + // Currently, we assume that the pointer object is a Sulong pointer and for this it's + // fine. + return left.object.equals(right.object); + } + + @Specialization(guards = "!fastCheck") + boolean doNativeSlow(PythonAbstractNativeObject left, PythonAbstractNativeObject right, @Cached("create(__EQ__)") CExtNodes.PointerCompareNode pointerCompareNode) { return pointerCompareNode.execute(left, right); } @@ -570,7 +584,11 @@ public static boolean doSlowPath(Object left, Object right) { } public static IsSameTypeNode create() { - return IsSameTypeNodeGen.create(); + return IsSameTypeNodeGen.create(false); + } + + public static IsSameTypeNode createFast() { + return IsSameTypeNodeGen.create(true); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index 9b3d50b76e..3cde31448b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -44,6 +44,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroStorageNode; import com.oracle.graal.python.nodes.PNodeWithContext; @@ -96,6 +97,7 @@ protected Object lookup(PythonAbstractClass klass, Object key, } protected final String key; + @Child private TypeNodes.IsSameTypeNode isSameTypeNode = TypeNodes.IsSameTypeNode.createFast(); @Child private GetMroStorageNode getMroNode; public LookupAttributeInMRONode(String key) { @@ -168,7 +170,7 @@ protected PythonClassAssumptionPair findAttrClassAndAssumptionInMRO(PythonAbstra return new PythonClassAssumptionPair(attrAssumption, PNone.NO_VALUE); } - @Specialization(guards = {"klass == cachedKlass", "cachedClassInMROInfo != null"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = { + @Specialization(guards = {"isSameType(cachedKlass, klass)", "cachedClassInMROInfo != null"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = { "cachedClassInMROInfo.assumption"}) protected Object lookupConstantMROCached(@SuppressWarnings("unused") PythonAbstractClass klass, @Cached("klass") @SuppressWarnings("unused") PythonAbstractClass cachedKlass, @@ -184,7 +186,7 @@ protected ReadAttributeFromObjectNode[] create(int size) { return nodes; } - @Specialization(guards = {"klass == cachedKlass", "mroLength < 32"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = "lookupStable") + @Specialization(guards = {"isSameType(cachedKlass, klass)", "mroLength < 32"}, limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", assumptions = "lookupStable") @ExplodeLoop(kind = ExplodeLoop.LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN) protected Object lookupConstantMRO(@SuppressWarnings("unused") PythonAbstractClass klass, @Cached("klass") @SuppressWarnings("unused") PythonAbstractClass cachedKlass, @@ -243,4 +245,8 @@ public static Object lookupSlow(LazyPythonClass klass, String key) { } return PNone.NO_VALUE; } + + protected boolean isSameType(PythonAbstractClass cachedKlass, PythonAbstractClass klass) { + return isSameTypeNode.execute(cachedKlass, klass); + } } From 78f381afcaa0061e11063e25a77bacc93742760e Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 1 Feb 2019 15:17:00 +0100 Subject: [PATCH 107/202] Directly use 'length' of MRO array. --- .../com/oracle/graal/python/nodes/classes/IsSubtypeNode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java index b0ab1689d8..b9fc9fae71 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/IsSubtypeNode.java @@ -77,7 +77,7 @@ public static IsSubtypeNode create() { @Specialization(guards = { // "derived == cachedDerived", // "cls == cachedCls", // - "mro.length() < 32" // + "mro.getInternalClassArray().length < 32" // }, // limit = "getVariableArgumentInlineCacheLimit()", // assumptions = "mro.getLookupStableAssumption()") @@ -96,7 +96,7 @@ boolean isSubtypeOfConstantType(@SuppressWarnings("unused") PythonAbstractClass @Specialization(guards = { // "derived == cachedDerived", // - "mro.length() < 32" // + "mro.getInternalClassArray().length < 32" // }, // limit = "getVariableArgumentInlineCacheLimit()", // replaces = "isSubtypeOfConstantType", // From 8ccc69f647bacb75d15ce73f606eb2f41577f866 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 1 Feb 2019 15:17:22 +0100 Subject: [PATCH 108/202] Make methods final where possible. --- .../python/runtime/sequence/storage/MroSequenceStorage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java index ed9eaf6906..784869904e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/MroSequenceStorage.java @@ -85,7 +85,7 @@ public MroSequenceStorage(String className, int capacity) { } @Override - public PythonAbstractClass getItemNormalized(int idx) { + public final PythonAbstractClass getItemNormalized(int idx) { return values[idx]; } @@ -182,7 +182,7 @@ public Object[] getInternalArray() { return values; } - public PythonAbstractClass[] getInternalClassArray() { + public final PythonAbstractClass[] getInternalClassArray() { return values; } From fe77f7b44fb1356580bea87c9156d8b343a5b155 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Mon, 4 Feb 2019 11:05:57 +0100 Subject: [PATCH 109/202] Use 'equals' of native pointer object in guard. --- .../oracle/graal/python/builtins/objects/cext/CExtNodes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index 7edd6255f4..2e4debc425 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -848,7 +848,7 @@ public abstract static class GetNativeClassNode extends CExtBaseNode { public abstract PythonAbstractClass execute(PythonAbstractNativeObject object); - @Specialization(guards = "object == cachedObject", limit = "1") + @Specialization(guards = "cachedObject.equals(object)", limit = "1") PythonAbstractClass getNativeClassCached(@SuppressWarnings("unused") PythonAbstractNativeObject object, @SuppressWarnings("unused") @Cached("object") PythonAbstractNativeObject cachedObject, @Cached("getNativeClass(cachedObject)") PythonAbstractClass cachedClass) { From 6d7696251b36b474abc1cdaf2dc346794ccb047b Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Mon, 4 Feb 2019 13:39:17 +0100 Subject: [PATCH 110/202] Cache results in 'GetTypeMemberNode'. --- .../src/typeobject.c | 4 +-- .../builtins/modules/TruffleCextBuiltins.java | 26 ++++++++++++++++++- .../builtins/objects/cext/CExtNodes.java | 25 ++++++++++++++---- .../cext/PythonAbstractNativeObject.java | 12 +++++++++ .../builtins/objects/type/TypeNodes.java | 11 ++++++-- .../graal/python/runtime/PythonContext.java | 13 ++++++++++ 6 files changed, 81 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/typeobject.c b/graalpython/com.oracle.graal.python.cext/src/typeobject.c index cc0db093e9..5e151b6918 100644 --- a/graalpython/com.oracle.graal.python.cext/src/typeobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/typeobject.c @@ -542,9 +542,9 @@ int PyType_Ready(PyTypeObject* cls) { #undef ADD_METHOD_OR_SLOT } +UPCALL_ID(PyTruffle_Type_Modified); void PyType_Modified(PyTypeObject* type) { - // (tfel) I don't think we have to do anything here, since we track MRO - // changes separately, anyway + UPCALL_CEXT_VOID(_jls_PyTruffle_Type_Modified, native_to_java(type), polyglot_from_string(type->tp_name, SRC_CS), native_to_java(type->tp_mro)); } MUST_INLINE static int valid_identifier(PyObject *s) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 2aa8ee2a77..65ee3bbb0e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -189,6 +189,8 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.api.utilities.CyclicAssumption; @CoreFunctions(defineModule = "python_cext") public class TruffleCextBuiltins extends PythonBuiltins { @@ -2314,7 +2316,7 @@ int add(Object self, @SuppressWarnings("unused") Object o) { @Builtin(name = "PyTruffle_Compute_Mro", fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - @TypeSystemReference(PythonArithmeticTypes.class) + @TypeSystemReference(PythonTypes.class) public abstract static class PyTruffle_Compute_Mro extends PythonBinaryBuiltinNode { @Specialization @@ -2323,4 +2325,26 @@ Object doIt(PythonNativeObject self, String className) { return factory().createTuple(new MroSequenceStorage(className, doSlowPath)); } } + + @Builtin(name = "PyTruffle_Type_Modified", fixedNumOfPositionalArgs = 3) + @GenerateNodeFactory + @TypeSystemReference(PythonTypes.class) + public abstract static class PyTruffle_Type_Modified extends PythonTernaryBuiltinNode { + + @Specialization + Object doIt(PythonNativeClass clazz, String name, PTuple mroTuple, + @Cached("createClassProfile()") ValueProfile profile) { + CyclicAssumption nativeClassStableAssumption = getContext().getNativeClassStableAssumption(clazz, false); + if (nativeClassStableAssumption != null) { + nativeClassStableAssumption.invalidate("PyType_Modified(\"" + name + "\") called"); + } + SequenceStorage sequenceStorage = profile.profile(mroTuple.getSequenceStorage()); + if (sequenceStorage instanceof MroSequenceStorage) { + ((MroSequenceStorage) sequenceStorage).lookupChanged(); + } else { + throw new IllegalStateException("invalid MRO object for native type \"" + name + "\""); + } + return PNone.NONE; + } + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index 2e4debc425..85872cbf3d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -57,6 +57,7 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.CextUpcallNodeGen; import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.DirectUpcallNodeGen; import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.GetNativeClassNodeGen; +import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.GetTypeMemberNodeGen; import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.IsPointerNodeGen; import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.MaterializeDelegateNodeGen; import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ObjectUpcallNodeGen; @@ -100,6 +101,7 @@ import com.oracle.graal.python.nodes.object.GetClassNode; import com.oracle.graal.python.nodes.object.GetLazyClassNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; +import com.oracle.graal.python.nodes.truffle.PythonTypes; import com.oracle.graal.python.nodes.util.CastToIndexNode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.exception.PythonErrorType; @@ -113,6 +115,7 @@ import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.ForeignAccess; @@ -1608,7 +1611,8 @@ public static GetObjectDictNode create() { } } - public static class GetTypeMemberNode extends GetNativeDictNode { + @TypeSystemReference(PythonTypes.class) + public abstract static class GetTypeMemberNode extends GetNativeDictNode { @Child private ToSulongNode toSulong; @Child private AsPythonObjectNode toJava; @Child private PCallCapiFunction callGetTpDictNode; @@ -1616,7 +1620,7 @@ public static class GetTypeMemberNode extends GetNativeDictNode { @CompilationFinal private IsBuiltinClassProfile isTypeProfile; - private GetTypeMemberNode(String memberName) { + protected GetTypeMemberNode(String memberName) { String getterFuncName = "get_" + memberName; if (!NativeCAPISymbols.isValid(getterFuncName)) { throw new IllegalArgumentException("invalid native member getter function " + getterFuncName); @@ -1624,8 +1628,15 @@ private GetTypeMemberNode(String memberName) { callGetTpDictNode = PCallCapiFunction.create(getterFuncName); } - @Override - public Object execute(Object self) { + @Specialization(guards = "cachedObj.equals(obj)", limit = "1", assumptions = "getNativeClassStableAssumption(cachedObj)") + public Object doCached(@SuppressWarnings("unused") PythonNativeClass obj, + @Cached("obj") @SuppressWarnings("unused") PythonNativeClass cachedObj, + @Cached("doUncached(obj)") Object result) { + return result; + } + + @Specialization + public Object doUncached(Object self) { if (toSulong == null || toJava == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); toSulong = insert(ToSulongNode.create()); @@ -1635,6 +1646,10 @@ public Object execute(Object self) { return toJava.execute(callGetTpDictNode.call(toSulong.execute(self))); } + protected Assumption getNativeClassStableAssumption(PythonNativeClass clazz) { + return getContext().getNativeClassStableAssumption(clazz, true).getAssumption(); + } + private boolean isNativeTypeObject(Object self) { if (getNativeClassNode == null || isTypeProfile == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -1654,7 +1669,7 @@ public static Object doSlowPath(Object self, String memberName) { } public static GetTypeMemberNode create(String typeMember) { - return new GetTypeMemberNode(typeMember); + return GetTypeMemberNodeGen.create(typeMember); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java index f0596d70dc..2eb3da9c62 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java @@ -81,4 +81,16 @@ public int hashCode() { // this is important for the default '__hash__' implementation return Objects.hashCode(object); } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + PythonAbstractNativeObject other = (PythonAbstractNativeObject) obj; + return Objects.equals(object, other.object); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 8ffef819ea..bdaf7d6971 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -540,6 +540,7 @@ private static PythonAbstractClass[] cast(Object[] arr) { @ImportStatic(SpecialMethodNames.class) public abstract static class IsSameTypeNode extends PNodeWithContext { + @Child private CExtNodes.PointerCompareNode pointerCompareNode; protected final boolean fastCheck; @@ -563,8 +564,14 @@ boolean doNativeFast(PythonAbstractNativeObject left, PythonAbstractNativeObject } @Specialization(guards = "!fastCheck") - boolean doNativeSlow(PythonAbstractNativeObject left, PythonAbstractNativeObject right, - @Cached("create(__EQ__)") CExtNodes.PointerCompareNode pointerCompareNode) { + boolean doNativeSlow(PythonAbstractNativeObject left, PythonAbstractNativeObject right) { + if (doNativeFast(left, right)) { + return true; + } + if (pointerCompareNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + pointerCompareNode = insert(CExtNodes.PointerCompareNode.create(SpecialMethodNames.__EQ__)); + } return pointerCompareNode.execute(left, right); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 1e8bc7313e..3384e02136 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -42,6 +42,7 @@ import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.objects.bytes.OpaqueBytes; import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PThreadState; +import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass; import com.oracle.graal.python.builtins.objects.common.HashingStorage; import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.module.PythonModule; @@ -55,6 +56,7 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; +import com.oracle.truffle.api.utilities.CyclicAssumption; public final class PythonContext { @@ -62,6 +64,7 @@ public final class PythonContext { private PythonModule mainModule; private final PythonCore core; private final HashMap atExitHooks = new HashMap<>(); + private final HashMap nativeClassStableAssumptions = new HashMap<>(); private final AtomicLong globalId = new AtomicLong(Integer.MAX_VALUE * 2L + 4L); private final ThreadGroup threadGroup = new ThreadGroup(GRAALPYTHON_THREADS); @@ -340,4 +343,14 @@ public void triggerAsyncActions() { public void registerAsyncAction(Supplier actionSupplier) { handler.registerAction(actionSupplier); } + + @TruffleBoundary + public CyclicAssumption getNativeClassStableAssumption(PythonNativeClass cls, boolean createOnDemand) { + CyclicAssumption assumption = nativeClassStableAssumptions.get(cls); + if (assumption == null && createOnDemand) { + assumption = new CyclicAssumption("Native class " + cls + " stable"); + nativeClassStableAssumptions.put(cls, assumption); + } + return assumption; + } } From 501e97621d4b84e2c376976db2c799d07133be71 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 5 Feb 2019 09:37:31 +0100 Subject: [PATCH 111/202] Add benchmark guest vm config 'sandboxed'. --- mx.graalpython/mx_graalpython.py | 5 ++++- mx.graalpython/mx_graalpython_benchmark.py | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/mx.graalpython/mx_graalpython.py b/mx.graalpython/mx_graalpython.py index c653f3ec89..fa8c6960cf 100644 --- a/mx.graalpython/mx_graalpython.py +++ b/mx.graalpython/mx_graalpython.py @@ -38,7 +38,7 @@ from mx_gate import Task from mx_graalpython_bench_param import PATH_MESO, BENCHMARKS from mx_graalpython_benchmark import PythonBenchmarkSuite, python_vm_registry, CPythonVm, PyPyVm, GraalPythonVm, \ - CONFIGURATION_DEFAULT, CONFIGURATION_EXPERIMENTAL_SPLITTING + CONFIGURATION_DEFAULT, CONFIGURATION_EXPERIMENTAL_SPLITTING, CONFIGURATION_SANDBOXED from mx_unittest import unittest SUITE = mx.suite('graalpython') @@ -850,6 +850,9 @@ def _register_vms(namespace): '-Dgraal.TruffleExperimentalSplitting=true', '-Dgraal.TruffleExperimentalSplittingAllowForcedSplits=false' ]), SUITE, 10) + python_vm_registry.add_vm(GraalPythonVm(config_name=CONFIGURATION_SANDBOXED, extra_polyglot_args=[ + '--llvm.sandboxed', + ]), SUITE, 10) def _register_bench_suites(namespace): diff --git a/mx.graalpython/mx_graalpython_benchmark.py b/mx.graalpython/mx_graalpython_benchmark.py index b6b02edf8f..a4c604eb9e 100644 --- a/mx.graalpython/mx_graalpython_benchmark.py +++ b/mx.graalpython/mx_graalpython_benchmark.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. # Copyright (c) 2013, Regents of the University of California # # All rights reserved. @@ -30,6 +30,7 @@ from os.path import join import mx +import mx_subst import mx_benchmark from mx_benchmark import StdOutRule, java_vm_registry, Vm, GuestVm, VmBenchmarkSuite, AveragingBenchmarkMixin from mx_graalpython_bench_param import HARNESS_PATH @@ -55,6 +56,7 @@ PYTHON_VM_REGISTRY_NAME = "Python" CONFIGURATION_DEFAULT = "default" CONFIGURATION_EXPERIMENTAL_SPLITTING = "experimental_splitting" +CONFIGURATION_SANDBOXED = "sandboxed" DEFAULT_ITERATIONS = 10 @@ -187,13 +189,14 @@ def name(self): class GraalPythonVm(GuestVm): def __init__(self, config_name=CONFIGURATION_DEFAULT, distributions=None, cp_suffix=None, cp_prefix=None, - host_vm=None, extra_vm_args=None): + host_vm=None, extra_vm_args=None, extra_polyglot_args=None): super(GraalPythonVm, self).__init__(host_vm=host_vm) self._config_name = config_name self._distributions = distributions self._cp_suffix = cp_suffix self._cp_prefix = cp_prefix self._extra_vm_args = extra_vm_args + self._extra_polyglot_args = extra_polyglot_args def hosting_registry(self): return java_vm_registry @@ -211,10 +214,15 @@ def run(self, cwd, args): assert isinstance(self._distributions, list), "distributions must be either None or a list" dists += self._distributions + extra_polyglot_args = self._extra_polyglot_args if isinstance(self._extra_polyglot_args, list) else [] if mx.suite("sulong", fatalIfMissing=False): dists.append('SULONG') if mx.suite("sulong-managed", fatalIfMissing=False): dists.append('SULONG_MANAGED') + extra_polyglot_args += [mx_subst.path_substitutions.substitute('--llvm.libraryPath=')] + else: + extra_polyglot_args += [mx_subst.path_substitutions.substitute('--llvm.libraryPath=')] + vm_args = mx.get_runtime_jvm_args(dists, cp_suffix=self._cp_suffix, cp_prefix=self._cp_prefix) if isinstance(self._extra_vm_args, list): @@ -223,7 +231,7 @@ def run(self, cwd, args): "-Dpython.home=%s" % join(SUITE.dir, "graalpython"), "com.oracle.graal.python.shell.GraalPythonMain" ] - cmd = truffle_options + vm_args + args + cmd = truffle_options + vm_args + extra_polyglot_args + args return self.host_vm().run(cwd, cmd) def name(self): @@ -234,7 +242,8 @@ def config_name(self): def with_host_vm(self, host_vm): return self.__class__(config_name=self._config_name, distributions=self._distributions, - cp_suffix=self._cp_suffix, cp_prefix=self._cp_prefix, host_vm=host_vm) + cp_suffix=self._cp_suffix, cp_prefix=self._cp_prefix, host_vm=host_vm, + extra_vm_args=self._extra_vm_args, extra_polyglot_args=self._extra_polyglot_args) # ---------------------------------------------------------------------------------------------------------------------- From 743dd28c16fc94c9995fe59b9d6f08dc7a9e0a81 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 5 Feb 2019 09:38:03 +0100 Subject: [PATCH 112/202] Some minor cleanup. --- .../graal/python/builtins/objects/cext/CExtNodes.java | 4 +--- .../builtins/objects/cext/PythonAbstractNativeObject.java | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index 85872cbf3d..d9f96eb98c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -847,8 +847,6 @@ public abstract static class GetNativeClassNode extends CExtBaseNode { @Child private PCallCapiFunction callGetObTypeNode; @Child private AsPythonObjectNode toJavaNode; - @CompilationFinal private TruffleObject func; - public abstract PythonAbstractClass execute(PythonAbstractNativeObject object); @Specialization(guards = "cachedObject.equals(object)", limit = "1") @@ -1361,7 +1359,7 @@ public static class PCallCapiFunction extends CExtBaseNode { private final String name; private final BranchProfile profile = BranchProfile.create(); - @CompilationFinal TruffleObject receiver; + @CompilationFinal private TruffleObject receiver; public PCallCapiFunction(String name) { this.name = name; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java index 2eb3da9c62..85ef69e9df 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonAbstractNativeObject.java @@ -93,4 +93,10 @@ public boolean equals(Object obj) { PythonAbstractNativeObject other = (PythonAbstractNativeObject) obj; return Objects.equals(object, other.object); } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return String.format("PythonAbstractNativeObject(%s)", object); + } } From b9c92e7b09331e161bf9d112738a885d5dc71f09 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 5 Feb 2019 09:50:32 +0100 Subject: [PATCH 113/202] Rename builtin type 'TruffleObject' to 'foreign'. --- .../oracle/graal/python/builtins/PythonBuiltinClassType.java | 3 ++- .../oracle/graal/python/builtins/objects/type/TypeNodes.java | 5 ----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java index d3bfa351e9..984d5d0ada 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java @@ -29,13 +29,14 @@ import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.object.Shape; public enum PythonBuiltinClassType implements LazyPythonClass { - TruffleObject("truffle_object"), + TruffleObject(BuiltinNames.FOREIGN), Boolean("bool", "builtins"), GetSetDescriptor("get_set_desc"), PArray("array", "array"), diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index bdaf7d6971..65d2ff01dc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -72,7 +72,6 @@ import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetTypeFlagsNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.IsSameTypeNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.IsTypeNodeGen; -import com.oracle.graal.python.nodes.BuiltinNames; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialMethodNames; @@ -274,10 +273,6 @@ public static String doSlowPath(Object obj) { if (obj instanceof PythonManagedClass) { return ((PythonManagedClass) obj).getName(); } else if (obj instanceof PythonBuiltinClassType) { - // TODO(fa): remove this special case - if (obj == PythonBuiltinClassType.TruffleObject) { - return BuiltinNames.FOREIGN; - } return ((PythonBuiltinClassType) obj).getName(); } else if (PGuards.isNativeClass(obj)) { return (String) CExtNodes.GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_NAME); From 54873c3399acf4731e19d7b3a15ff3c488afc8f5 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 5 Feb 2019 10:41:21 +0100 Subject: [PATCH 114/202] Fix: do not use exklusive guards with 'Fallback' annotation. --- .../builtins/objects/type/TypeNodes.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 65d2ff01dc..d3c4f9a554 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -537,7 +537,7 @@ private static PythonAbstractClass[] cast(Object[] arr) { public abstract static class IsSameTypeNode extends PNodeWithContext { @Child private CExtNodes.PointerCompareNode pointerCompareNode; - protected final boolean fastCheck; + private final boolean fastCheck; public IsSameTypeNode(boolean fastCheck) { this.fastCheck = fastCheck; @@ -550,16 +550,11 @@ boolean doManaged(PythonManagedClass left, PythonManagedClass right) { return left == right; } - @Specialization(guards = "fastCheck") - boolean doNativeFast(PythonAbstractNativeObject left, PythonAbstractNativeObject right) { - // This check is a bit dangerous since we cannot be sure about the code that is running. - // Currently, we assume that the pointer object is a Sulong pointer and for this it's - // fine. - return left.object.equals(right.object); - } - - @Specialization(guards = "!fastCheck") + @Specialization boolean doNativeSlow(PythonAbstractNativeObject left, PythonAbstractNativeObject right) { + if (fastCheck) { + return doNativeFast(left, right); + } if (doNativeFast(left, right)) { return true; } @@ -575,6 +570,13 @@ boolean doOther(@SuppressWarnings("unused") Object left, @SuppressWarnings("unus return false; } + private static boolean doNativeFast(PythonAbstractNativeObject left, PythonAbstractNativeObject right) { + // This check is a bit dangerous since we cannot be sure about the code that is running. + // Currently, we assume that the pointer object is a Sulong pointer and for this it's + // fine. + return left.object.equals(right.object); + } + @TruffleBoundary public static boolean doSlowPath(Object left, Object right) { if (left instanceof PythonManagedClass && right instanceof PythonManagedClass) { From 8e6fa8b6ec05984d5ee307fb889f6a36c3499876 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 6 Feb 2019 09:52:54 +0100 Subject: [PATCH 115/202] Avoid interface call on 'LazyPythonClass.getInstanceShape'. --- .../builtins/modules/BuiltinConstructors.java | 27 +++++++++++--- .../builtins/modules/TruffleCextBuiltins.java | 3 +- .../modules/UnicodeDataModuleBuiltins.java | 5 ++- .../builtins/objects/object/PythonObject.java | 3 +- .../objects/type/LazyPythonClass.java | 4 --- .../builtins/objects/type/TypeNodes.java | 35 +++++++++++++++++++ .../runtime/object/PythonObjectFactory.java | 8 ++--- 7 files changed, 69 insertions(+), 16 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index 96215da2f8..801d55a45b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -178,6 +178,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.object.HiddenKey; +import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -1345,6 +1346,7 @@ public abstract static class ObjectNode extends PythonVarargsBuiltinNode { @Child private PCallCapiFunction callNativeGenericNewNode; @Children private CExtNodes.ToSulongNode[] toSulongNodes; @Child private CExtNodes.AsPythonObjectNode asPythonObjectNode; + @Child private TypeNodes.GetInstanceShape getInstanceShapeNode; @Override public final Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeyword[] keywords) throws VarargsBuiltinDirectInvocationNotSupported { @@ -1353,10 +1355,9 @@ public final Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeywo @Specialization Object doDirectConstruct(@SuppressWarnings("unused") PNone ignored, Object[] arguments, @SuppressWarnings("unused") PKeyword[] kwargs) { - if (PGuards.isNativeClass(arguments[0])) { - throw raise(PythonBuiltinClassType.SystemError, "cannot instantiate native class here"); - } - return factory().createPythonObject((LazyPythonClass) arguments[0]); + assert arguments[0] != null; + LazyPythonClass first = (LazyPythonClass) first(arguments); + return factory().createPythonObject(first, getInstanceShape(first)); } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf", "!self.needsNativeAllocation()"}) @@ -1370,7 +1371,7 @@ Object doObjectIndirect(PythonManagedClass self, Object[] varargs, PKeyword[] kw if (varargs.length > 0 || kwargs.length > 0) { // TODO: tfel: this should throw an error only if init isn't overridden } - return factory().createPythonObject(self); + return factory().createPythonObject(self, getInstanceShape(self)); } @Specialization(guards = "self.needsNativeAllocation()") @@ -1422,6 +1423,22 @@ private Object callNativeGenericNewNode(PythonNativeClass self, Object[] varargs return asPythonObjectNode.execute( callNativeGenericNewNode.call(toSulongNodes[0].execute(self), toSulongNodes[1].execute(self), toSulongNodes[2].execute(targs), toSulongNodes[3].execute(dkwargs))); } + + private Shape getInstanceShape(LazyPythonClass clazz) { + if (getInstanceShapeNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getInstanceShapeNode = insert(TypeNodes.GetInstanceShape.create()); + } + return getInstanceShapeNode.execute(clazz); + } + + protected static Object first(Object[] arguments) { + return arguments[0]; + } + + protected static Class getJavaClass(Object arg) { + return ((LazyPythonClass) arg).getClass(); + } } // range(stop) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index 65ee3bbb0e..a72c8dbbf5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -124,6 +124,7 @@ import com.oracle.graal.python.builtins.objects.type.PythonClass; import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetInstanceShape; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; import com.oracle.graal.python.nodes.PGuards; import com.oracle.graal.python.nodes.PNodeWithContext; @@ -209,7 +210,7 @@ public void initialize(PythonCore core) { PythonClass errorHandlerClass = core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, "CErrorHandler", new PythonAbstractClass[]{core.lookupType(PythonBuiltinClassType.PythonObject)}); builtinConstants.put("CErrorHandler", errorHandlerClass); - builtinConstants.put(ERROR_HANDLER, core.factory().createPythonObject(errorHandlerClass)); + builtinConstants.put(ERROR_HANDLER, core.factory().createPythonObject(errorHandlerClass, GetInstanceShape.doSlowPath(errorHandlerClass))); builtinConstants.put(NATIVE_NULL, new PythonNativeNull()); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/UnicodeDataModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/UnicodeDataModuleBuiltins.java index ed3b5a0033..430da81319 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/UnicodeDataModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/UnicodeDataModuleBuiltins.java @@ -51,6 +51,8 @@ import com.oracle.graal.python.builtins.PythonBuiltins; 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.type.PythonBuiltinClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetInstanceShape; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.runtime.PythonCore; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -137,7 +139,8 @@ public static String getUnicodeVersion() { public void initialize(PythonCore core) { super.initialize(core); builtinConstants.put("version", getUnicodeVersion()); - PythonObject ucd_3_2_0 = core.factory().createPythonObject(core.lookupType(PythonBuiltinClassType.PythonObject)); + PythonBuiltinClass objectType = core.lookupType(PythonBuiltinClassType.PythonObject); + PythonObject ucd_3_2_0 = core.factory().createPythonObject(objectType, GetInstanceShape.doSlowPath(objectType)); ucd_3_2_0.setAttribute("unidata_version", "3.2.0"); builtinConstants.put("ucd_3_2_0", ucd_3_2_0); // TODO this is a fake object, just satisfy // pip installer import diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java index 5e7753908e..68440a1404 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java @@ -36,6 +36,7 @@ import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode; import com.oracle.truffle.api.Assumption; @@ -59,7 +60,7 @@ public class PythonObject extends PythonAbstractObject { public PythonObject(LazyPythonClass pythonClass) { assert pythonClass != null : getClass().getSimpleName(); this.pythonClass = pythonClass; - storage = pythonClass.getInstanceShape().newInstance(); + storage = TypeNodes.GetInstanceShape.doSlowPath(pythonClass).newInstance(); } public PythonObject(LazyPythonClass pythonClass, Shape instanceShape) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java index 18fad54529..6c23b4077d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/LazyPythonClass.java @@ -40,9 +40,5 @@ */ package com.oracle.graal.python.builtins.objects.type; -import com.oracle.truffle.api.object.Shape; - public interface LazyPythonClass { - - Shape getInstanceShape(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index d3c4f9a554..5ce9bcd399 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -64,6 +64,7 @@ import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.type.PythonManagedClass.FlagsContainer; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetBaseClassesNodeGen; +import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetInstanceShapeNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroStorageNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetNameNodeGen; import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSubclassesNodeGen; @@ -94,6 +95,7 @@ import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; @@ -749,4 +751,37 @@ public static IsTypeNode create() { return IsTypeNodeGen.create(); } } + + public abstract static class GetInstanceShape extends PNodeWithContext { + + public abstract Shape execute(LazyPythonClass clazz); + + @Specialization + Shape doBuiltinClassType(PythonBuiltinClassType clazz) { + return clazz.getInstanceShape(); + } + + @Specialization + Shape doManagedClass(PythonManagedClass clazz) { + return clazz.getInstanceShape(); + } + + @Fallback + Shape doError(@SuppressWarnings("unused") LazyPythonClass clazz) { + throw raise(PythonBuiltinClassType.SystemError, "cannot get shape of native class"); + } + + public static Shape doSlowPath(LazyPythonClass clazz) { + if (clazz instanceof PythonBuiltinClassType) { + return ((PythonBuiltinClassType) clazz).getInstanceShape(); + } else if (clazz instanceof PythonManagedClass) { + return ((PythonManagedClass) clazz).getInstanceShape(); + } + throw PythonLanguage.getCore().raise(PythonBuiltinClassType.SystemError, "cannot get shape of native class"); + } + + public static GetInstanceShape create() { + return GetInstanceShapeNodeGen.create(); + } + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index b5cdac55b1..d38cfcc243 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -188,12 +188,12 @@ private boolean reportAllocations() { @CompilationFinal private Optional cachedInstanceShape = Optional.empty(); - public PythonObject createPythonObject(LazyPythonClass cls) { + public PythonObject createPythonObject(LazyPythonClass cls, Shape instanceShape) { assert cls != null; Optional cached = cachedInstanceShape; if (cached != null) { if (cached.isPresent()) { - if (cached.get() == cls.getInstanceShape()) { + if (cached.get() == instanceShape) { return trace(new PythonObject(cls, cached.get())); } else { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -201,10 +201,10 @@ public PythonObject createPythonObject(LazyPythonClass cls) { } } else { CompilerDirectives.transferToInterpreterAndInvalidate(); - cachedInstanceShape = Optional.of(cls.getInstanceShape()); + cachedInstanceShape = Optional.of(instanceShape); } } - return trace(new PythonObject(cls, cls.getInstanceShape())); + return trace(new PythonObject(cls, instanceShape)); } public PythonNativeObject createNativeObjectWrapper(TruffleObject obj) { From 14df7677bb9b7ee30c4f105b496c7c140384fe4b Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 6 Feb 2019 10:20:00 +0100 Subject: [PATCH 116/202] locals() in a class scope should return the namespace locals --- .../python/builtins/objects/frame/FrameBuiltins.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java index 62fb546e5e..e68b0a2b4d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java @@ -41,6 +41,7 @@ import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory.DictNodeFactory; import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.traceback.PTraceback; +import com.oracle.graal.python.nodes.function.ClassBodyRootNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; @@ -171,7 +172,13 @@ Object getFromFrame(Frame owner, @Cached("create()") BranchProfile noFrameOnPFrame) { PFrame pFrame = PArguments.getPFrame(owner); if (noPFrame.profile(pFrame == null)) { - pFrame = factory().createPFrame(owner); + Object specialArgument = PArguments.getSpecialArgument(owner); + if (specialArgument instanceof ClassBodyRootNode) { + // the namespace argument stores the locals + pFrame = factory().createPFrame(owner, PArguments.getArgument(owner, 0)); + } else { + pFrame = factory().createPFrame(owner); + } PArguments.setPFrame(owner, pFrame); } else if (!pFrame.hasFrame()) { noFrameOnPFrame.enter(); From db118f92c1e69cf0089a1935c93e890e3213ad92 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 6 Feb 2019 10:20:24 +0100 Subject: [PATCH 117/202] writing to a cell in a class scope should still write the value to the namespace also --- .../nodes/classes/ReadClassAttributeNode.java | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ReadClassAttributeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ReadClassAttributeNode.java index 319b14fe28..47a455d88a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ReadClassAttributeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ReadClassAttributeNode.java @@ -47,6 +47,7 @@ import com.oracle.graal.python.nodes.expression.ExpressionNode; import com.oracle.graal.python.nodes.frame.ReadLocalNode; import com.oracle.graal.python.nodes.frame.ReadNode; +import com.oracle.graal.python.nodes.frame.WriteNode; import com.oracle.graal.python.nodes.statement.StatementNode; import com.oracle.graal.python.nodes.subscript.GetItemNode; import com.oracle.graal.python.runtime.exception.PException; @@ -94,14 +95,12 @@ public StatementNode makeDeleteNode() { @Override public StatementNode makeWriteNode(ExpressionNode rhs) { - ExpressionNode right = rhs; // freevars pass through the special Class scope if (readCellLocal != null && !isFreeVar) { - // TODO (tfel): Is this what's intended? - return ((ReadNode) readCellLocal).makeWriteNode(rhs); + return new WriteClassAttributeCellNode((ReadNode) readCellLocal, (ReadNode) getNsItem, rhs); } else { // assignments always got to the innermost scope - return ((ReadNode) getNsItem).makeWriteNode(right); + return ((ReadNode) getNsItem).makeWriteNode(rhs); } } @@ -132,4 +131,31 @@ Object read(VirtualFrame frame, return readGlobal.execute(frame); } } + + private static class WriteClassAttributeCellNode extends StatementNode implements WriteNode { + @Child private WriteNode writeCellLocal; + @Child private WriteNode writeNsItem; + @Child private ExpressionNode right; + + WriteClassAttributeCellNode(ReadNode readCellLocal, ReadNode getNsItem, ExpressionNode rhs) { + writeCellLocal = (WriteNode) readCellLocal.makeWriteNode(null); + writeNsItem = (WriteNode) getNsItem.makeWriteNode(null); + right = rhs; + } + + public ExpressionNode getRhs() { + return right; + } + + public void doWrite(VirtualFrame frame, Object value) { + writeCellLocal.doWrite(frame, value); + writeNsItem.doWrite(frame, value); + } + + @Override + public void executeVoid(VirtualFrame frame) { + Object value = right.execute(frame); + doWrite(frame, value); + } + } } From 5796ee706a617c2880a4c7c77ea05e92fa0023f7 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 6 Feb 2019 10:21:27 +0100 Subject: [PATCH 118/202] the class definition epilogue should really be a prologue, since __module__ and __qualname__ are available during body execution --- ...tionEpilogNode.java => ClassDefinitionPrologueNode.java} | 6 +++--- .../oracle/graal/python/parser/PythonTreeTranslator.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/{ClassDefinitionEpilogNode.java => ClassDefinitionPrologueNode.java} (95%) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionEpilogNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionPrologueNode.java similarity index 95% rename from graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionEpilogNode.java rename to graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionPrologueNode.java index 5c87108ce6..6b5f6d9a31 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionEpilogNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionPrologueNode.java @@ -50,18 +50,18 @@ import com.oracle.graal.python.nodes.subscript.SetItemIfNotPresentNode; import com.oracle.truffle.api.frame.VirtualFrame; -public class ClassDefinitionEpilogNode extends StatementNode { +public class ClassDefinitionPrologueNode extends StatementNode { @Child private ReadGlobalOrBuiltinNode readGlobalNameNode = ReadGlobalOrBuiltinNode.create(__NAME__); @Child private ReadIndexedArgumentNode readPrimaryArgNode = ReadIndexedArgumentNode.create(0); @Child private SetItemIfNotPresentNode setItemIfNotPresentNode = SetItemIfNotPresentNode.create(); private final String qualName; - public ClassDefinitionEpilogNode() { + public ClassDefinitionPrologueNode() { this(null); } - public ClassDefinitionEpilogNode(String qualName) { + public ClassDefinitionPrologueNode(String qualName) { this.qualName = qualName; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java index 8c85dedee0..45e4604d81 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java @@ -59,7 +59,7 @@ import com.oracle.graal.python.nodes.argument.ReadDefaultArgumentNode; import com.oracle.graal.python.nodes.attributes.GetAttributeNode; import com.oracle.graal.python.nodes.call.PythonCallNode; -import com.oracle.graal.python.nodes.classes.ClassDefinitionEpilogNode; +import com.oracle.graal.python.nodes.classes.ClassDefinitionPrologueNode; import com.oracle.graal.python.nodes.control.BlockNode; import com.oracle.graal.python.nodes.control.ForNode; import com.oracle.graal.python.nodes.control.GetIteratorNode; @@ -1855,7 +1855,7 @@ protected ExpressionNode asClassBody(Object accept, String qualName) { environment.createLocal(__DOC__); body.set(0, environment.findVariable(__DOC__).makeWriteNode((ExpressionNode) body.get(0))); } - body.add(new ClassDefinitionEpilogNode(qualName)); + body.add(0, new ClassDefinitionPrologueNode(qualName)); return new ReturnTargetNode(asBlock(body), factory.createNullLiteral()); } From cec4fa5fac0dce3f4f6a6b07856ae49f8f560d83 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 6 Feb 2019 10:23:34 +0100 Subject: [PATCH 119/202] add test for class body scope --- .../src/tests/test_scope.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_scope.py b/graalpython/com.oracle.graal.python.test/src/tests/test_scope.py index 9b3c586f6b..d9decea102 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_scope.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_scope.py @@ -906,3 +906,29 @@ def my_obj(): assert set(my_obj.__code__.co_cellvars) == set() assert set(my_obj.__code__.co_freevars) == {'my_obj', 'y'} + + +def test_classbody_scope(): + class A(): + ranges = [(1, 10)] + + class B(): + ranges = [(2, 12)] + + class C(): + ranges = [ ] + + class CA(): + ranges = [(3, 13)] + + locs = locals() + + class D(B, C): + pass + + + A.C.ranges = (A.C.CA.ranges) + assert A.C.ranges == A.C.CA.ranges == [(3, 13)] + locs = list(A.locs.keys()) + for k in ["__module__", "__qualname__", "ranges", "B", "C", "locs", "D"]: + assert k in locs, locs From 228df7ffd93c22553ae0bf094648a9f02e56da1a Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 6 Feb 2019 11:30:24 +0100 Subject: [PATCH 120/202] Avoid AttributeError when raising OSError. --- graalpython/lib-graalpython/exceptions.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/graalpython/lib-graalpython/exceptions.py b/graalpython/lib-graalpython/exceptions.py index 7ab8deea3f..c9bb2d7daf 100644 --- a/graalpython/lib-graalpython/exceptions.py +++ b/graalpython/lib-graalpython/exceptions.py @@ -137,6 +137,10 @@ def _oserror_use_init(subtype): def _oserror_init(self, *arg): narg = len(arg) + self.errno = None + self.strerror = None + self.filename = None + self.filename2 = None if (2 <= narg and narg <= 5): self.errno = arg[0] self.strerror = arg[1] From 9ca6c81997329eead49ed5c506af614ab68576e7 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 6 Feb 2019 13:57:21 +0100 Subject: [PATCH 121/202] update copyrights --- .../com.oracle.graal.python.test/src/tests/test_scope.py | 2 +- .../graal/python/nodes/classes/ClassDefinitionPrologueNode.java | 2 +- .../graal/python/nodes/classes/ReadClassAttributeNode.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_scope.py b/graalpython/com.oracle.graal.python.test/src/tests/test_scope.py index d9decea102..356f42a066 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_scope.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_scope.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionPrologueNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionPrologueNode.java index 6b5f6d9a31..c7372bc9fa 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionPrologueNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ClassDefinitionPrologueNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ReadClassAttributeNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ReadClassAttributeNode.java index 47a455d88a..91516187cd 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ReadClassAttributeNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ReadClassAttributeNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 From cf1b7b52a10626311086f04764a4dcb1ab428c82 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 09:31:14 +0100 Subject: [PATCH 122/202] add internal and undocumented way of connecting with the java debugger --- .../graal/python/shell/GraalPythonMain.java | 8 ++- .../builtins/modules/FcntlModuleBuiltins.java | 57 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/FcntlModuleBuiltins.java diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java index 87ecbf0c45..e6bc8a044d 100644 --- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java +++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java @@ -158,6 +158,12 @@ protected List preprocessArguments(List givenArgs, Map getCmdline(List args, List subProcessDefs) { cmd.add("-cp"); cmd.add(ManagementFactory.getRuntimeMXBean().getClassPath()); for (String subProcArg : subProcessDefs) { - assert subProcArg.startsWith("D"); + assert subProcArg.startsWith("D") || subProcArg.startsWith("X"); cmd.add("-" + subProcArg); } cmd.add(GraalPythonMain.class.getName()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/FcntlModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/FcntlModuleBuiltins.java new file mode 100644 index 0000000000..33567a712f --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/FcntlModuleBuiltins.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.builtins.modules; + +import java.util.ArrayList; +import java.util.List; + +import com.oracle.graal.python.builtins.CoreFunctions; +import com.oracle.graal.python.builtins.PythonBuiltins; +import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; +import com.oracle.truffle.api.dsl.NodeFactory; + +@CoreFunctions(defineModule = "fcntl") +public class FcntlModuleBuiltins extends PythonBuiltins { + @Override + protected List> getNodeFactories() { + return new ArrayList<>(); + } +} From 4fb63f46f8308e97b0b9b08f3224a2cfbe9956c5 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 09:31:49 +0100 Subject: [PATCH 123/202] add fcntl module --- .../src/com/oracle/graal/python/builtins/Python3Core.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java index 4596baf03d..8a4c28e9d6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java @@ -57,6 +57,7 @@ import com.oracle.graal.python.builtins.modules.CtypesModuleBuiltins; import com.oracle.graal.python.builtins.modules.ErrnoModuleBuiltins; import com.oracle.graal.python.builtins.modules.FaulthandlerModuleBuiltins; +import com.oracle.graal.python.builtins.modules.FcntlModuleBuiltins; import com.oracle.graal.python.builtins.modules.FunctoolsModuleBuiltins; import com.oracle.graal.python.builtins.modules.GcModuleBuiltins; import com.oracle.graal.python.builtins.modules.IOModuleBuiltins; @@ -329,7 +330,8 @@ private static final PythonBuiltins[] initializeBuiltins(Env env) { new ZipImporterBuiltins(), new ZipImportModuleBuiltins(), new ZLibModuleBuiltins(), - new MMapModuleBuiltins())); + new MMapModuleBuiltins(), + new FcntlModuleBuiltins())); if (!TruffleOptions.AOT) { ServiceLoader providers = ServiceLoader.load(PythonBuiltins.class); for (PythonBuiltins builtin : providers) { From 7d2411c93106019d10f6b60f2f152ef36c61e115 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 09:32:02 +0100 Subject: [PATCH 124/202] return a constant ctermid for now --- .../python/builtins/modules/PosixModuleBuiltins.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index 0069dd36ad..1ee097ba5c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -1863,4 +1863,13 @@ String getStrError(int errno) { return result; } } + + @Builtin(name = "ctermid", fixedNumOfPositionalArgs = 0) + @GenerateNodeFactory + abstract static class CtermId extends PythonBuiltinNode { + @Specialization + String ctermid() { + return "/dev/tty"; + } + } } From 4ade31161fe06cec45ddc466f1962aedaafcd572 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 09:32:22 +0100 Subject: [PATCH 125/202] in the generic case for type.__call__, support PythonBuiltinClassTypes --- .../graal/python/builtins/objects/type/TypeBuiltins.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 66fa11a48f..fbbf029b54 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -219,7 +219,14 @@ protected Object doItUnboxed(VirtualFrame frame, @SuppressWarnings("unused") PNo @Specialization(replaces = "doItUnboxed") protected Object doItUnboxedIndirect(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords) { Object self = arguments[0]; - return op(frame, (PythonAbstractClass) self, arguments, keywords, false); + if (self instanceof PythonAbstractClass) { + return op(frame, (PythonAbstractClass) self, arguments, keywords, false); + } else if (self instanceof PythonBuiltinClassType) { + PythonBuiltinClass actual = getContext().getCore().lookupType((PythonBuiltinClassType) self); + return op(frame, actual, arguments, keywords, false); + } else { + throw raise(TypeError, "descriptor '__call__' requires a 'type' object but received a '%p'", self); + } } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf"}) From 52de27c4828076b6dab380cd768af109f4464422 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 10:04:45 +0100 Subject: [PATCH 126/202] add global hex function --- .../builtins/modules/BuiltinFunctions.java | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index eff0fbaaab..1b88497173 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -29,6 +29,8 @@ import static com.oracle.graal.python.builtins.objects.PNotImplemented.NOT_IMPLEMENTED; import static com.oracle.graal.python.nodes.BuiltinNames.ABS; import static com.oracle.graal.python.nodes.BuiltinNames.BIN; +import static com.oracle.graal.python.nodes.BuiltinNames.BREAKPOINT; +import static com.oracle.graal.python.nodes.BuiltinNames.BREAKPOINTHOOK; import static com.oracle.graal.python.nodes.BuiltinNames.CALLABLE; import static com.oracle.graal.python.nodes.BuiltinNames.CHR; import static com.oracle.graal.python.nodes.BuiltinNames.COMPILE; @@ -39,6 +41,7 @@ import static com.oracle.graal.python.nodes.BuiltinNames.EXEC; import static com.oracle.graal.python.nodes.BuiltinNames.GETATTR; import static com.oracle.graal.python.nodes.BuiltinNames.HASH; +import static com.oracle.graal.python.nodes.BuiltinNames.HEX; import static com.oracle.graal.python.nodes.BuiltinNames.ID; import static com.oracle.graal.python.nodes.BuiltinNames.ISINSTANCE; import static com.oracle.graal.python.nodes.BuiltinNames.ISSUBCLASS; @@ -55,8 +58,6 @@ import static com.oracle.graal.python.nodes.BuiltinNames.ROUND; import static com.oracle.graal.python.nodes.BuiltinNames.SETATTR; import static com.oracle.graal.python.nodes.BuiltinNames.SUM; -import static com.oracle.graal.python.nodes.BuiltinNames.BREAKPOINT; -import static com.oracle.graal.python.nodes.BuiltinNames.BREAKPOINTHOOK; import static com.oracle.graal.python.nodes.BuiltinNames.__BUILTIN__; import static com.oracle.graal.python.nodes.BuiltinNames.__DEBUG__; import static com.oracle.graal.python.nodes.BuiltinNames.__DUMP_TRUFFLE_AST__; @@ -170,8 +171,8 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.debug.Debugger; import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.debug.Debugger; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; @@ -351,6 +352,60 @@ protected static OctNode create() { } } + // hex(object) + @Builtin(name = HEX, fixedNumOfPositionalArgs = 1) + @TypeSystemReference(PythonArithmeticTypes.class) + @GenerateNodeFactory + public abstract static class HexNode extends PythonUnaryBuiltinNode { + + public abstract String executeObject(Object x); + + @TruffleBoundary + private static String buildString(boolean isNegative, String number) { + StringBuilder sb = new StringBuilder(); + if (isNegative) { + sb.append('-'); + } + sb.append("0x"); + sb.append(number); + return sb.toString(); + } + + @Specialization + public String doL(long x) { + return buildString(x < 0, longToHexString(x)); + } + + @TruffleBoundary + private static String longToHexString(long x) { + return Long.toHexString(Math.abs(x)); + } + + @Specialization + public String doD(double x) { + throw raise(TypeError, "'%p' object cannot be interpreted as an integer", x); + } + + @Specialization + @TruffleBoundary + public String doPI(PInt x) { + BigInteger value = x.getValue(); + return buildString(value.compareTo(BigInteger.ZERO) == -1, value.abs().toString(8)); + } + + @Specialization + public String doO(Object x, + @Cached("create()") CastToIntegerFromIndexNode toIntNode, + @Cached("create()") OctNode recursiveNode) { + Object value = toIntNode.execute(x); + return recursiveNode.executeObject(value); + } + + protected static OctNode create() { + return BuiltinFunctionsFactory.OctNodeFactory.create(); + } + } + // callable(object) @Builtin(name = CALLABLE, fixedNumOfPositionalArgs = 1) @GenerateNodeFactory From 9469aede9e5bdca4a1e6ea578e09c49eba6b1387 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 10:04:56 +0100 Subject: [PATCH 127/202] support str.splitlines keyword argument --- .../graal/python/builtins/objects/str/StringBuiltins.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringBuiltins.java index a1a0bb6173..f084b12aa7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringBuiltins.java @@ -1291,10 +1291,10 @@ private PList rsplitfields(String s, int maxsplit) { } // str.splitlines([keepends]) - @Builtin(name = "splitlines", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2) + @Builtin(name = "splitlines", fixedNumOfPositionalArgs = 1, keywordArguments = {"keepends"}) @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) - public abstract static class SplitLinesNode extends PythonBuiltinNode { + public abstract static class SplitLinesNode extends PythonBinaryBuiltinNode { @Child private ListAppendNode appendNode = ListAppendNode.create(); @Child private CastToBooleanNode keepEndsNode = CastToBooleanNode.createIfTrueNode(); From dbe7a05a4b0ceab539c4e519780df531120c5124 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 6 Feb 2019 17:43:43 +0100 Subject: [PATCH 128/202] Add missing @ExplodeLoop in 'KeywordArgumentsNode'. --- .../argument/keywords/KeywordArgumentsNode.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/argument/keywords/KeywordArgumentsNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/argument/keywords/KeywordArgumentsNode.java index 3fbbbfc0db..d273a2daf0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/argument/keywords/KeywordArgumentsNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/argument/keywords/KeywordArgumentsNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. @@ -54,7 +54,7 @@ public static KeywordArgumentsNode create(ExpressionNode[] arguments, Expression public abstract PKeyword[] execute(VirtualFrame frame); - @Specialization(guards = "starargs.length == cachedLen", limit = "getVariableArgumentInlineCacheLimit()") + @Specialization(guards = {"starargs.length == cachedLen", "starargs.length < 32"}, limit = "getVariableArgumentInlineCacheLimit()") @ExplodeLoop PKeyword[] makeKeywords(VirtualFrame frame, PKeyword[] starargs, @Cached("starargs.length") int cachedLen) { @@ -83,6 +83,7 @@ PKeyword[] makeKeywords(VirtualFrame frame, PKeyword[] starargs, } @Specialization(replaces = "makeKeywords") + @ExplodeLoop PKeyword[] makeKeywordsUncached(VirtualFrame frame, PKeyword[] starargs) { int length = arguments.length; CompilerAsserts.partialEvaluationConstant(length); @@ -97,9 +98,7 @@ PKeyword[] makeKeywordsUncached(VirtualFrame frame, PKeyword[] starargs) { } } - for (int i = 0; i < starargs.length; i++) { - keywords[arguments.length + i] = starargs[i]; - } + copyStarargs(keywords, starargs); if (reshape > 0) { return compactNode.execute(keywords, reshape); @@ -107,4 +106,12 @@ PKeyword[] makeKeywordsUncached(VirtualFrame frame, PKeyword[] starargs) { return keywords; } } + + private void copyStarargs(PKeyword[] keywords, PKeyword[] starargs) { + // This loop has deliberately been moved out such that it won't be exploded since the length + // of iterations is not constant. + for (int i = 0; i < starargs.length; i++) { + keywords[arguments.length + i] = starargs[i]; + } + } } From 72b6c3cc1137ef1500469e1a8d2ed4a9ab8f48cc Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 10:28:26 +0100 Subject: [PATCH 129/202] user subclasses are heaptypes. use a basic way to check this --- .../graal/python/builtins/objects/type/TypeNodes.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java index 5ce9bcd399..df46b38706 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java @@ -102,6 +102,7 @@ public abstract class TypeNodes { public abstract static class GetTypeFlagsNode extends PNodeWithContext { + private static final int HEAPTYPE = 1 << 9; public abstract long execute(PythonAbstractClass clazz); @@ -113,7 +114,7 @@ long doInitialized(PythonManagedClass clazz) { @Specialization long doGeneric(PythonManagedClass clazz) { if (!isInitialized(clazz)) { - return getValue(clazz.getFlagsContainer()); + return getValue(clazz, clazz.getFlagsContainer()); } return clazz.getFlagsContainer().flags; } @@ -125,12 +126,16 @@ long doNative(PythonNativeClass clazz, } @TruffleBoundary - private static long getValue(FlagsContainer fc) { + private static long getValue(PythonManagedClass clazz, FlagsContainer fc) { // This method is only called from C code, i.e., the flags of the initial super class // must be available. if (fc.initialDominantBase != null) { fc.flags = doSlowPath(fc.initialDominantBase); fc.initialDominantBase = null; + if (clazz instanceof PythonClass) { + // user classes are heap types + fc.flags |= HEAPTYPE; + } } return fc.flags; } @@ -142,7 +147,7 @@ public static long doSlowPath(PythonAbstractClass clazz) { if (isInitialized(mclazz)) { return mclazz.getFlagsContainer().flags; } else { - return getValue(mclazz.getFlagsContainer()); + return getValue(mclazz, mclazz.getFlagsContainer()); } } else if (PGuards.isNativeClass(clazz)) { return doNativeGeneric((PythonNativeClass) clazz, createReadNode()); From d5ef994754ec6e55c100aff5dbbb33661e2d1265 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 10:29:12 +0100 Subject: [PATCH 130/202] expose the `__flags__` attribute on types --- .../python/builtins/objects/type/TypeBuiltins.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index fbbf029b54..c2c474bafd 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -876,4 +876,15 @@ Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @Su throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type"); } } + + @Builtin(name = "__flags__", fixedNumOfPositionalArgs = 1, isGetter = true) + @GenerateNodeFactory + static abstract class FlagsNode extends PythonUnaryBuiltinNode { + @Child TypeNodes.GetTypeFlagsNode getFlagsNode = TypeNodes.GetTypeFlagsNode.create(); + + @Specialization + Object flags(PythonAbstractClass self) { + return getFlagsNode.execute(self); + } + } } From 98436548942dc6ff5eeec3d505338688b886ccd3 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 10:34:44 +0100 Subject: [PATCH 131/202] copy-paste error --- .../graal/python/builtins/modules/BuiltinFunctions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 1b88497173..28addcec15 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -396,13 +396,13 @@ public String doPI(PInt x) { @Specialization public String doO(Object x, @Cached("create()") CastToIntegerFromIndexNode toIntNode, - @Cached("create()") OctNode recursiveNode) { + @Cached("create()") HexNode recursiveNode) { Object value = toIntNode.execute(x); return recursiveNode.executeObject(value); } - protected static OctNode create() { - return BuiltinFunctionsFactory.OctNodeFactory.create(); + protected static HexNode create() { + return BuiltinFunctionsFactory.HexNodeFactory.create(); } } From 8b29d83f967d6eb12c29b50dfc71577f1018fde7 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 10:39:49 +0100 Subject: [PATCH 132/202] minor cleanup --- .../graal/python/builtins/modules/FcntlModuleBuiltins.java | 2 +- .../graal/python/builtins/objects/type/TypeBuiltins.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/FcntlModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/FcntlModuleBuiltins.java index 33567a712f..a50f2ca713 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/FcntlModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/FcntlModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index c2c474bafd..e12d3db217 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -219,10 +219,10 @@ protected Object doItUnboxed(VirtualFrame frame, @SuppressWarnings("unused") PNo @Specialization(replaces = "doItUnboxed") protected Object doItUnboxedIndirect(VirtualFrame frame, @SuppressWarnings("unused") PNone noSelf, Object[] arguments, PKeyword[] keywords) { Object self = arguments[0]; - if (self instanceof PythonAbstractClass) { + if (PGuards.isClass(self)) { return op(frame, (PythonAbstractClass) self, arguments, keywords, false); } else if (self instanceof PythonBuiltinClassType) { - PythonBuiltinClass actual = getContext().getCore().lookupType((PythonBuiltinClassType) self); + PythonBuiltinClass actual = getBuiltinPythonClass((PythonBuiltinClassType) self); return op(frame, actual, arguments, keywords, false); } else { throw raise(TypeError, "descriptor '__call__' requires a 'type' object but received a '%p'", self); From ce750215dc4ce7e2106c3d67935382091de4bb93 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 11:40:32 +0100 Subject: [PATCH 133/202] make sure we always have some scope in single input --- .../oracle/graal/python/parser/ScopeTranslator.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/ScopeTranslator.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/ScopeTranslator.java index 084eb7b793..42a4208f91 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/ScopeTranslator.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/ScopeTranslator.java @@ -76,17 +76,15 @@ public T visitFile_input(Python3Parser.File_inputContext ctx) { @Override public T visitSingle_input(Single_inputContext ctx) { - if (interactive) { - ctx.scope = environment.pushScope(ctx, ScopeInfo.ScopeKind.Module); - } else if (curInlineLocals != null) { + if (!interactive && curInlineLocals != null) { ctx.scope = environment.pushScope(ctx, ScopeInfo.ScopeKind.Function, curInlineLocals); + } else { + ctx.scope = environment.pushScope(ctx, ScopeInfo.ScopeKind.Module); } try { return super.visitSingle_input(ctx); } finally { - if (interactive || curInlineLocals != null) { - environment.popScope(); - } + environment.popScope(); } } From e20afecb9915ed64e8cf4753b88571691ca2f09f Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 7 Feb 2019 11:45:58 +0100 Subject: [PATCH 134/202] use sys.displayhook when running interactively, rather than printing directly --- .../graal/python/shell/GraalPythonMain.java | 6 ++++- .../oracle/graal/python/PythonLanguage.java | 8 ++++++- graalpython/lib-graalpython/sys.py | 24 +++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java index 87ecbf0c45..f58cbfadd6 100644 --- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java +++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java @@ -608,7 +608,11 @@ public int readEvalPrint(Context context, ConsoleHandler consoleHandler) { while (true) { // processing subsequent lines while input is incomplete lastStatus = 0; try { - context.eval(Source.newBuilder(getLanguageId(), sb.toString(), "").interactive(true).buildLiteral()); + Value result = context.eval(Source.newBuilder(getLanguageId(), sb.toString(), "").interactive(true).buildLiteral()); + Value displayhook = sys.getMember("displayhook"); + if (displayhook != null && displayhook.canExecute()) { + displayhook.execute(result); + } } catch (PolyglotException e) { if (continuePrompt == null) { continuePrompt = doEcho ? sys.getMember("ps2").asString() : null; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index 2b4c4e81c4..0e280a55bc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -343,7 +343,13 @@ public static PythonCore getCore() { @Override protected boolean isVisible(PythonContext context, Object value) { - return value != PNone.NONE && value != PNone.NO_VALUE; + if (PythonOptions.getOption(context, PythonOptions.TerminalIsInteractive)) { + // if we run through our own launcher, the sys.__displayhook__ would provide the + // printing + return false; + } else { + return value != PNone.NONE && value != PNone.NO_VALUE; + } } @Override diff --git a/graalpython/lib-graalpython/sys.py b/graalpython/lib-graalpython/sys.py index 2fb58cde88..ded6698aaf 100644 --- a/graalpython/lib-graalpython/sys.py +++ b/graalpython/lib-graalpython/sys.py @@ -204,3 +204,27 @@ def breakpointhook(*args, **kws): @__builtin__ def getrecursionlimit(): return 1000 + + +@__builtin__ +def displayhook(value): + if value is None: + return + builtins = modules['builtins'] + # Set '_' to None to avoid recursion + builtins._ = None + text = repr(value) + try: + stdout.write(text) + except UnicodeEncodeError: + bytes = text.encode(stdout.encoding, 'backslashreplace') + if hasattr(stdout, 'buffer'): + stdout.buffer.write(bytes) + else: + text = bytes.decode(stdout.encoding, 'strict') + stdout.write(text) + stdout.write("\n") + builtins._ = value + + +__displayhook__ = displayhook From 5d64e88e557f0e807c4a49a4d14285e330eeb32e Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 7 Feb 2019 13:04:32 +0100 Subject: [PATCH 135/202] Move logic of 'ADD_MEMBER' and 'ADD_SLOT' to C functions. --- .../src/typeobject.c | 72 +++++++++---------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/typeobject.c b/graalpython/com.oracle.graal.python.cext/src/typeobject.c index 5e151b6918..a0bceaa887 100644 --- a/graalpython/com.oracle.graal.python.cext/src/typeobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/typeobject.c @@ -147,10 +147,8 @@ static PyObject* wrap_pow(ternaryfunc f, ...) { int nargs = polyglot_get_arg_count(); switch(nargs) { case 3: - // TODO use 'native_to_java' on result return f(polyglot_get_arg(1), polyglot_get_arg(2), Py_None); case 4: - // TODO use 'native_to_java' on result return f(polyglot_get_arg(1), polyglot_get_arg(2), polyglot_get_arg(3)); } return Py_NoValue; @@ -231,21 +229,36 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS; } - -// TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between // TODO support member flags other than READONLY UPCALL_ID(AddMember); +static void add_member(PyTypeObject* cls, PyObject* type_dict, PyObject* mname, int mtype, Py_ssize_t moffset, int mflags, char* mdoc) { + UPCALL_CEXT_VOID(_jls_AddMember, + cls, + native_to_java(type_dict), + native_to_java(mname), + mtype, + moffset, + native_to_java(((mflags & READONLY) == 0) ? Py_True : Py_False), + polyglot_from_string(mdoc ? mdoc : "", SRC_CS) + ); +} + +static void add_method_or_slot(PyTypeObject* cls, PyObject* type_dict, char* name, void* meth, void* clanding, int flags, char* doc) { + polyglot_invoke(PY_TRUFFLE_CEXT, + "AddFunction", + cls, + native_to_java(type_dict), + polyglot_from_string((name), SRC_CS), + (meth), + (clanding), + get_method_flags_wrapper(flags), + polyglot_from_string(doc, SRC_CS), + (flags) > 0 && ((flags) & METH_CLASS) != 0, + (flags) > 0 && ((flags) & METH_STATIC) != 0); +} + #define ADD_MEMBER(__javacls__, __tpdict__, __mname__, __mtype__, __moffset__, __mflags__, __mdoc__) \ - do { \ - UPCALL_CEXT_VOID(_jls_AddMember, \ - (__javacls__), \ - native_to_java(__tpdict__), \ - (__mname__), \ - (__mtype__), \ - (__moffset__), \ - native_to_java((((__mflags__) & READONLY) == 0) ? Py_True : Py_False), \ - polyglot_from_string((__mdoc__) ? (__mdoc__) : "", SRC_CS)); \ -} while (0) + add_member((__javacls__), (__tpdict__), (__mname__), (__mtype__), (__moffset__), (__mflags__), (__mdoc__)) UPCALL_ID(PyTruffle_Type_Slots); @@ -261,20 +274,10 @@ int PyType_Ready(PyTypeObject* cls) { #define ADD_METHOD(m) ADD_METHOD_OR_SLOT(m.ml_name, get_method_flags_cwrapper(m.ml_flags), m.ml_meth, m.ml_flags, m.ml_doc) #define ADD_SLOT(name, meth, flags) ADD_METHOD_OR_SLOT(name, get_method_flags_cwrapper(flags), meth, flags, name) #define ADD_SLOT_CONV(name, clanding, meth, flags) ADD_METHOD_OR_SLOT(name, clanding, meth, flags, name) -#define ADD_METHOD_OR_SLOT(name, clanding, meth, flags, doc) \ - if (meth) { \ - polyglot_invoke(PY_TRUFFLE_CEXT, \ - "AddFunction", \ - cls, \ - native_to_java(dict), \ - polyglot_from_string((name), SRC_CS), \ - (meth), \ - (clanding), \ - get_method_flags_wrapper(flags), \ - polyglot_from_string(doc, SRC_CS), \ - (flags) > 0 && ((flags) & METH_CLASS) != 0, \ - (flags) > 0 && ((flags) & METH_STATIC) != 0); \ - } +#define ADD_METHOD_OR_SLOT(__name__, __clanding__, __meth__, __flags__, __doc__) \ + if (__meth__) { \ + add_method_or_slot(cls, dict, (__name__), (__meth__), (__clanding__), (__flags__), (__doc__)); \ + } // https://docs.python.org/3/c-api/typeobj.html#Py_TPFLAGS_READY if ((cls->tp_flags & Py_TPFLAGS_READY) || (cls->tp_flags & Py_TPFLAGS_READYING)) { @@ -544,7 +547,7 @@ int PyType_Ready(PyTypeObject* cls) { UPCALL_ID(PyTruffle_Type_Modified); void PyType_Modified(PyTypeObject* type) { - UPCALL_CEXT_VOID(_jls_PyTruffle_Type_Modified, native_to_java(type), polyglot_from_string(type->tp_name, SRC_CS), native_to_java(type->tp_mro)); + UPCALL_CEXT_VOID(_jls_PyTruffle_Type_Modified, native_type_to_java(type), polyglot_from_string(type->tp_name, SRC_CS), native_to_java(type->tp_mro)); } MUST_INLINE static int valid_identifier(PyObject *s) { @@ -557,16 +560,7 @@ MUST_INLINE static int valid_identifier(PyObject *s) { return 1; } -/* -typedef struct PyMemberDef { - char *name; - int type; - Py_ssize_t offset; - int flags; - char *doc; -} PyMemberDef; - - */ +/* Add get-set descriptors for slots provided in 'slotsTuple'. */ Py_ssize_t PyTruffle_Type_AddSlots(PyTypeObject* cls, PyObject* slotsTuple) { int i; Py_ssize_t cur_offset = cls->tp_basicsize; From 40209318c808f2801cacbb6d0ed72e25d2a9c7ae Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 8 Feb 2019 00:10:41 +0100 Subject: [PATCH 136/202] fix using the displayhook when we run through our own launcher and add test --- .../graal/python/shell/GraalPythonMain.java | 6 +--- .../src/tests/test_parser.py | 16 +++++++++ .../oracle/graal/python/PythonLanguage.java | 30 +++++++++++------ .../graal/python/nodes/BuiltinNames.java | 1 + .../graal/python/nodes/NodeFactory.java | 5 +++ .../nodes/statement/PrintExpressionNode.java | 33 +++++++++++++++++++ .../graal/python/parser/PythonParserImpl.java | 11 +++---- .../python/parser/PythonTreeTranslator.java | 26 ++++++++------- 8 files changed, 96 insertions(+), 32 deletions(-) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java index f58cbfadd6..87ecbf0c45 100644 --- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java +++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java @@ -608,11 +608,7 @@ public int readEvalPrint(Context context, ConsoleHandler consoleHandler) { while (true) { // processing subsequent lines while input is incomplete lastStatus = 0; try { - Value result = context.eval(Source.newBuilder(getLanguageId(), sb.toString(), "").interactive(true).buildLiteral()); - Value displayhook = sys.getMember("displayhook"); - if (displayhook != null && displayhook.canExecute()) { - displayhook.execute(result); - } + context.eval(Source.newBuilder(getLanguageId(), sb.toString(), "").interactive(true).buildLiteral()); } catch (PolyglotException e) { if (continuePrompt == null) { continuePrompt = doEcho ? sys.getMember("ps2").asString() : null; diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_parser.py b/graalpython/com.oracle.graal.python.test/src/tests/test_parser.py index 44646baf3f..82719d3ab6 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_parser.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_parser.py @@ -98,3 +98,19 @@ def func(): pass return func assert run_me() == "just a string, not func", run_me() + + +def test_single_input_non_interactive(): + import sys + oldhook = sys.displayhook + got_value = None + def newhook(value): + nonlocal got_value + got_value = value + sys.displayhook = newhook + try: + code = compile('sum([1, 2, 3])', '', 'single') + assert exec(code) == None + assert got_value == 6 + finally: + sys.displayhook = oldhook diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index 0e280a55bc..faec67b538 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -233,7 +233,7 @@ protected CallTarget parse(ParsingRequest request) { if (core.isInitialized()) { context.initializeMainModule(source.getPath()); } - RootNode root = doParse(core, source); + RootNode root = doParse(context, source); if (core.isInitialized()) { return Truffle.getRuntime().createCallTarget(new TopLevelExceptionHandler(this, root)); } else { @@ -241,9 +241,25 @@ protected CallTarget parse(ParsingRequest request) { } } - private RootNode doParse(PythonCore pythonCore, Source source) { + private RootNode doParse(PythonContext context, Source source) { + ParserMode mode = null; + if (source.isInteractive()) { + if (PythonOptions.getOption(context, PythonOptions.TerminalIsInteractive)) { + // if we run through our own launcher, the sys.__displayhook__ would provide the + // printing + mode = ParserMode.Statement; + } else { + // if we're not run through our own launcher, the embedder will expect the normal + // Truffle printing + mode = ParserMode.InteractiveStatement; + } + } else { + // by default we assume a module + mode = ParserMode.File; + } + PythonCore pythonCore = context.getCore(); try { - return (RootNode) pythonCore.getParser().parse(source.isInteractive() ? ParserMode.InteractiveStatement : ParserMode.File, pythonCore, source, null); + return (RootNode) pythonCore.getParser().parse(mode, pythonCore, source, null); } catch (PException e) { // handle PException during parsing (PIncompleteSourceException will propagate through) Truffle.getRuntime().createCallTarget(new TopLevelExceptionHandler(this, e)).call(); @@ -343,13 +359,7 @@ public static PythonCore getCore() { @Override protected boolean isVisible(PythonContext context, Object value) { - if (PythonOptions.getOption(context, PythonOptions.TerminalIsInteractive)) { - // if we run through our own launcher, the sys.__displayhook__ would provide the - // printing - return false; - } else { - return value != PNone.NONE && value != PNone.NO_VALUE; - } + return value != PNone.NONE && value != PNone.NO_VALUE; } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java index e56258d606..6fff8d5a10 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java @@ -56,6 +56,7 @@ public abstract class BuiltinNames { public static final String __DEBUG__ = "__debug__"; // sys + public static final String DISPLAYHOOK = "displayhook"; public static final String BREAKPOINTHOOK = "breakpointhook"; public static final String EXCEPTHOOK = "excepthook"; public static final String LAST_TYPE = "last_type"; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/NodeFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/NodeFactory.java index 3ab5f82d33..4324c4bf6c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/NodeFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/NodeFactory.java @@ -101,6 +101,7 @@ import com.oracle.graal.python.nodes.statement.ImportFromNode; import com.oracle.graal.python.nodes.statement.ImportNode; import com.oracle.graal.python.nodes.statement.ImportStarNode; +import com.oracle.graal.python.nodes.statement.PrintExpressionNode; import com.oracle.graal.python.nodes.statement.StatementNode; import com.oracle.graal.python.nodes.statement.TryExceptNode; import com.oracle.graal.python.nodes.statement.TryFinallyNode; @@ -565,4 +566,8 @@ public PDataModelEmulationNode createIsCallable() { public PDataModelEmulationNode createIsIterable() { return IsIterableNode.create(); } + + public PrintExpressionNode createPrintExpression(ExpressionNode body) { + return PrintExpressionNode.create(body); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java new file mode 100644 index 0000000000..9452b4fcbe --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java @@ -0,0 +1,33 @@ +package com.oracle.graal.python.nodes.statement; + +import static com.oracle.graal.python.nodes.BuiltinNames.DISPLAYHOOK; + +import com.oracle.graal.python.builtins.objects.PNone; +import com.oracle.graal.python.builtins.objects.module.PythonModule; +import com.oracle.graal.python.nodes.attributes.GetAttributeNode; +import com.oracle.graal.python.nodes.call.CallNode; +import com.oracle.graal.python.nodes.expression.ExpressionNode; +import com.oracle.truffle.api.frame.VirtualFrame; + +public class PrintExpressionNode extends ExpressionNode { + @Child GetAttributeNode getAttribute = GetAttributeNode.create(DISPLAYHOOK); + @Child CallNode callNode = CallNode.create(); + @Child ExpressionNode valueNode; + + public PrintExpressionNode(ExpressionNode valueNode) { + this.valueNode = valueNode; + } + + @Override + public Object execute(VirtualFrame frame) { + Object value = valueNode.execute(frame); + PythonModule sysModule = getContext().getCore().lookupBuiltinModule("sys"); + Object displayhook = getAttribute.executeObject(sysModule); + callNode.execute(frame, displayhook, value); + return PNone.NONE; + } + + public static PrintExpressionNode create(ExpressionNode valueNode) { + return new PrintExpressionNode(valueNode); + } +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonParserImpl.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonParserImpl.java index b744ad8703..8e9188cfb4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonParserImpl.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonParserImpl.java @@ -71,15 +71,14 @@ public Node parse(ParserMode mode, ParserErrorCallback errors, Source source, Fr throw new RuntimeException("unexpected mode: " + mode); } } catch (Exception e) { - if (mode == ParserMode.InteractiveStatement || mode == ParserMode.InlineEvaluation) { + if (mode == ParserMode.InteractiveStatement && e instanceof PIncompleteSourceException) { + ((PIncompleteSourceException) e).setSource(source); + throw e; + } else if (mode == ParserMode.InlineEvaluation) { try { parser.reset(); input = parser.eval_input(); } catch (Exception e2) { - if (mode == ParserMode.InteractiveStatement && e instanceof PIncompleteSourceException) { - ((PIncompleteSourceException) e).setSource(source); - throw e; - } throw handleParserError(errors, source, e); } } else { @@ -98,7 +97,7 @@ public Node parse(ParserMode mode, ParserErrorCallback errors, Source source, Fr defineScopes.createFrameSlotsForCellAndFreeVars(); // create Truffle ASTs - return PythonTreeTranslator.translate(errors, source.getName(), input, environment, source, mode == ParserMode.InlineEvaluation); + return PythonTreeTranslator.translate(errors, source.getName(), input, environment, source, mode); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java index 45e4604d81..f9210b9313 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java @@ -95,6 +95,7 @@ import com.oracle.graal.python.parser.antlr.Python3Parser.Lambdef_nocond_bodyContext; import com.oracle.graal.python.parser.antlr.Python3Parser.VarargslistContext; import com.oracle.graal.python.runtime.PythonParser.ParserErrorCallback; +import com.oracle.graal.python.runtime.PythonParser.ParserMode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; @@ -114,33 +115,32 @@ public final class PythonTreeTranslator extends Python3BaseVisitor { protected final Source source; protected final String name; - protected final boolean isInlineMode; + protected final ParserMode mode; - public PythonTreeTranslator(ParserErrorCallback errors, String name, TranslationEnvironment environment, Source source, boolean isInlineMode) { + public PythonTreeTranslator(ParserErrorCallback errors, String name, TranslationEnvironment environment, Source source, ParserMode mode) { this.errors = errors; this.name = name; this.environment = environment; this.source = source; - this.isInlineMode = isInlineMode; + this.mode = mode; this.factory = errors.getLanguage().getNodeFactory(); this.loops = new LoopsBookKeeper(); this.assigns = new AssignmentTranslator(errors, environment, this); } - public static Node translate(ParserErrorCallback errors, String name, ParserRuleContext input, TranslationEnvironment environment, Source source, boolean isInlineMode) { - PythonTreeTranslator translator = new PythonTreeTranslator(errors, name, environment, source, isInlineMode); + public static Node translate(ParserErrorCallback errors, String name, ParserRuleContext input, TranslationEnvironment environment, Source source, ParserMode mode) { + PythonTreeTranslator translator = new PythonTreeTranslator(errors, name, environment, source, mode); try { Object parseResult = input.accept(translator); - if (!isInlineMode && parseResult instanceof RootNode || isInlineMode && parseResult instanceof PNode) { + if (mode == ParserMode.InlineEvaluation) { + assert parseResult instanceof PNode : "expected PNode result for InlineEvaluation"; return (Node) parseResult; } else { - throw new RuntimeException("Unexpected parse result"); + assert parseResult instanceof RootNode : "expected RootNode result from parsing"; + return (Node) parseResult; } } catch (PException e) { throw e; - } catch (Exception t) { - t.printStackTrace(); - throw new RuntimeException("Failed in " + translator + " with error " + t, t); } } @@ -253,8 +253,12 @@ public Object visitSingle_input(Python3Parser.Single_inputContext ctx) { ExpressionNode body = asExpression(super.visitSingle_input(ctx)); deriveSourceSection(ctx, body); environment.popScope(); - if (isInlineMode) { + if (mode == ParserMode.InlineEvaluation) { return body; + } else if (mode == ParserMode.Statement) { + body = factory.createPrintExpression(body); + deriveSourceSection(ctx, body); + return factory.createModuleRoot("", getModuleDoc(ctx), body, ctx.scope.getFrameDescriptor()); } else { return factory.createModuleRoot("", getModuleDoc(ctx), body, ctx.scope.getFrameDescriptor()); } From f3d10d757e4c9a6da77656841cc37fc442196adc Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 8 Feb 2019 00:15:07 +0100 Subject: [PATCH 137/202] update copyrights --- .../nodes/statement/PrintExpressionNode.java | 40 +++++++++++++++++++ .../graal/python/parser/PythonParserImpl.java | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java index 9452b4fcbe..fa3777110a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java @@ -1,3 +1,43 @@ +/* + * Copyright (c) 2018, 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 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ package com.oracle.graal.python.nodes.statement; import static com.oracle.graal.python.nodes.BuiltinNames.DISPLAYHOOK; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonParserImpl.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonParserImpl.java index 8e9188cfb4..341c7b8144 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonParserImpl.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonParserImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. From da5dddbecac9a33f74a05cdd237b1486e7a4420c Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 8 Feb 2019 00:25:06 +0100 Subject: [PATCH 138/202] move break --- .../src/com/oracle/graal/python/shell/GraalPythonMain.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java index e6bc8a044d..6311dad41a 100644 --- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java +++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java @@ -162,8 +162,8 @@ protected List preprocessArguments(List givenArgs, Map Date: Fri, 8 Feb 2019 08:49:34 +0100 Subject: [PATCH 139/202] update default copyright year to 2019 --- .../graal/python/nodes/statement/PrintExpressionNode.java | 2 +- mx.graalpython/copyrights/benchmarks.copyright.hash | 3 +-- mx.graalpython/copyrights/jython.copyright.star | 2 +- mx.graalpython/copyrights/oracle.copyright.hash | 2 +- mx.graalpython/copyrights/oracle.copyright.star | 2 +- mx.graalpython/copyrights/pypy-image-demo.copyright.hash | 2 +- mx.graalpython/copyrights/pypy.copyright.hash | 2 +- mx.graalpython/copyrights/python.copyright.hash | 2 +- mx.graalpython/copyrights/python.copyright.star | 2 +- mx.graalpython/copyrights/python3antlr.copyright.star | 2 +- mx.graalpython/copyrights/zippy.copyright.hash | 2 +- mx.graalpython/copyrights/zippy.copyright.star | 2 +- 12 files changed, 12 insertions(+), 13 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java index fa3777110a..5eb3c84be3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/PrintExpressionNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 diff --git a/mx.graalpython/copyrights/benchmarks.copyright.hash b/mx.graalpython/copyrights/benchmarks.copyright.hash index 10d7c6de79..586534a9f1 100644 --- a/mx.graalpython/copyrights/benchmarks.copyright.hash +++ b/mx.graalpython/copyrights/benchmarks.copyright.hash @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright 2008-2010 Isaac Gouy # Copyright (c) 2013, 2014, Regents of the University of California -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2019, Oracle and/or its affiliates. # All rights reserved. # # Revised BSD license @@ -35,4 +35,3 @@ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/mx.graalpython/copyrights/jython.copyright.star b/mx.graalpython/copyrights/jython.copyright.star index ac60f3732e..00a54d1a9b 100644 --- a/mx.graalpython/copyrights/jython.copyright.star +++ b/mx.graalpython/copyrights/jython.copyright.star @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. + * Copyright (c) 2019, Oracle and/or its affiliates. * Copyright (c) -2016 Jython Developers * * Licensed under PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 diff --git a/mx.graalpython/copyrights/oracle.copyright.hash b/mx.graalpython/copyrights/oracle.copyright.hash index 61fd6363b8..6d664b2bd4 100644 --- a/mx.graalpython/copyrights/oracle.copyright.hash +++ b/mx.graalpython/copyrights/oracle.copyright.hash @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 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 diff --git a/mx.graalpython/copyrights/oracle.copyright.star b/mx.graalpython/copyrights/oracle.copyright.star index 512e476c8e..531dfcf3bb 100644 --- a/mx.graalpython/copyrights/oracle.copyright.star +++ b/mx.graalpython/copyrights/oracle.copyright.star @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 diff --git a/mx.graalpython/copyrights/pypy-image-demo.copyright.hash b/mx.graalpython/copyrights/pypy-image-demo.copyright.hash index 3ab6d847ff..e089c06ffa 100644 --- a/mx.graalpython/copyrights/pypy-image-demo.copyright.hash +++ b/mx.graalpython/copyrights/pypy-image-demo.copyright.hash @@ -1,4 +1,4 @@ -# Copyright (c) 2017, Oracle and/or its affiliates. +# Copyright (c) 2019, Oracle and/or its affiliates. # Copyright (c) 2013, Pablo Mouzo # # Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/mx.graalpython/copyrights/pypy.copyright.hash b/mx.graalpython/copyrights/pypy.copyright.hash index df6d01a624..85c927f48f 100644 --- a/mx.graalpython/copyrights/pypy.copyright.hash +++ b/mx.graalpython/copyrights/pypy.copyright.hash @@ -1,5 +1,5 @@ # coding=utf-8 -# Copyright (c) 2017, Oracle and/or its affiliates. +# Copyright (c) 2019, Oracle and/or its affiliates. # Copyright (c) 2017, The PyPy Project # # The MIT License diff --git a/mx.graalpython/copyrights/python.copyright.hash b/mx.graalpython/copyrights/python.copyright.hash index 422c756683..b1272a634c 100644 --- a/mx.graalpython/copyrights/python.copyright.hash +++ b/mx.graalpython/copyrights/python.copyright.hash @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2019, Oracle and/or its affiliates. # Copyright (C) 1996-2017 Python Software Foundation # # Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 diff --git a/mx.graalpython/copyrights/python.copyright.star b/mx.graalpython/copyrights/python.copyright.star index 9e2aae6318..9c0c8bcc7f 100644 --- a/mx.graalpython/copyrights/python.copyright.star +++ b/mx.graalpython/copyrights/python.copyright.star @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, Oracle and/or its affiliates. +/* Copyright (c) 2019, Oracle and/or its affiliates. * Copyright (C) 1996-2017 Python Software Foundation * * Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 diff --git a/mx.graalpython/copyrights/python3antlr.copyright.star b/mx.graalpython/copyrights/python3antlr.copyright.star index 81b8ff8b49..ef58283651 100644 --- a/mx.graalpython/copyrights/python3antlr.copyright.star +++ b/mx.graalpython/copyrights/python3antlr.copyright.star @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, Oracle and/or its affiliates. + * Copyright (c) 2017-2019, Oracle and/or its affiliates. * Copyright (c) 2014 by Bart Kiers * * The MIT License (MIT) diff --git a/mx.graalpython/copyrights/zippy.copyright.hash b/mx.graalpython/copyrights/zippy.copyright.hash index 9095f9d3a2..48b09db02a 100644 --- a/mx.graalpython/copyrights/zippy.copyright.hash +++ b/mx.graalpython/copyrights/zippy.copyright.hash @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2019, Oracle and/or its affiliates. # Copyright (c) 2013, Regents of the University of California # # All rights reserved. diff --git a/mx.graalpython/copyrights/zippy.copyright.star b/mx.graalpython/copyrights/zippy.copyright.star index 0ebb3daa80..f263ec6c85 100644 --- a/mx.graalpython/copyrights/zippy.copyright.star +++ b/mx.graalpython/copyrights/zippy.copyright.star @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. + * Copyright (c) 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. From 1750f288a63554956de435234837b14dbd446b33 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 25 Jan 2019 23:17:36 +0100 Subject: [PATCH 140/202] Support module 'mmap'. --- .../graal/python/builtins/Python3Core.java | 4 +- .../builtins/PythonBuiltinClassType.java | 1 + .../builtins/modules/MMapModuleBuiltins.java | 61 +++++- .../builtins/objects/mmap/MMapBuiltins.java | 186 ++++++++++++++++++ .../python/builtins/objects/mmap/PMMap.java | 61 ++++++ .../runtime/object/PythonObjectFactory.java | 10 + graalpython/lib-graalpython/mmap.py | 17 -- 7 files changed, 321 insertions(+), 19 deletions(-) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/PMMap.java diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java index 8a4c28e9d6..79f25c9de9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java @@ -134,6 +134,7 @@ import com.oracle.graal.python.builtins.objects.method.DecoratedMethodBuiltins; import com.oracle.graal.python.builtins.objects.method.MethodBuiltins; import com.oracle.graal.python.builtins.objects.method.StaticmethodBuiltins; +import com.oracle.graal.python.builtins.objects.mmap.MMapBuiltins; import com.oracle.graal.python.builtins.objects.module.PythonModule; import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins; import com.oracle.graal.python.builtins.objects.object.PythonObject; @@ -331,7 +332,8 @@ private static final PythonBuiltins[] initializeBuiltins(Env env) { new ZipImportModuleBuiltins(), new ZLibModuleBuiltins(), new MMapModuleBuiltins(), - new FcntlModuleBuiltins())); + new FcntlModuleBuiltins(), + new MMapBuiltins())); if (!TruffleOptions.AOT) { ServiceLoader providers = ServiceLoader.load(PythonBuiltins.class); for (PythonBuiltins builtin : providers) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java index 984d5d0ada..0a8dc76929 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java @@ -67,6 +67,7 @@ public enum PythonBuiltinClassType implements LazyPythonClass { PMappingproxy("mappingproxy"), PMemoryView("memoryview", "builtins"), PMethod("method"), + PMMap("mmap", "mmap"), PNone("NoneType"), PNotImplemented("NotImplementedType"), PRandom("Random", "_random"), diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java index 8f8d7e6c7b..cf10e71e1f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java @@ -40,22 +40,81 @@ */ package com.oracle.graal.python.builtins.modules; +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PMMap; +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError; + +import java.nio.channels.Channel; +import java.nio.channels.FileChannel.MapMode; +import java.nio.channels.SeekableByteChannel; import java.util.List; +import com.oracle.graal.python.builtins.Builtin; import com.oracle.graal.python.builtins.CoreFunctions; import com.oracle.graal.python.builtins.PythonBuiltins; +import com.oracle.graal.python.builtins.objects.PNone; +import com.oracle.graal.python.builtins.objects.mmap.PMMap; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; +import com.oracle.graal.python.nodes.function.PythonBuiltinNode; +import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ValueProfile; @CoreFunctions(defineModule = "mmap") public class MMapModuleBuiltins extends PythonBuiltins { + private static final int ACCESS_DEFAULT = 0; + private static final int ACCESS_READ = 1; + private static final int ACCESS_WRITE = 2; + private static final int ACCESS_COPY = 3; @Override protected List> getNodeFactories() { - return ZipImportModuleBuiltinsFactory.getFactories(); + return MMapModuleBuiltinsFactory.getFactories(); } public MMapModuleBuiltins() { + builtinConstants.put("ACCESS_DEFAULT", ACCESS_DEFAULT); + builtinConstants.put("ACCESS_READ", ACCESS_READ); + builtinConstants.put("ACCESS_WRITE", ACCESS_WRITE); + builtinConstants.put("ACCESS_COPY", ACCESS_COPY); } + @Builtin(name = "mmap", fixedNumOfPositionalArgs = 3, keywordArguments = {"tagname", "access"}, constructsClass = PMMap) + @GenerateNodeFactory + public abstract static class MMapNode extends PythonBuiltinNode { + + private final ValueProfile classProfile = ValueProfile.createClassProfile(); + + @Specialization(guards = {"isNoValue(access)"}) + PMMap doIt(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access) { + return doGeneric(clazz, fd, length, tagname, ACCESS_DEFAULT); + } + + // mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset]) + @Specialization + PMMap doGeneric(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, int access) { + Channel fileChannel = getContext().getResources().getFileChannel(fd, classProfile); + if (fileChannel instanceof SeekableByteChannel) { + MapMode mode = convertAccessToMapMode(access); + return factory().createMMap(clazz, (SeekableByteChannel) fileChannel); + } + throw raise(ValueError, "cannot mmap file"); + } + + private MapMode convertAccessToMapMode(int access) { + switch (access) { + case 0: + return MapMode.READ_WRITE; + case 1: + return MapMode.READ_ONLY; + case 2: + return MapMode.READ_WRITE; + case 3: + return MapMode.PRIVATE; + } + throw raise(ValueError, "mmap invalid access parameter."); + } + + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java new file mode 100644 index 0000000000..1c2e126cba --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2019, 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 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.builtins.objects.mmap; + +import static com.oracle.graal.python.nodes.SpecialMethodNames.__ADD__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__CONTAINS__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__GE__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__GT__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__LE__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__LT__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__MUL__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__NE__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__RMUL__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__STR__; + +import java.io.IOException; +import java.util.List; + +import com.oracle.graal.python.builtins.Builtin; +import com.oracle.graal.python.builtins.CoreFunctions; +import com.oracle.graal.python.builtins.PythonBuiltinClassType; +import com.oracle.graal.python.builtins.PythonBuiltins; +import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum; +import com.oracle.graal.python.nodes.SpecialMethodNames; +import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; +import com.oracle.graal.python.nodes.function.PythonBuiltinNode; +import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode; +import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode; +import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; +import com.oracle.truffle.api.dsl.GenerateNodeFactory; +import com.oracle.truffle.api.dsl.NodeFactory; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; + +@CoreFunctions(extendClasses = PythonBuiltinClassType.PMMap) +public class MMapBuiltins extends PythonBuiltins { + + @Override + protected List> getNodeFactories() { + return MMapBuiltinsFactory.getFactories(); + } + + @Builtin(name = __ADD__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class AddNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = __MUL__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class MulNode extends PythonBuiltinNode { + } + + @Builtin(name = __RMUL__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class RMulNode extends MulNode { + } + + @Builtin(name = __CONTAINS__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class ContainsNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = __LT__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class LtNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = __LE__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class LeNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = __GT__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class GtNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = __GE__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class GeNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = __NE__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class NeNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = __EQ__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class EqNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = __STR__, fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + abstract static class StrNode extends PythonUnaryBuiltinNode { + } + + @Builtin(name = __REPR__, fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + abstract static class ReprNode extends StrNode { + } + + @Builtin(name = __GETITEM__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class GetItemNode extends PythonBinaryBuiltinNode { + } + + @Builtin(name = SpecialMethodNames.__SETITEM__, fixedNumOfPositionalArgs = 3) + @GenerateNodeFactory + abstract static class SetItemNode extends PythonTernaryBuiltinNode { + + } + + @Builtin(name = __LEN__, fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + public abstract static class LenNode extends PythonUnaryBuiltinNode { + + } + + @Builtin(name = SpecialMethodNames.__ENTER__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class EnterNode extends PythonBuiltinNode { + } + + @Builtin(name = SpecialMethodNames.__EXIT__, fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class ExitNode extends PythonBuiltinNode { + } + + @Builtin(name = "size", fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + abstract static class SizeNode extends PythonBuiltinNode { + + @Specialization + long size(VirtualFrame frame, PMMap self) { + try { + return self.getChannel().size(); + } catch (IOException e) { + throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + } + } + } + +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/PMMap.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/PMMap.java new file mode 100644 index 0000000000..9dfbd53770 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/PMMap.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019, 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 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.builtins.objects.mmap; + +import java.nio.channels.SeekableByteChannel; + +import com.oracle.graal.python.builtins.objects.object.PythonObject; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; + +public class PMMap extends PythonObject { + + private final SeekableByteChannel mappedByteBuffer; + + public PMMap(LazyPythonClass pythonClass, SeekableByteChannel mappedByteBuffer) { + super(pythonClass); + this.mappedByteBuffer = mappedByteBuffer; + } + + public SeekableByteChannel getChannel() { + return mappedByteBuffer; + } + +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index d38cfcc243..f40269c959 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -27,6 +27,7 @@ import java.lang.ref.ReferenceQueue; import java.math.BigInteger; +import java.nio.channels.SeekableByteChannel; import java.nio.file.DirectoryStream; import java.util.Map; import java.util.Optional; @@ -87,6 +88,7 @@ import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod; import com.oracle.graal.python.builtins.objects.method.PDecoratedMethod; import com.oracle.graal.python.builtins.objects.method.PMethod; +import com.oracle.graal.python.builtins.objects.mmap.PMMap; 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.posix.PDirEntry; @@ -839,4 +841,12 @@ public PDirEntry createDirEntry(String name, TruffleFile file) { public Object createDirEntry(LazyPythonClass cls, String name, TruffleFile file) { return trace(new PDirEntry(cls, name, file)); } + + public PMMap createMMap(SeekableByteChannel channel) { + return trace(new PMMap(PythonBuiltinClassType.PMMap, channel)); + } + + public PMMap createMMap(LazyPythonClass clazz, SeekableByteChannel channel) { + return trace(new PMMap(clazz, channel)); + } } diff --git a/graalpython/lib-graalpython/mmap.py b/graalpython/lib-graalpython/mmap.py index abbb660cb9..ad6e1eb1e8 100644 --- a/graalpython/lib-graalpython/mmap.py +++ b/graalpython/lib-graalpython/mmap.py @@ -48,20 +48,3 @@ PROT_READ=0x1 PROT_WRITE=0x2 PROT_EXEC=0x4 - -ACCESS_DEFAULT=0 -ACCESS_READ=1 -ACCESS_WRITE=2 -ACCESS_COPY=3 - - -class mmap: - def __init__(self, fileno, length, flags=MAP_SHARED, prot=PROT_WRITE|PROT_READ, access=ACCESS_DEFAULT): - pass - - def readline(self): - # TODO(fa): implement - raise NotImplementedError - - - From e3d588c19efda0cd8fb065a478296c21ecb01c38 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Mon, 28 Jan 2019 11:56:56 +0100 Subject: [PATCH 141/202] Add test. --- .../src/tests/cpyext/test_mmap.py | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_mmap.py diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_mmap.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_mmap.py new file mode 100644 index 0000000000..31509c025a --- /dev/null +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_mmap.py @@ -0,0 +1,87 @@ +# Copyright (c) 2019, 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 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import mmap +import tempfile +from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, unhandled_error_compare, GRAALPYTHON +__dir__ = __file__.rpartition("/")[0] + + +def create_and_map_file(): + tmp = tempfile.mktemp(prefix="pymmap_") + with open(tmp, "w") as f: + f.write("hello, world") + f = open(tmp, "r") + return mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) + + +class TestPyMmap(CPyExtTestCase): + def compile_module(self, name): + type(self).mro()[1].__dict__["test_%s" % name].create_module(name) + super(TestPyMmap, self).compile_module(name) + + + test_buffer = CPyExtFunction( + lambda args: b"hello, world", + lambda: ( + (create_and_map_file(),), + ), + code=""" + static PyObject* get_mmap_buf(PyObject* mmapObj) { + Py_buffer buf; + Py_ssize_t len, i; + char* data = NULL; + if (PyObject_GetBuffer(mmapObj, &buf, PyBUF_SIMPLE)) { + return NULL; + } + len = buf.len; + data = (char*) malloc(sizeof(char)*len); + for (i=0; i < buf.len; i++) { + data[i] = ((char *) buf.buf)[i]; + } + return PyBytes_FromStringAndSize(data, len); + } + """, + resultspec="O", + argspec='O', + arguments=["PyObject* mmapObj"], + callfunction="get_mmap_buf", + cmpfunc=unhandled_error_compare + ) From ab28c745b7200dc98a361949cc6872aec54d7c7f Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Mon, 28 Jan 2019 18:15:34 +0100 Subject: [PATCH 142/202] Implement 'mmap' builtins. --- .../builtins/modules/MMapModuleBuiltins.java | 39 +++- .../builtins/modules/PosixModuleBuiltins.java | 88 +------- .../cext/PythonObjectNativeWrapperMR.java | 8 +- .../builtins/objects/mmap/MMapBuiltins.java | 188 +++++++++++++++++- .../python/builtins/objects/mmap/PMMap.java | 15 +- .../graal/python/nodes/util/ChannelNodes.java | 143 +++++++++++++ .../runtime/object/PythonObjectFactory.java | 8 +- graalpython/lib-graalpython/mmap.py | 2 + 8 files changed, 382 insertions(+), 109 deletions(-) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java index cf10e71e1f..8545459c80 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java @@ -43,19 +43,24 @@ import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PMMap; import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError; -import java.nio.channels.Channel; +import java.io.IOException; import java.nio.channels.FileChannel.MapMode; import java.nio.channels.SeekableByteChannel; +import java.nio.file.StandardOpenOption; +import java.util.HashSet; import java.util.List; +import java.util.Set; import com.oracle.graal.python.builtins.Builtin; import com.oracle.graal.python.builtins.CoreFunctions; +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.mmap.PMMap; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; +import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; @@ -80,26 +85,38 @@ public MMapModuleBuiltins() { builtinConstants.put("ACCESS_COPY", ACCESS_COPY); } - @Builtin(name = "mmap", fixedNumOfPositionalArgs = 3, keywordArguments = {"tagname", "access"}, constructsClass = PMMap) + @Builtin(name = "mmap", fixedNumOfPositionalArgs = 3, keywordArguments = {"tagname", "access", "offset"}, constructsClass = PMMap) @GenerateNodeFactory public abstract static class MMapNode extends PythonBuiltinNode { private final ValueProfile classProfile = ValueProfile.createClassProfile(); - @Specialization(guards = {"isNoValue(access)"}) - PMMap doIt(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access) { - return doGeneric(clazz, fd, length, tagname, ACCESS_DEFAULT); + @Specialization(guards = {"isNoValue(access)", "isNoValue(offset)"}) + PMMap doIt(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access, @SuppressWarnings("unused") PNone offset) { + return doGeneric(clazz, fd, length, tagname, ACCESS_DEFAULT, 0); } // mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset]) @Specialization - PMMap doGeneric(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, int access) { - Channel fileChannel = getContext().getResources().getFileChannel(fd, classProfile); - if (fileChannel instanceof SeekableByteChannel) { - MapMode mode = convertAccessToMapMode(access); - return factory().createMMap(clazz, (SeekableByteChannel) fileChannel); + PMMap doGeneric(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, int access, long offset) { + String path = getContext().getResources().getFilePath(fd); + TruffleFile truffleFile = getContext().getEnv().getTruffleFile(path); + + // TODO(fa) correctly honor access flags + MapMode mode = convertAccessToMapMode(access); + Set options = new HashSet<>(); + options.add(StandardOpenOption.READ); + options.add(StandardOpenOption.WRITE); + + // we create a new channel otherwise we cannot guarantee that the cursor is exclusive + SeekableByteChannel fileChannel; + try { + fileChannel = truffleFile.newByteChannel(options); + fileChannel.position(offset); + return new PMMap(PythonBuiltinClassType.PMMap, fileChannel, length, offset); + } catch (IOException e) { + throw raise(ValueError, "cannot mmap file"); } - throw raise(ValueError, "cannot mmap file"); } private MapMode convertAccessToMapMode(int access) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index 1ee097ba5c..643acc2298 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -78,7 +78,6 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.modules.PosixModuleBuiltinsFactory.CastToPathNodeGen; import com.oracle.graal.python.builtins.modules.PosixModuleBuiltinsFactory.ConvertPathlikeObjectNodeGen; -import com.oracle.graal.python.builtins.modules.PosixModuleBuiltinsFactory.ReadFromChannelNodeGen; import com.oracle.graal.python.builtins.modules.PosixModuleBuiltinsFactory.StatNodeFactory; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.bytes.BytesNodes.ToBytesNode; @@ -110,6 +109,7 @@ import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; import com.oracle.graal.python.nodes.util.CastToIndexNode; import com.oracle.graal.python.nodes.util.CastToIntegerFromIntNode; +import com.oracle.graal.python.nodes.util.ChannelNodes.ReadFromChannelNode; import com.oracle.graal.python.runtime.PosixResources; import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.PythonCore; @@ -1007,90 +1007,10 @@ public static WriteNode create() { } } - abstract static class ReadFromChannelNode extends PNodeWithContext { - private final BranchProfile gotException = BranchProfile.create(); - - abstract ByteSequenceStorage execute(Channel channel, int size); - - @Specialization - ByteSequenceStorage readSeekable(SeekableByteChannel channel, int size) { - long availableSize; - try { - availableSize = availableSize(channel); - } catch (IOException e) { - gotException.enter(); - throw raise(OSError, e); - } - if (availableSize > ReadNode.MAX_READ) { - availableSize = ReadNode.MAX_READ; - } - int sz = (int) Math.min(availableSize, size); - return readReadable(channel, sz); - } - - @TruffleBoundary(transferToInterpreterOnException = false) - private static long availableSize(SeekableByteChannel channel) throws IOException { - return channel.size() - channel.position(); - } - - @Specialization - ByteSequenceStorage readReadable(ReadableByteChannel channel, int size) { - int sz = Math.min(size, ReadNode.MAX_READ); - ByteBuffer dst = allocateBuffer(sz); - int readSize = readIntoBuffer(channel, dst); - byte[] array; - if (readSize <= 0) { - array = new byte[0]; - readSize = 0; - } else { - array = getByteBufferArray(dst); - } - ByteSequenceStorage byteSequenceStorage = new ByteSequenceStorage(array); - byteSequenceStorage.setNewLength(readSize); - return byteSequenceStorage; - } - - @Specialization - ByteSequenceStorage readGeneric(Channel channel, int size) { - if (channel instanceof SeekableByteChannel) { - return readSeekable((SeekableByteChannel) channel, size); - } else if (channel instanceof ReadableByteChannel) { - return readReadable((ReadableByteChannel) channel, size); - } else { - throw raise(OSError, "file not opened for reading"); - } - } - - @TruffleBoundary(allowInlining = true) - private static byte[] getByteBufferArray(ByteBuffer dst) { - return dst.array(); - } - - @TruffleBoundary(allowInlining = true) - private int readIntoBuffer(ReadableByteChannel readableChannel, ByteBuffer dst) { - try { - return readableChannel.read(dst); - } catch (IOException e) { - gotException.enter(); - throw raise(OSError, e); - } - } - - @TruffleBoundary(allowInlining = true) - private static ByteBuffer allocateBuffer(int sz) { - return ByteBuffer.allocate(sz); - } - - public static ReadFromChannelNode create() { - return ReadFromChannelNodeGen.create(); - } - } - @Builtin(name = "read", fixedNumOfPositionalArgs = 2) @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) public abstract static class ReadNode extends PythonFileNode { - private static final int MAX_READ = Integer.MAX_VALUE / 2; @CompilationFinal private BranchProfile tooLargeProfile = BranchProfile.create(); @@ -1100,8 +1020,8 @@ Object readOpaque(@SuppressWarnings("unused") VirtualFrame frame, int fd, long r @Cached("create()") ReadFromChannelNode readNode) { if (OpaqueBytes.isInOpaqueFilesystem(getResources().getFilePath(fd), getContext())) { Channel channel = getResources().getFileChannel(fd, channelClassProfile); - ByteSequenceStorage bytes = readNode.execute(channel, MAX_READ); - return new OpaqueBytes(Arrays.copyOf(bytes.getInternalByteArray(), bytes.length())); + ByteSequenceStorage bytes = readNode.execute(channel, ReadFromChannelNode.MAX_READ); + return new OpaqueBytes(Arrays.copyOf(bytes.getInternalByteArray(), bytes.length())); } return read(frame, fd, requestedSize, channelClassProfile, readNode); } @@ -1115,7 +1035,7 @@ Object read(@SuppressWarnings("unused") VirtualFrame frame, int fd, long request size = Math.toIntExact(requestedSize); } catch (ArithmeticException e) { tooLargeProfile.enter(); - size = MAX_READ; + size = ReadFromChannelNode.MAX_READ; } Channel channel = getResources().getFileChannel(fd, channelClassProfile); ByteSequenceStorage array = readNode.execute(channel, size); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index ea07d7cab5..b3c1cd348d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -453,7 +453,8 @@ Object doTpAsBuffer(PythonManagedClass object, @SuppressWarnings("unused") Strin @Cached("create()") BranchProfile notBytes, @Cached("create()") BranchProfile notBytearray, @Cached("create()") BranchProfile notMemoryview, - @Cached("create()") BranchProfile notBuffer) { + @Cached("create()") BranchProfile notBuffer, + @Cached("create()") BranchProfile notMmap) { PythonCore core = getCore(); PythonBuiltinClass pBytes = core.lookupType(PythonBuiltinClassType.PBytes); if (isSubtype.execute(object, pBytes)) { @@ -475,6 +476,11 @@ Object doTpAsBuffer(PythonManagedClass object, @SuppressWarnings("unused") Strin return new PyBufferProcsWrapper(pBuffer); } notBuffer.enter(); + PythonBuiltinClass pMmap = core.lookupType(PythonBuiltinClassType.PMMap); + if (isSubtype.execute(object, pMmap)) { + return new PyBufferProcsWrapper(pMemoryview); + } + notMmap.enter(); // NULL pointer return getToSulongNode().execute(PNone.NO_VALUE); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index 1c2e126cba..a7ac63b89b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -42,7 +42,9 @@ import static com.oracle.graal.python.nodes.SpecialMethodNames.__ADD__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__CONTAINS__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__ENTER__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__; +import static com.oracle.graal.python.nodes.SpecialMethodNames.__EXIT__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__GE__; import static com.oracle.graal.python.nodes.SpecialMethodNames.__GT__; @@ -56,23 +58,38 @@ import static com.oracle.graal.python.nodes.SpecialMethodNames.__STR__; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; import java.util.List; import com.oracle.graal.python.builtins.Builtin; import com.oracle.graal.python.builtins.CoreFunctions; 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.bytes.PBytes; import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum; import com.oracle.graal.python.nodes.SpecialMethodNames; +import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; +import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; +import com.oracle.graal.python.nodes.util.CastToIndexNode; +import com.oracle.graal.python.nodes.util.ChannelNodes.ReadByteFromChannelNode; +import com.oracle.graal.python.nodes.util.ChannelNodes.ReadFromChannelNode; +import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateNodeFactory; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.ConditionProfile; @CoreFunctions(extendClasses = PythonBuiltinClassType.PMMap) public class MMapBuiltins extends PythonBuiltins { @@ -155,18 +172,51 @@ abstract static class SetItemNode extends PythonTernaryBuiltinNode { @Builtin(name = __LEN__, fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - public abstract static class LenNode extends PythonUnaryBuiltinNode { - + public abstract static class LenNode extends PythonBuiltinNode { + @Specialization + long len(VirtualFrame frame, PMMap self) { + try { + return self.getChannel().size(); + } catch (IOException e) { + throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + } + } } - @Builtin(name = SpecialMethodNames.__ENTER__, fixedNumOfPositionalArgs = 2) + @Builtin(name = __ENTER__, fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - abstract static class EnterNode extends PythonBuiltinNode { + abstract static class EnterNode extends PythonUnaryBuiltinNode { + @Specialization + Object size(PMMap self) { + return self; + } } - @Builtin(name = SpecialMethodNames.__EXIT__, fixedNumOfPositionalArgs = 2) + @Builtin(name = __EXIT__, fixedNumOfPositionalArgs = 4) @GenerateNodeFactory abstract static class ExitNode extends PythonBuiltinNode { + protected static final String CLOSE = "close"; + + @Specialization + Object size(PMMap self, @SuppressWarnings("unused") Object typ, @SuppressWarnings("unused") Object val, @SuppressWarnings("unused") Object tb, + @Cached("create(CLOSE)") LookupAndCallUnaryNode callCloseNode) { + return callCloseNode.executeObject(self); + } + } + + @Builtin(name = "close", fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + abstract static class CloseNode extends PythonUnaryBuiltinNode { + + @Specialization + PNone close(PMMap self) { + try { + self.getChannel().close(); + } catch (IOException e) { + // TODO(fa): ignore ? + } + return PNone.NONE; + } } @Builtin(name = "size", fixedNumOfPositionalArgs = 1) @@ -174,13 +224,137 @@ abstract static class ExitNode extends PythonBuiltinNode { abstract static class SizeNode extends PythonBuiltinNode { @Specialization - long size(VirtualFrame frame, PMMap self) { + long size(VirtualFrame frame, PMMap self, + @Cached("createBinaryProfile()") ConditionProfile profile) { + if (profile.profile(self.getLength() == 0)) { + try { + return self.getChannel().size() - self.getOffset(); + } catch (IOException e) { + throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + } + } + return self.getLength(); + } + } + + @Builtin(name = "tell", fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + abstract static class TellNode extends PythonBuiltinNode { + @Specialization + long readline(VirtualFrame frame, PMMap self) { + try { - return self.getChannel().size(); + SeekableByteChannel channel = self.getChannel(); + return channel.position() - self.getOffset(); } catch (IOException e) { throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); } } } + @Builtin(name = "read_byte", fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + @TypeSystemReference(PythonArithmeticTypes.class) + abstract static class ReadByteNode extends PythonUnaryBuiltinNode { + + @Specialization + int readByte(PMMap self, + @Cached("create()") ReadByteFromChannelNode readByteNode) { + return readByteNode.execute(self.getChannel()); + } + } + + @Builtin(name = "read", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2) + @GenerateNodeFactory + @TypeSystemReference(PythonArithmeticTypes.class) + abstract static class ReadNode extends PythonBuiltinNode { + + @Specialization(guards = "!isNoValue(n)") + PBytes read(PMMap self, @SuppressWarnings("unused") PNone n, + @Cached("create()") ReadFromChannelNode readChannelNode) { + ByteSequenceStorage res = readChannelNode.execute(self.getChannel(), ReadFromChannelNode.MAX_READ); + return factory().createBytes(res); + } + + @Specialization(guards = "!isNoValue(n)") + PBytes read(PMMap self, Object n, + @Cached("create()") ReadFromChannelNode readChannelNode, + @Cached("create()") CastToIndexNode castToIndexNode) { + ByteSequenceStorage res = readChannelNode.execute(self.getChannel(), castToIndexNode.execute(n)); + return factory().createBytes(res); + } + } + + @Builtin(name = "readline", fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + abstract static class ReadlineNode extends PythonBuiltinNode { + + @Specialization + @TruffleBoundary + Object readline(PMMap self) { + + try { + ByteBuffer buf = ByteBuffer.allocate(4096); + SeekableByteChannel channel = self.getChannel(); + // search for newline char + int nread; + while ((nread = channel.read(buf)) > 0) { + for (int i = 0; i < buf.remaining(); i++) { + + } + } + return null; + } catch (IOException e) { + throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + } + } + } + + @Builtin(name = "seek", fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + @TypeSystemReference(PythonArithmeticTypes.class) + abstract static class SeekNode extends PythonBuiltinNode { + + @Specialization(guards = "isNoValue(how)") + Object seek(VirtualFrame frame, PMMap self, long dist, @SuppressWarnings("unused") PNone how) { + return seek(frame, self, dist, 0); + } + + @Specialization + Object seek(VirtualFrame frame, PMMap self, long dist, int how) { + try { + return doSeek(self, dist, how); + } catch (IOException e) { + throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + } + } + + @TruffleBoundary + private Object doSeek(PMMap self, long dist, int how) throws IOException { + SeekableByteChannel channel = self.getChannel(); + long where; + switch (how) { + case 0: /* relative to start */ + where = dist; + break; + case 1: /* relative to current position */ + where = channel.position() + dist; + break; + case 2: /* relative to end */ + long size; + if (self.getLength() == 0) { + size = channel.size() - self.getOffset(); + } else { + size = self.getLength(); + } + where = size + dist; + break; + default: + throw raise(PythonBuiltinClassType.ValueError, "unknown seek type"); + } + channel.position(where); + return PNone.NONE; + } + } + } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/PMMap.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/PMMap.java index 9dfbd53770..1e3e1f7b48 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/PMMap.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/PMMap.java @@ -45,17 +45,28 @@ import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -public class PMMap extends PythonObject { +public final class PMMap extends PythonObject { private final SeekableByteChannel mappedByteBuffer; + private final long length; + private final long offset; - public PMMap(LazyPythonClass pythonClass, SeekableByteChannel mappedByteBuffer) { + public PMMap(LazyPythonClass pythonClass, SeekableByteChannel mappedByteBuffer, long length, long offset) { super(pythonClass); this.mappedByteBuffer = mappedByteBuffer; + this.length = length; + this.offset = offset; } public SeekableByteChannel getChannel() { return mappedByteBuffer; } + public long getLength() { + return length; + } + + public long getOffset() { + return offset; + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java new file mode 100644 index 0000000000..ca3528c1f8 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java @@ -0,0 +1,143 @@ +package com.oracle.graal.python.nodes.util; + +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.OSError; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.Channel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SeekableByteChannel; + +import com.oracle.graal.python.builtins.PythonBuiltinClassType; +import com.oracle.graal.python.nodes.PNodeWithContext; +import com.oracle.graal.python.nodes.util.ChannelNodesFactory.ReadByteFromChannelNodeGen; +import com.oracle.graal.python.nodes.util.ChannelNodesFactory.ReadFromChannelNodeGen; +import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; + +public abstract class ChannelNodes { + public abstract static class ReadErrorHandler extends PNodeWithContext { + public abstract Object execute(Channel channel, int nrequested, int nread); + } + + abstract static class ReadFromChannelBaseNode extends PNodeWithContext { + + private final BranchProfile gotException = BranchProfile.create(); + + @TruffleBoundary(allowInlining = true) + protected static ByteBuffer allocate(int n) { + return ByteBuffer.allocate(n); + } + + @TruffleBoundary(transferToInterpreterOnException = false) + protected static long availableSize(SeekableByteChannel channel) throws IOException { + return channel.size() - channel.position(); + } + + @TruffleBoundary(allowInlining = true) + protected static byte[] getByteBufferArray(ByteBuffer dst) { + return dst.array(); + } + + @TruffleBoundary(allowInlining = true) + protected int readIntoBuffer(ReadableByteChannel readableChannel, ByteBuffer dst) { + try { + return readableChannel.read(dst); + } catch (IOException e) { + gotException.enter(); + throw raise(OSError, e); + } + } + } + + public abstract static class ReadFromChannelNode extends ReadFromChannelBaseNode { + public static final int MAX_READ = Integer.MAX_VALUE / 2; + private final BranchProfile gotException = BranchProfile.create(); + + public abstract ByteSequenceStorage execute(Channel channel, int size); + + @Specialization + ByteSequenceStorage readSeekable(SeekableByteChannel channel, int size) { + long availableSize; + try { + availableSize = availableSize(channel); + } catch (IOException e) { + gotException.enter(); + throw raise(OSError, e); + } + if (availableSize > MAX_READ) { + availableSize = MAX_READ; + } + int sz = (int) Math.min(availableSize, size); + return readReadable(channel, sz); + } + + @Specialization + ByteSequenceStorage readReadable(ReadableByteChannel channel, int size) { + int sz = Math.min(size, MAX_READ); + ByteBuffer dst = allocateBuffer(sz); + int readSize = readIntoBuffer(channel, dst); + byte[] array; + if (readSize <= 0) { + array = new byte[0]; + readSize = 0; + } else { + array = getByteBufferArray(dst); + } + ByteSequenceStorage byteSequenceStorage = new ByteSequenceStorage(array); + byteSequenceStorage.setNewLength(readSize); + return byteSequenceStorage; + } + + @Specialization + ByteSequenceStorage readGeneric(Channel channel, int size) { + if (channel instanceof SeekableByteChannel) { + return readSeekable((SeekableByteChannel) channel, size); + } else if (channel instanceof ReadableByteChannel) { + return readReadable((ReadableByteChannel) channel, size); + } else { + throw raise(OSError, "file not opened for reading"); + } + } + + @TruffleBoundary(allowInlining = true) + private static ByteBuffer allocateBuffer(int sz) { + return ByteBuffer.allocate(sz); + } + + public static ReadFromChannelNode create() { + return ReadFromChannelNodeGen.create(); + } + } + + public abstract static class ReadByteFromChannelNode extends ReadFromChannelBaseNode { + + public abstract int execute(Channel channel); + + @Specialization + int readByte(ReadableByteChannel channel, + @Cached("createBinaryProfile()") ConditionProfile readProfile, + @Cached("create()") BranchProfile errorProfile) { + ByteBuffer buf = allocate(1); + int read = readIntoBuffer(channel, buf); + if (readProfile.profile(read != 1)) { + errorProfile.enter(); + throw raise(PythonBuiltinClassType.ValueError, "read byte out of range"); + } + return get(buf); + } + + @TruffleBoundary(allowInlining = true) + private static int get(ByteBuffer buf) { + return buf.get(); + } + + public static ReadByteFromChannelNode create() { + return ReadByteFromChannelNodeGen.create(); + } + } +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java index f40269c959..c79d8cc13f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java @@ -842,11 +842,11 @@ public Object createDirEntry(LazyPythonClass cls, String name, TruffleFile file) return trace(new PDirEntry(cls, name, file)); } - public PMMap createMMap(SeekableByteChannel channel) { - return trace(new PMMap(PythonBuiltinClassType.PMMap, channel)); + public PMMap createMMap(SeekableByteChannel channel, long length, long offset) { + return trace(new PMMap(PythonBuiltinClassType.PMMap, channel, length, offset)); } - public PMMap createMMap(LazyPythonClass clazz, SeekableByteChannel channel) { - return trace(new PMMap(clazz, channel)); + public PMMap createMMap(LazyPythonClass clazz, SeekableByteChannel channel, long length, long offset) { + return trace(new PMMap(clazz, channel, length, offset)); } } diff --git a/graalpython/lib-graalpython/mmap.py b/graalpython/lib-graalpython/mmap.py index ad6e1eb1e8..2d33028688 100644 --- a/graalpython/lib-graalpython/mmap.py +++ b/graalpython/lib-graalpython/mmap.py @@ -48,3 +48,5 @@ PROT_READ=0x1 PROT_WRITE=0x2 PROT_EXEC=0x4 + +PAGESIZE = 4096 From c8f715b1eb0e8dfec4f24d61eada01fb7a61bfda Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 07:35:16 +0100 Subject: [PATCH 143/202] Move 'CastToByteNode' to separate file. --- .../builtins/modules/ArrayModuleBuiltins.java | 2 +- .../builtins/modules/BuiltinConstructors.java | 2 +- .../builtins/modules/TruffleCextBuiltins.java | 2 +- .../objects/bytes/ByteArrayBuiltins.java | 5 +- .../builtins/objects/bytes/BytesNodes.java | 11 +- .../objects/common/SequenceStorageNodes.java | 96 +----------- .../python/nodes/util/CastToByteNode.java | 143 ++++++++++++++++++ .../sequence/storage/ByteSequenceStorage.java | 7 +- 8 files changed, 161 insertions(+), 107 deletions(-) create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java index 97541bb61c..dcb680ae34 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java @@ -38,7 +38,6 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.array.PArray; import com.oracle.graal.python.builtins.objects.common.SequenceNodes; -import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.CastToByteNode; import com.oracle.graal.python.builtins.objects.range.PRange; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.control.GetIteratorNode; @@ -46,6 +45,7 @@ import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; +import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.sequence.PSequence; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index 801d55a45b..f7f13d13b3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -93,7 +93,6 @@ import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; import com.oracle.graal.python.builtins.objects.common.PHashingCollection; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; -import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.CastToByteNode; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NoGeneralizationNode; import com.oracle.graal.python.builtins.objects.complex.PComplex; import com.oracle.graal.python.builtins.objects.dict.PDict; @@ -155,6 +154,7 @@ import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.nodes.subscript.SliceLiteralNode; import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; +import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.graal.python.nodes.util.CastToDoubleNode; import com.oracle.graal.python.nodes.util.CastToIndexNode; import com.oracle.graal.python.nodes.util.CastToStringNode; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index a72c8dbbf5..cae1c3d4c8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -96,7 +96,6 @@ import com.oracle.graal.python.builtins.objects.code.PCode; import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; -import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.CastToByteNode; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NormalizeIndexNode; import com.oracle.graal.python.builtins.objects.complex.PComplex; import com.oracle.graal.python.builtins.objects.dict.PDict; @@ -152,6 +151,7 @@ import com.oracle.graal.python.nodes.subscript.SliceLiteralNode; import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; import com.oracle.graal.python.nodes.truffle.PythonTypes; +import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.graal.python.nodes.util.CastToIndexNode; import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.PythonCore; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/ByteArrayBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/ByteArrayBuiltins.java index e3ac79b39a..bcc4115fc6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/ByteArrayBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/ByteArrayBuiltins.java @@ -75,6 +75,7 @@ import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; import com.oracle.graal.python.nodes.object.GetLazyClassNode; import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; +import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.graal.python.runtime.sequence.PSequence; import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage; @@ -358,7 +359,7 @@ public PByteArray append(PByteArray byteArray, Object arg, } protected static SequenceStorageNodes.AppendNode createAppend() { - return SequenceStorageNodes.AppendNode.create(() -> NoGeneralizationNode.create("byte must be in range(0, 256)")); + return SequenceStorageNodes.AppendNode.create(() -> NoGeneralizationNode.create(CastToByteNode.INVALID_BYTE_VALUE)); } } @@ -376,7 +377,7 @@ public PNone doGeneric(PByteArray byteArray, Object source, } protected static SequenceStorageNodes.ExtendNode createExtend() { - return SequenceStorageNodes.ExtendNode.create(() -> NoGeneralizationNode.create("byte must be in range(0, 256)")); + return SequenceStorageNodes.ExtendNode.create(() -> NoGeneralizationNode.create(CastToByteNode.INVALID_BYTE_VALUE)); } protected boolean isPSequenceWithStorage(Object source) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesNodes.java index 7ad7c0fb3d..aa3edb7d53 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesNodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -57,6 +57,7 @@ import com.oracle.graal.python.nodes.control.GetIteratorNode; import com.oracle.graal.python.nodes.control.GetNextNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; +import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.sequence.PSequence; import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; @@ -286,7 +287,7 @@ public static FindNode create() { public static class FromSequenceStorageNode extends Node { @Node.Child private SequenceStorageNodes.GetItemNode getItemNode; - @Node.Child private SequenceStorageNodes.CastToByteNode castToByteNode; + @Node.Child private CastToByteNode castToByteNode; @Node.Child private SequenceStorageNodes.LenNode lenNode; public byte[] execute(SequenceStorage storage) { @@ -307,10 +308,10 @@ private SequenceStorageNodes.GetItemNode getGetItemNode() { return getItemNode; } - private SequenceStorageNodes.CastToByteNode getCastToByteNode() { + private CastToByteNode getCastToByteNode() { if (castToByteNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castToByteNode = insert(SequenceStorageNodes.CastToByteNode.create()); + castToByteNode = insert(CastToByteNode.create()); } return castToByteNode; } @@ -355,7 +356,7 @@ public abstract static class FromIteratorNode extends PNodeWithContext { public SequenceStorageNodes.AppendNode getAppendByteNode() { if (appendByteNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - appendByteNode = insert(SequenceStorageNodes.AppendNode.create(() -> SequenceStorageNodes.NoGeneralizationNode.create("byte must be in range(0, 256)"))); + appendByteNode = insert(SequenceStorageNodes.AppendNode.create(() -> SequenceStorageNodes.NoGeneralizationNode.create(CastToByteNode.INVALID_BYTE_VALUE))); } return appendByteNode; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java index d47d8b4714..680a796a9c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -48,7 +48,6 @@ import java.util.Arrays; import java.util.function.BiFunction; -import java.util.function.Function; import java.util.function.Supplier; import com.oracle.graal.python.PythonLanguage; @@ -56,7 +55,6 @@ import com.oracle.graal.python.builtins.objects.cext.CExtNodes.PCallCapiFunction; import com.oracle.graal.python.builtins.objects.cext.NativeCAPISymbols; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.AppendNodeGen; -import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.CastToByteNodeGen; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.CmpNodeGen; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.ConcatBaseNodeGen; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.ConcatNodeGen; @@ -105,6 +103,7 @@ import com.oracle.graal.python.nodes.expression.CastToBooleanNode; import com.oracle.graal.python.nodes.object.GetLazyClassNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; +import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.graal.python.nodes.util.CastToIndexNode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.exception.PythonErrorType; @@ -1177,97 +1176,6 @@ public static StorageToNativeNode create() { } } - public abstract static class CastToByteNode extends PNodeWithContext { - - private final Function rangeErrorHandler; - private final Function typeErrorHandler; - - protected CastToByteNode(Function rangeErrorHandler, Function typeErrorHandler) { - this.rangeErrorHandler = rangeErrorHandler; - this.typeErrorHandler = typeErrorHandler; - } - - public abstract byte execute(Object val); - - @Specialization - protected byte doByte(byte value) { - return value; - } - - @Specialization(rewriteOn = ArithmeticException.class) - protected byte doInt(int value) { - return PInt.byteValueExact(value); - } - - @Specialization(replaces = "doInt") - protected byte doIntOvf(int value) { - try { - return PInt.byteValueExact(value); - } catch (ArithmeticException e) { - return handleRangeError(value); - } - } - - @Specialization(rewriteOn = ArithmeticException.class) - protected byte doLong(long value) { - return PInt.byteValueExact(value); - } - - @Specialization(replaces = "doLong") - protected byte doLongOvf(long value) { - try { - return PInt.byteValueExact(value); - } catch (ArithmeticException e) { - return handleRangeError(value); - } - } - - @Specialization(rewriteOn = ArithmeticException.class) - protected byte doPInt(PInt value) { - return PInt.byteValueExact(value.longValueExact()); - } - - @Specialization(replaces = "doPInt") - protected byte doPIntOvf(PInt value) { - try { - return PInt.byteValueExact(value.longValueExact()); - } catch (ArithmeticException e) { - return handleRangeError(value); - } - } - - @Specialization - protected byte doBoolean(boolean value) { - return value ? (byte) 1 : (byte) 0; - } - - @Fallback - protected byte doGeneric(@SuppressWarnings("unused") Object val) { - if (typeErrorHandler != null) { - return typeErrorHandler.apply(val); - } else { - throw raise(TypeError, "an integer is required (got type %p)", val); - } - } - - private byte handleRangeError(Object val) { - if (rangeErrorHandler != null) { - return rangeErrorHandler.apply(val); - } else { - throw raise(ValueError, "byte must be in range(0, 256)"); - } - } - - public static CastToByteNode create() { - return CastToByteNodeGen.create(null, null); - } - - public static CastToByteNode create(Function rangeErrorHandler, Function typeErrorHandler) { - return CastToByteNodeGen.create(rangeErrorHandler, typeErrorHandler); - } - - } - protected abstract static class BinCmpOp { protected abstract boolean cmp(int l, int r); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java new file mode 100644 index 0000000000..9853d37309 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2019, 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 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.nodes.util; + +import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError; +import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError; + +import java.util.function.Function; + +import com.oracle.graal.python.builtins.objects.ints.PInt; +import com.oracle.graal.python.nodes.PNodeWithContext; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; + +public abstract class CastToByteNode extends PNodeWithContext { + public static final String INVALID_BYTE_VALUE = "byte must be in range(0, 256)"; + + private final Function rangeErrorHandler; + private final Function typeErrorHandler; + + protected CastToByteNode(Function rangeErrorHandler, Function typeErrorHandler) { + this.rangeErrorHandler = rangeErrorHandler; + this.typeErrorHandler = typeErrorHandler; + } + + public abstract byte execute(Object val); + + @Specialization + protected byte doByte(byte value) { + return value; + } + + @Specialization(rewriteOn = ArithmeticException.class) + protected byte doInt(int value) { + return PInt.byteValueExact(value); + } + + @Specialization(replaces = "doInt") + protected byte doIntOvf(int value) { + try { + return PInt.byteValueExact(value); + } catch (ArithmeticException e) { + return handleRangeError(value); + } + } + + @Specialization(rewriteOn = ArithmeticException.class) + protected byte doLong(long value) { + return PInt.byteValueExact(value); + } + + @Specialization(replaces = "doLong") + protected byte doLongOvf(long value) { + try { + return PInt.byteValueExact(value); + } catch (ArithmeticException e) { + return handleRangeError(value); + } + } + + @Specialization(rewriteOn = ArithmeticException.class) + protected byte doPInt(PInt value) { + return PInt.byteValueExact(value.longValueExact()); + } + + @Specialization(replaces = "doPInt") + protected byte doPIntOvf(PInt value) { + try { + return PInt.byteValueExact(value.longValueExact()); + } catch (ArithmeticException e) { + return handleRangeError(value); + } + } + + @Specialization + protected byte doBoolean(boolean value) { + return value ? (byte) 1 : (byte) 0; + } + + @Fallback + protected byte doGeneric(@SuppressWarnings("unused") Object val) { + if (typeErrorHandler != null) { + return typeErrorHandler.apply(val); + } else { + throw raise(TypeError, "an integer is required (got type %p)", val); + } + } + + private byte handleRangeError(Object val) { + if (rangeErrorHandler != null) { + return rangeErrorHandler.apply(val); + } else { + throw raise(ValueError, INVALID_BYTE_VALUE); + } + } + + public static CastToByteNode create() { + return CastToByteNodeGen.create(null, null); + } + + public static CastToByteNode create(Function rangeErrorHandler, Function typeErrorHandler) { + return CastToByteNodeGen.create(rangeErrorHandler, typeErrorHandler); + } + +} \ No newline at end of file diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/ByteSequenceStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/ByteSequenceStorage.java index 3f63af6263..fe8abca92b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/ByteSequenceStorage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/ByteSequenceStorage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -31,6 +31,7 @@ import java.util.Arrays; import com.oracle.graal.python.PythonLanguage; +import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; public final class ByteSequenceStorage extends TypedSequenceStorage { @@ -113,7 +114,7 @@ public void setItemNormalized(int idx, Object value) throws SequenceStoreExcepti setByteItemNormalized(idx, (byte) value); } else if (value instanceof Integer) { if ((int) value < 0 || (int) value >= 256) { - throw PythonLanguage.getCore().raise(ValueError, "byte must be in range(0, 256)"); + throw PythonLanguage.getCore().raise(ValueError, CastToByteNode.INVALID_BYTE_VALUE); } setByteItemNormalized(idx, ((Integer) value).byteValue()); } else { @@ -190,7 +191,7 @@ public void setByteSliceInBound(int start, int stop, int step, IntSequenceStorag int i = start; for (int j = 0; j < otherLength; i += step, j++) { if (seqValues[j] < Byte.MIN_VALUE || seqValues[j] > Byte.MAX_VALUE) { - throw PythonLanguage.getCore().raise(ValueError, "byte must be in range(0, 256)"); + throw PythonLanguage.getCore().raise(ValueError, CastToByteNode.INVALID_BYTE_VALUE); } values[i] = (byte) seqValues[j]; } From 31d67830d75aa7dbfa688a27e7ef621e9263d2c4 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 07:59:28 +0100 Subject: [PATCH 144/202] Implement 'mmap.readline'. --- .../builtins/objects/mmap/MMapBuiltins.java | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index a7ac63b89b..c5d6667030 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -68,6 +68,8 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.bytes.PBytes; +import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; +import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NoGeneralizationNode; import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; @@ -77,6 +79,7 @@ import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; +import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.graal.python.nodes.util.CastToIndexNode; import com.oracle.graal.python.nodes.util.ChannelNodes.ReadByteFromChannelNode; import com.oracle.graal.python.nodes.util.ChannelNodes.ReadFromChannelNode; @@ -84,7 +87,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateNodeFactory; -import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; @@ -290,24 +292,43 @@ PBytes read(PMMap self, Object n, abstract static class ReadlineNode extends PythonBuiltinNode { @Specialization - @TruffleBoundary - Object readline(PMMap self) { + Object readline(PMMap self, + @Cached("createAppend()") SequenceStorageNodes.AppendNode appendNode) { try { ByteBuffer buf = ByteBuffer.allocate(4096); SeekableByteChannel channel = self.getChannel(); + ByteSequenceStorage res = new ByteSequenceStorage(16); // search for newline char - int nread; - while ((nread = channel.read(buf)) > 0) { - for (int i = 0; i < buf.remaining(); i++) { - + outer: while (readIntoBuffer(channel, buf) > 0) { + buf.flip(); + while (buf.hasRemaining()) { + byte b = buf.get(); + // CPython really tests for '\n' only + if (b != (byte) '\n') { + appendNode.execute(res, b); + } else { + // recover correct position (i.e. number of remaining bytes in buffer) + channel.position(channel.position() - buf.remaining() - 1); + break outer; + } } + buf.clear(); } - return null; + return factory().createBytes(res); } catch (IOException e) { throw raise(PythonBuiltinClassType.OSError, e.getMessage()); } } + + @TruffleBoundary(allowInlining = true) + private static int readIntoBuffer(SeekableByteChannel ch, ByteBuffer dst) throws IOException { + return ch.read(dst); + } + + protected static SequenceStorageNodes.AppendNode createAppend() { + return SequenceStorageNodes.AppendNode.create(() -> NoGeneralizationNode.create(CastToByteNode.INVALID_BYTE_VALUE)); + } } @Builtin(name = "seek", fixedNumOfPositionalArgs = 1) From 86bfe1fbbb2691c171fa3e8c43ce56cd02deeb14 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 09:52:44 +0100 Subject: [PATCH 145/202] Support anonymous mmap. --- .../builtins/modules/MMapModuleBuiltins.java | 82 ++++++++++++++++++- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java index 8545459c80..16a56cff5d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java @@ -45,6 +45,8 @@ import java.io.IOException; import java.nio.channels.FileChannel.MapMode; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; import java.nio.channels.SeekableByteChannel; import java.nio.file.StandardOpenOption; import java.util.HashSet; @@ -64,6 +66,7 @@ import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ValueProfile; @CoreFunctions(defineModule = "mmap") @@ -90,15 +93,24 @@ public MMapModuleBuiltins() { public abstract static class MMapNode extends PythonBuiltinNode { private final ValueProfile classProfile = ValueProfile.createClassProfile(); + private final BranchProfile invalidLengthProfile = BranchProfile.create(); - @Specialization(guards = {"isNoValue(access)", "isNoValue(offset)"}) + @Specialization(guards = {"fd < 0", "isNoValue(access)", "isNoValue(offset)"}) + PMMap doAnonymous(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access, @SuppressWarnings("unused") PNone offset) { + checkLength(length); + return new PMMap(clazz, new AnonymousMap(length), length, 0); + } + + @Specialization(guards = {"fd >= 0", "isNoValue(access)", "isNoValue(offset)"}) PMMap doIt(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access, @SuppressWarnings("unused") PNone offset) { - return doGeneric(clazz, fd, length, tagname, ACCESS_DEFAULT, 0); + return doFile(clazz, fd, length, tagname, ACCESS_DEFAULT, 0); } // mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset]) - @Specialization - PMMap doGeneric(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, int access, long offset) { + @Specialization(guards = "fd >= 0") + PMMap doFile(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, int access, long offset) { + checkLength(length); + String path = getContext().getResources().getFilePath(fd); TruffleFile truffleFile = getContext().getEnv().getTruffleFile(path); @@ -133,5 +145,67 @@ private MapMode convertAccessToMapMode(int access) { throw raise(ValueError, "mmap invalid access parameter."); } + private void checkLength(int length) { + if (length < 0) { + invalidLengthProfile.enter(); + throw raise(PythonBuiltinClassType.OverflowError, "memory mapped length must be positive"); + } + } + + } + + private static class AnonymousMap implements SeekableByteChannel { + private final byte[] data; + + private boolean open = true; + private int cur; + + public AnonymousMap(int cap) { + this.data = new byte[cap]; + } + + public boolean isOpen() { + return open; + } + + public void close() throws IOException { + open = false; + } + + public int read(ByteBuffer dst) throws IOException { + int nread = Math.min(dst.remaining(), data.length - cur); + dst.put(data, cur, nread); + return nread; + } + + public int write(ByteBuffer src) throws IOException { + int nwrite = Math.min(src.remaining(), data.length - cur); + src.get(data, cur, nwrite); + return nwrite; + } + + public long position() throws IOException { + return cur; + } + + public SeekableByteChannel position(long newPosition) throws IOException { + if (newPosition < 0 || newPosition >= data.length) { + throw new IllegalArgumentException(); + } + cur = (int) newPosition; + return this; + } + + public long size() throws IOException { + return data.length; + } + + public SeekableByteChannel truncate(long size) throws IOException { + for (int i = 0; i < size; i++) { + data[i] = 0; + } + return this; + } + } } From eae700540ffdd428fca9005f336b718ecfdf9bfd Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 09:53:12 +0100 Subject: [PATCH 146/202] Implement 'mmap.find' and mman subscript. --- .../builtins/objects/mmap/MMapBuiltins.java | 225 ++++++++++++++++-- .../graal/python/nodes/util/ChannelNodes.java | 1 + 2 files changed, 209 insertions(+), 17 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index c5d6667030..71aad2a5ed 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -68,9 +68,16 @@ import com.oracle.graal.python.builtins.PythonBuiltins; import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.bytes.PBytes; +import com.oracle.graal.python.builtins.objects.bytes.PIBytesLike; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NoGeneralizationNode; +import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NormalizeIndexNode; import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum; +import com.oracle.graal.python.builtins.objects.ints.PInt; +import com.oracle.graal.python.builtins.objects.mmap.MMapBuiltinsFactory.InternalLenNodeGen; +import com.oracle.graal.python.builtins.objects.slice.PSlice; +import com.oracle.graal.python.builtins.objects.slice.PSlice.SliceInfo; +import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.SpecialMethodNames; import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; @@ -81,9 +88,12 @@ import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.graal.python.nodes.util.CastToIndexNode; +import com.oracle.graal.python.nodes.util.CastToJavaLongNode; import com.oracle.graal.python.nodes.util.ChannelNodes.ReadByteFromChannelNode; import com.oracle.graal.python.nodes.util.ChannelNodes.ReadFromChannelNode; import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; +import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateNodeFactory; @@ -91,7 +101,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.BranchProfile; @CoreFunctions(extendClasses = PythonBuiltinClassType.PMMap) public class MMapBuiltins extends PythonBuiltins { @@ -163,7 +173,59 @@ abstract static class ReprNode extends StrNode { @Builtin(name = __GETITEM__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - abstract static class GetItemNode extends PythonBinaryBuiltinNode { + abstract static class GetItemNode extends PythonBuiltinNode { + + @Specialization(guards = "!isPSlice(idxObj)") + int doSingle(VirtualFrame frame, PMMap self, Object idxObj, + @Cached("create()") ReadByteFromChannelNode readByteNode, + @Cached("createExact()") CastToJavaLongNode castToLongNode, + @Cached("create()") InternalLenNode lenNode) { + + try { + long i = castToLongNode.execute(idxObj); + long len = lenNode.execute(frame, self); + SeekableByteChannel channel = self.getChannel(); + long idx = i < 0 ? i + len : i; + + // save current position + long oldPos = channel.position(); + + channel.position(idx); + int res = readByteNode.execute(channel); + + // restore position + channel.position(oldPos); + + return res; + + } catch (IOException e) { + throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + } + } + + @Specialization + Object doSlice(VirtualFrame frame, PMMap self, PSlice idx, + @Cached("create()") ReadFromChannelNode readNode, + @Cached("create()") InternalLenNode lenNode) { + try { + long len = lenNode.execute(frame, self); + SliceInfo info = idx.computeIndices(PInt.intValueExact(len)); + SeekableByteChannel channel = self.getChannel(); + + // save current position + long oldPos = channel.position(); + + channel.position(info.start); + ByteSequenceStorage s = readNode.execute(channel, info.length); + + // restore position + channel.position(oldPos); + + return factory().createBytes(s); + } catch (IOException e) { + throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + } + } } @Builtin(name = SpecialMethodNames.__SETITEM__, fixedNumOfPositionalArgs = 3) @@ -176,12 +238,9 @@ abstract static class SetItemNode extends PythonTernaryBuiltinNode { @GenerateNodeFactory public abstract static class LenNode extends PythonBuiltinNode { @Specialization - long len(VirtualFrame frame, PMMap self) { - try { - return self.getChannel().size(); - } catch (IOException e) { - throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); - } + long len(VirtualFrame frame, PMMap self, + @Cached("create()") InternalLenNode lenNode) { + return lenNode.execute(frame, self); } } @@ -227,15 +286,8 @@ abstract static class SizeNode extends PythonBuiltinNode { @Specialization long size(VirtualFrame frame, PMMap self, - @Cached("createBinaryProfile()") ConditionProfile profile) { - if (profile.profile(self.getLength() == 0)) { - try { - return self.getChannel().size() - self.getOffset(); - } catch (IOException e) { - throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); - } - } - return self.getLength(); + @Cached("create()") InternalLenNode lenNode) { + return lenNode.execute(frame, self); } } @@ -378,4 +430,143 @@ private Object doSeek(PMMap self, long dist, int how) throws IOException { } } + @Builtin(name = "find", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 4) + @GenerateNodeFactory + @TypeSystemReference(PythonArithmeticTypes.class) + public abstract static class FindNode extends PythonBuiltinNode { + + @Child private NormalizeIndexNode normalizeIndexNode; + @Child private SequenceStorageNodes.GetItemNode getLeftItemNode; + @Child private SequenceStorageNodes.GetItemNode getRightItemNode; + + public abstract long execute(PMMap bytes, Object sub, Object starting, Object ending); + + @Specialization + long find(PMMap primary, PIBytesLike sub, Object starting, Object ending, + @Cached("create()") ReadByteFromChannelNode readByteNode) { + try { + SeekableByteChannel channel = primary.getChannel(); + long len1 = channel.size(); + + SequenceStorage needle = sub.getSequenceStorage(); + int len2 = needle.length(); + + long s = castToLong(starting, 0); + long e = castToLong(ending, len1); + + long start = s < 0 ? s + len1 : s; + long end = e < 0 ? e + len1 : e; + + if (start >= len1 || len1 < len2) { + return -1; + } else if (end > len1) { + end = len1; + } + + // TODO implement a more efficient algorithm + outer: for (long i = start; i < end; i++) { + // TODO(fa) don't seek but use circular buffer + channel.position(i); + for (int j = 0; j < len2; j++) { + int hb = readByteNode.execute(channel); + int nb = getGetRightItemNode().executeInt(needle, j); + if (nb != hb || i + j >= end) { + continue outer; + } + } + return i; + } + return -1; + } catch (IOException e) { + throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + } + } + + @Specialization + long find(PMMap primary, int sub, Object starting, @SuppressWarnings("unused") Object ending, + @Cached("create()") ReadByteFromChannelNode readByteNode) { + try { + SeekableByteChannel channel = primary.getChannel(); + long len1 = channel.size(); + + long s = castToLong(starting, 0); + long e = castToLong(ending, len1); + + long start = s < 0 ? s + len1 : s; + long end = Math.max(e < 0 ? e + len1 : e, len1); + + channel.position(start); + + for (long i = start; i < end; i++) { + int hb = readByteNode.execute(channel); + if (hb == sub) { + return i; + } + } + return -1; + } catch (IOException e) { + throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + } + } + + // TODO(fa): use node + private static long castToLong(Object obj, long defaultVal) { + if (obj instanceof Integer || obj instanceof Long) { + return ((Number) obj).longValue(); + } else if (obj instanceof PInt) { + try { + return ((PInt) obj).longValueExact(); + } catch (ArithmeticException e) { + return defaultVal; + } + } + return defaultVal; + } + + private SequenceStorageNodes.GetItemNode getGetRightItemNode() { + if (getRightItemNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getRightItemNode = insert(SequenceStorageNodes.GetItemNode.create()); + } + return getRightItemNode; + } + } + + abstract static class InternalLenNode extends PNodeWithContext { + + public abstract long execute(VirtualFrame frame, PMMap self); + + @Specialization(guards = "self.getLength() == 0") + long doFull(VirtualFrame frame, PMMap self, + @Cached("create()") BranchProfile profile) { + try { + return self.getChannel().size() - self.getOffset(); + } catch (IOException e) { + profile.enter(); + throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + } + } + + @Specialization(guards = "self.getLength() > 0") + long doWindow(@SuppressWarnings("unused") VirtualFrame frame, PMMap self) { + return self.getLength(); + } + + @Specialization + long doGeneric(VirtualFrame frame, PMMap self) { + if (self.getLength() == 0) { + try { + return self.getChannel().size() - self.getOffset(); + } catch (IOException e) { + throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + } + } + return self.getLength(); + } + + public static InternalLenNode create() { + return InternalLenNodeGen.create(); + } + } + } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java index ca3528c1f8..f1ad3fd1e2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java @@ -133,6 +133,7 @@ int readByte(ReadableByteChannel channel, @TruffleBoundary(allowInlining = true) private static int get(ByteBuffer buf) { + buf.flip(); return buf.get(); } From 4eed044691bf35d7f7115a338024319b76363d46 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 13:23:30 +0100 Subject: [PATCH 147/202] Implement 'mmap.__setitem__'. --- .../builtins/objects/mmap/MMapBuiltins.java | 152 ++++++++++++++- .../python/nodes/util/CastToByteNode.java | 24 ++- .../graal/python/nodes/util/ChannelNodes.java | 178 +++++++++++++++++- 3 files changed, 336 insertions(+), 18 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index 71aad2a5ed..7b132a0763 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -59,6 +59,7 @@ import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.channels.Channel; import java.nio.channels.SeekableByteChannel; import java.util.List; @@ -69,6 +70,7 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.bytes.PBytes; import com.oracle.graal.python.builtins.objects.bytes.PIBytesLike; +import com.oracle.graal.python.builtins.objects.common.SequenceNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NoGeneralizationNode; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NormalizeIndexNode; @@ -83,14 +85,16 @@ import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode; -import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; import com.oracle.graal.python.nodes.util.CastToByteNode; import com.oracle.graal.python.nodes.util.CastToIndexNode; import com.oracle.graal.python.nodes.util.CastToJavaLongNode; +import com.oracle.graal.python.nodes.util.ChannelNodes; import com.oracle.graal.python.nodes.util.ChannelNodes.ReadByteFromChannelNode; import com.oracle.graal.python.nodes.util.ChannelNodes.ReadFromChannelNode; +import com.oracle.graal.python.nodes.util.ChannelNodes.WriteByteToChannelNode; +import com.oracle.graal.python.nodes.util.ChannelNodes.WriteToChannelNode; import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage; import com.oracle.truffle.api.CompilerDirectives; @@ -102,10 +106,59 @@ import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; @CoreFunctions(extendClasses = PythonBuiltinClassType.PMMap) public class MMapBuiltins extends PythonBuiltins { + protected interface ByteReadingNode { + + static ReadByteFromChannelNode createValueError() { + return ReadByteFromChannelNode.create(() -> new ChannelNodes.ReadByteErrorHandler() { + + @Override + public int execute(Channel channel) { + throw raise(PythonBuiltinClassType.ValueError, "read byte out of range"); + } + }); + } + + static ReadByteFromChannelNode createIndexError() { + return ReadByteFromChannelNode.create(() -> new ChannelNodes.ReadByteErrorHandler() { + + @Override + public int execute(Channel channel) { + throw raise(PythonBuiltinClassType.IndexError, "mmap index out of range"); + } + }); + + } + } + + protected interface ByteWritingNode { + + static WriteByteToChannelNode createValueError() { + return WriteByteToChannelNode.create(() -> new ChannelNodes.WriteByteErrorHandler() { + + @Override + public void execute(Channel channel, byte b) { + throw raise(PythonBuiltinClassType.ValueError, "write byte out of range"); + } + }); + } + + static WriteByteToChannelNode createIndexError() { + return WriteByteToChannelNode.create(() -> new ChannelNodes.WriteByteErrorHandler() { + + @Override + public void execute(Channel channel, byte b) { + throw raise(PythonBuiltinClassType.IndexError, "mmap index out of range"); + } + }); + + } + } + @Override protected List> getNodeFactories() { return MMapBuiltinsFactory.getFactories(); @@ -173,11 +226,11 @@ abstract static class ReprNode extends StrNode { @Builtin(name = __GETITEM__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - abstract static class GetItemNode extends PythonBuiltinNode { + abstract static class GetItemNode extends PythonBuiltinNode implements ByteReadingNode { @Specialization(guards = "!isPSlice(idxObj)") int doSingle(VirtualFrame frame, PMMap self, Object idxObj, - @Cached("create()") ReadByteFromChannelNode readByteNode, + @Cached("createIndexError()") ReadByteFromChannelNode readByteNode, @Cached("createExact()") CastToJavaLongNode castToLongNode, @Cached("create()") InternalLenNode lenNode) { @@ -226,12 +279,82 @@ Object doSlice(VirtualFrame frame, PMMap self, PSlice idx, throw raise(PythonBuiltinClassType.OSError, e.getMessage()); } } + } @Builtin(name = SpecialMethodNames.__SETITEM__, fixedNumOfPositionalArgs = 3) @GenerateNodeFactory - abstract static class SetItemNode extends PythonTernaryBuiltinNode { + abstract static class SetItemNode extends PythonBuiltinNode implements ByteWritingNode { + + @Specialization(guards = "!isPSlice(idxObj)") + PNone doSingle(VirtualFrame frame, PMMap self, Object idxObj, Object val, + @Cached("createIndexError()") WriteByteToChannelNode writeByteNode, + @Cached("createExact()") CastToJavaLongNode castToLongNode, + @Cached("createCoerce()") CastToByteNode castToByteNode, + @Cached("create()") InternalLenNode lenNode, + @Cached("createBinaryProfile()") ConditionProfile outOfRangeProfile) { + + try { + long i = castToLongNode.execute(idxObj); + long len = lenNode.execute(frame, self); + SeekableByteChannel channel = self.getChannel(); + long idx = i < 0 ? i + len : i; + + if (outOfRangeProfile.profile(idx < 0 || idx >= len)) { + throw raise(PythonBuiltinClassType.IndexError, "mmap index out of range"); + } + + // save current position + long oldPos = channel.position(); + channel.position(idx); + writeByteNode.execute(channel, castToByteNode.execute(val)); + + // restore position + channel.position(oldPos); + + return PNone.NONE; + + } catch (IOException e) { + throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + } + } + + @Specialization + PNone doSlice(VirtualFrame frame, PMMap self, PSlice idx, PIBytesLike val, + @Cached("create()") WriteToChannelNode writeNode, + @Cached("create()") SequenceNodes.GetSequenceStorageNode getStorageNode, + @Cached("create()") InternalLenNode lenNode, + @Cached("createBinaryProfile()") ConditionProfile invalidStepProfile) { + + try { + long len = lenNode.execute(frame, self); + SliceInfo info = idx.computeIndices(PInt.intValueExact(len)); + SeekableByteChannel channel = self.getChannel(); + + if (invalidStepProfile.profile(info.step != 1)) { + throw raise(PythonBuiltinClassType.SystemError, "step != 1 not supported"); + } + + // save current position + long oldPos = channel.position(); + + channel.position(info.start); + writeNode.execute(channel, getStorageNode.execute(val), info.length); + + // restore position + channel.position(oldPos); + + return PNone.NONE; + + } catch (IOException e) { + throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + } + } + + protected static CastToByteNode createCoerce() { + return CastToByteNode.create(true); + } } @Builtin(name = __LEN__, fixedNumOfPositionalArgs = 1) @@ -280,6 +403,16 @@ PNone close(PMMap self) { } } + @Builtin(name = "closed", fixedNumOfPositionalArgs = 1, isGetter = true) + @GenerateNodeFactory + abstract static class ClosedNode extends PythonUnaryBuiltinNode { + + @Specialization + boolean close(PMMap self) { + return !self.getChannel().isOpen(); + } + } + @Builtin(name = "size", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory abstract static class SizeNode extends PythonBuiltinNode { @@ -309,11 +442,11 @@ long readline(VirtualFrame frame, PMMap self) { @Builtin(name = "read_byte", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) - abstract static class ReadByteNode extends PythonUnaryBuiltinNode { + abstract static class ReadByteNode extends PythonUnaryBuiltinNode implements ByteReadingNode { @Specialization int readByte(PMMap self, - @Cached("create()") ReadByteFromChannelNode readByteNode) { + @Cached("createValueError()") ReadByteFromChannelNode readByteNode) { return readByteNode.execute(self.getChannel()); } } @@ -337,6 +470,7 @@ PBytes read(PMMap self, Object n, ByteSequenceStorage res = readChannelNode.execute(self.getChannel(), castToIndexNode.execute(n)); return factory().createBytes(res); } + } @Builtin(name = "readline", fixedNumOfPositionalArgs = 1) @@ -433,7 +567,7 @@ private Object doSeek(PMMap self, long dist, int how) throws IOException { @Builtin(name = "find", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 4) @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) - public abstract static class FindNode extends PythonBuiltinNode { + public abstract static class FindNode extends PythonBuiltinNode implements ByteReadingNode { @Child private NormalizeIndexNode normalizeIndexNode; @Child private SequenceStorageNodes.GetItemNode getLeftItemNode; @@ -443,7 +577,7 @@ public abstract static class FindNode extends PythonBuiltinNode { @Specialization long find(PMMap primary, PIBytesLike sub, Object starting, Object ending, - @Cached("create()") ReadByteFromChannelNode readByteNode) { + @Cached("createValueError()") ReadByteFromChannelNode readByteNode) { try { SeekableByteChannel channel = primary.getChannel(); long len1 = channel.size(); @@ -484,7 +618,7 @@ long find(PMMap primary, PIBytesLike sub, Object starting, Object ending, @Specialization long find(PMMap primary, int sub, Object starting, @SuppressWarnings("unused") Object ending, - @Cached("create()") ReadByteFromChannelNode readByteNode) { + @Cached("createValueError()") ReadByteFromChannelNode readByteNode) { try { SeekableByteChannel channel = primary.getChannel(); long len1 = channel.size(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java index 9853d37309..a3671b21d0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java @@ -45,8 +45,12 @@ import java.util.function.Function; +import com.oracle.graal.python.builtins.objects.bytes.PIBytesLike; +import com.oracle.graal.python.builtins.objects.common.SequenceNodes; +import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.nodes.PNodeWithContext; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; @@ -55,10 +59,12 @@ public abstract class CastToByteNode extends PNodeWithContext { private final Function rangeErrorHandler; private final Function typeErrorHandler; + protected final boolean coerce; - protected CastToByteNode(Function rangeErrorHandler, Function typeErrorHandler) { + protected CastToByteNode(Function rangeErrorHandler, Function typeErrorHandler, boolean coerce) { this.rangeErrorHandler = rangeErrorHandler; this.typeErrorHandler = typeErrorHandler; + this.coerce = coerce; } public abstract byte execute(Object val); @@ -115,6 +121,13 @@ protected byte doBoolean(boolean value) { return value ? (byte) 1 : (byte) 0; } + @Specialization(guards = "coerce") + protected byte doBytes(PIBytesLike value, + @Cached("create()") SequenceNodes.GetSequenceStorageNode getStorageNode, + @Cached("create()") SequenceStorageNodes.GetItemNode getItemNode) { + return doIntOvf(getItemNode.executeInt(getStorageNode.execute(value), 0)); + } + @Fallback protected byte doGeneric(@SuppressWarnings("unused") Object val) { if (typeErrorHandler != null) { @@ -133,11 +146,18 @@ private byte handleRangeError(Object val) { } public static CastToByteNode create() { - return CastToByteNodeGen.create(null, null); + return CastToByteNodeGen.create(null, null, false); + } + + public static CastToByteNode create(boolean coerce) { + return CastToByteNodeGen.create(null, null, coerce); } public static CastToByteNode create(Function rangeErrorHandler, Function typeErrorHandler) { return CastToByteNodeGen.create(rangeErrorHandler, typeErrorHandler); } + public static CastToByteNode create(Function rangeErrorHandler, Function typeErrorHandler, boolean coerce) { + return CastToByteNodeGen.create(rangeErrorHandler, typeErrorHandler, coerce); + } } \ No newline at end of file diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java index f1ad3fd1e2..5615ce7c35 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java @@ -7,12 +7,18 @@ import java.nio.channels.Channel; import java.nio.channels.ReadableByteChannel; import java.nio.channels.SeekableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.function.Supplier; -import com.oracle.graal.python.builtins.PythonBuiltinClassType; +import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes; import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.util.ChannelNodesFactory.ReadByteFromChannelNodeGen; import com.oracle.graal.python.nodes.util.ChannelNodesFactory.ReadFromChannelNodeGen; +import com.oracle.graal.python.nodes.util.ChannelNodesFactory.WriteByteToChannelNodeGen; +import com.oracle.graal.python.nodes.util.ChannelNodesFactory.WriteToChannelNodeGen; import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; +import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -24,6 +30,14 @@ public abstract static class ReadErrorHandler extends PNodeWithContext { public abstract Object execute(Channel channel, int nrequested, int nread); } + public abstract static class ReadByteErrorHandler extends PNodeWithContext { + public abstract int execute(Channel channel); + } + + public abstract static class WriteByteErrorHandler extends PNodeWithContext { + public abstract void execute(Channel channel, byte b); + } + abstract static class ReadFromChannelBaseNode extends PNodeWithContext { private final BranchProfile gotException = BranchProfile.create(); @@ -54,6 +68,36 @@ protected int readIntoBuffer(ReadableByteChannel readableChannel, ByteBuffer dst } } + abstract static class WriteToChannelBaseNode extends PNodeWithContext { + + private final BranchProfile gotException = BranchProfile.create(); + + @TruffleBoundary(allowInlining = true) + protected static ByteBuffer allocate(int n) { + return ByteBuffer.allocate(n); + } + + @TruffleBoundary(transferToInterpreterOnException = false) + protected static long availableSize(SeekableByteChannel channel) throws IOException { + return channel.size() - channel.position(); + } + + @TruffleBoundary(allowInlining = true) + protected static byte[] getByteBufferArray(ByteBuffer dst) { + return dst.array(); + } + + @TruffleBoundary(allowInlining = true) + protected int writeFromBuffer(WritableByteChannel writableChannel, ByteBuffer src) { + try { + return writableChannel.write(src); + } catch (IOException e) { + gotException.enter(); + throw raise(OSError, e); + } + } + } + public abstract static class ReadFromChannelNode extends ReadFromChannelBaseNode { public static final int MAX_READ = Integer.MAX_VALUE / 2; private final BranchProfile gotException = BranchProfile.create(); @@ -116,29 +160,149 @@ public static ReadFromChannelNode create() { public abstract static class ReadByteFromChannelNode extends ReadFromChannelBaseNode { + @Child private ReadByteErrorHandler errorHandler; + + private final Supplier errorHandlerFactory; + + public ReadByteFromChannelNode(Supplier errorHandlerFactory) { + this.errorHandlerFactory = errorHandlerFactory; + } + public abstract int execute(Channel channel); @Specialization int readByte(ReadableByteChannel channel, - @Cached("createBinaryProfile()") ConditionProfile readProfile, - @Cached("create()") BranchProfile errorProfile) { + @Cached("createBinaryProfile()") ConditionProfile readProfile) { ByteBuffer buf = allocate(1); int read = readIntoBuffer(channel, buf); if (readProfile.profile(read != 1)) { - errorProfile.enter(); - throw raise(PythonBuiltinClassType.ValueError, "read byte out of range"); + return handleError(channel); } return get(buf); } + private int handleError(Channel channel) { + if (errorHandler == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + errorHandler = insert(errorHandlerFactory.get()); + } + return errorHandler.execute(channel); + } + @TruffleBoundary(allowInlining = true) private static int get(ByteBuffer buf) { buf.flip(); return buf.get(); } - public static ReadByteFromChannelNode create() { - return ReadByteFromChannelNodeGen.create(); + public static ReadByteFromChannelNode create(Supplier errorHandlerFactory) { + return ReadByteFromChannelNodeGen.create(errorHandlerFactory); } } + + public abstract static class WriteByteToChannelNode extends WriteToChannelBaseNode { + + @Child private WriteByteErrorHandler errorHandler; + + private final Supplier errorHandlerFactory; + + public WriteByteToChannelNode(Supplier errorHandlerFactory) { + this.errorHandlerFactory = errorHandlerFactory; + } + + public abstract void execute(Channel channel, byte b); + + @Specialization + void readByte(WritableByteChannel channel, byte b, + @Cached("createBinaryProfile()") ConditionProfile readProfile) { + ByteBuffer buf = allocate(1); + put(b, buf); + int read = writeFromBuffer(channel, buf); + if (readProfile.profile(read != 1)) { + handleError(channel, b); + } + } + + @TruffleBoundary(allowInlining = true) + private static void put(byte b, ByteBuffer buf) { + buf.put(b); + buf.flip(); + } + + private void handleError(Channel channel, byte b) { + if (errorHandler == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + errorHandler = insert(errorHandlerFactory.get()); + } + errorHandler.execute(channel, b); + } + + public static WriteByteToChannelNode create(Supplier errorHandlerFactory) { + return WriteByteToChannelNodeGen.create(errorHandlerFactory); + } + } + + public abstract static class WriteToChannelNode extends WriteToChannelBaseNode { + @Child private SequenceStorageNodes.ToByteArrayNode toByteArrayNode; + + public static final int MAX_WRITE = Integer.MAX_VALUE / 2; + private final BranchProfile gotException = BranchProfile.create(); + + public abstract int execute(Channel channel, SequenceStorage s, int len); + + @Specialization + int writeSeekable(SeekableByteChannel channel, SequenceStorage s, int len) { + long availableSize; + try { + availableSize = availableSize(channel); + } catch (IOException e) { + gotException.enter(); + throw raise(OSError, e); + } + if (availableSize > MAX_WRITE) { + availableSize = MAX_WRITE; + } + int sz = (int) Math.min(availableSize, len); + return writeWritable(channel, s, sz); + + } + + @Specialization + int writeWritable(WritableByteChannel channel, SequenceStorage s, int len) { + ByteBuffer src = allocateBuffer(getBytes(s)); + if (src.remaining() > len) { + src.limit(len); + } + return writeFromBuffer(channel, src); + } + + @Specialization + int writeGeneric(Channel channel, SequenceStorage s, int len) { + if (channel instanceof SeekableByteChannel) { + return writeSeekable((SeekableByteChannel) channel, s, len); + } else if (channel instanceof ReadableByteChannel) { + return writeWritable((WritableByteChannel) channel, s, len); + } else { + throw raise(OSError, "file not opened for reading"); + } + } + + @TruffleBoundary(allowInlining = true) + private static ByteBuffer allocateBuffer(byte[] data) { + return ByteBuffer.wrap(data); + } + + private byte[] getBytes(SequenceStorage s) { + if (toByteArrayNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + toByteArrayNode = insert(SequenceStorageNodes.ToByteArrayNode.create(true)); + } + return toByteArrayNode.execute(s); + } + + public static WriteToChannelNode create() { + return WriteToChannelNodeGen.create(); + } + } + } From 54933e1ba393b73b7f02ae47ac73540eb6b0b358 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 14:15:27 +0100 Subject: [PATCH 148/202] Fix: 're.search' should accept 'mmap' object. --- graalpython/lib-graalpython/_sre.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/graalpython/lib-graalpython/_sre.py b/graalpython/lib-graalpython/_sre.py index 1a43e02219..aa19b7c538 100644 --- a/graalpython/lib-graalpython/_sre.py +++ b/graalpython/lib-graalpython/_sre.py @@ -39,6 +39,8 @@ import polyglot as _interop +from mmap import mmap + def default(value, default): return default if not value else value @@ -205,7 +207,7 @@ def _append_end_assert(pattern): return pattern if pattern.endswith(rb"\Z") else pattern + rb"\Z" def _is_bytes_like(object): - return isinstance(object, (bytes, bytearray, memoryview)) + return isinstance(object, (bytes, bytearray, memoryview, mmap)) class SRE_Pattern(): def __init__(self, pattern, flags): From a04afa82bc40bd97afdd9bab84640c617d009c0a Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 14:15:57 +0100 Subject: [PATCH 149/202] Add 'mmap.flush'. --- .../python/builtins/objects/mmap/MMapBuiltins.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index 7b132a0763..441f8f00b0 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -517,7 +517,7 @@ protected static SequenceStorageNodes.AppendNode createAppend() { } } - @Builtin(name = "seek", fixedNumOfPositionalArgs = 1) + @Builtin(name = "seek", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3) @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) abstract static class SeekNode extends PythonBuiltinNode { @@ -703,4 +703,15 @@ public static InternalLenNode create() { } } + @Builtin(name = "flush", fixedNumOfPositionalArgs = 1) + @GenerateNodeFactory + abstract static class FlushNode extends PythonUnaryBuiltinNode { + + @Specialization + Object seek(@SuppressWarnings("unused") PMMap self) { + return PNone.NONE; + } + + } + } From d53d7807a8f991f0291f10dde1c68e7ce3f32f19 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 16:19:57 +0100 Subject: [PATCH 150/202] Implement 'mmap.write'. --- .../builtins/objects/mmap/MMapBuiltins.java | 100 +++++++++++++----- 1 file changed, 73 insertions(+), 27 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index 441f8f00b0..34838671a9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -68,6 +68,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.bytes.BytesNodes; import com.oracle.graal.python.builtins.objects.bytes.PBytes; import com.oracle.graal.python.builtins.objects.bytes.PIBytesLike; import com.oracle.graal.python.builtins.objects.common.SequenceNodes; @@ -76,6 +77,7 @@ import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NormalizeIndexNode; import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum; import com.oracle.graal.python.builtins.objects.ints.PInt; +import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView; import com.oracle.graal.python.builtins.objects.mmap.MMapBuiltinsFactory.InternalLenNodeGen; import com.oracle.graal.python.builtins.objects.slice.PSlice; import com.oracle.graal.python.builtins.objects.slice.PSlice.SliceInfo; @@ -456,7 +458,7 @@ int readByte(PMMap self, @TypeSystemReference(PythonArithmeticTypes.class) abstract static class ReadNode extends PythonBuiltinNode { - @Specialization(guards = "!isNoValue(n)") + @Specialization(guards = "isNoValue(n)") PBytes read(PMMap self, @SuppressWarnings("unused") PNone n, @Cached("create()") ReadFromChannelNode readChannelNode) { ByteSequenceStorage res = readChannelNode.execute(self.getChannel(), ReadFromChannelNode.MAX_READ); @@ -517,10 +519,34 @@ protected static SequenceStorageNodes.AppendNode createAppend() { } } + @Builtin(name = "write", fixedNumOfPositionalArgs = 2) + @GenerateNodeFactory + abstract static class WriteNode extends PythonBinaryBuiltinNode { + + @Specialization + int writeBytesLike(PMMap self, PIBytesLike bytesLike, + @Cached("create()") WriteToChannelNode writeNode, + @Cached("create()") SequenceNodes.GetSequenceStorageNode getStorageNode) { + SeekableByteChannel channel = self.getChannel(); + return writeNode.execute(channel, getStorageNode.execute(bytesLike), Integer.MAX_VALUE); + } + + @Specialization + int writeMemoryview(PMMap self, PMemoryView memoryView, + @Cached("create()") WriteToChannelNode writeNode, + @Cached("create()") BytesNodes.ToBytesNode toBytesNode) { + byte[] data = toBytesNode.execute(memoryView); + return writeNode.execute(self.getChannel(), new ByteSequenceStorage(data), Integer.MAX_VALUE); + } + } + @Builtin(name = "seek", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3) @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) abstract static class SeekNode extends PythonBuiltinNode { + @Child private CastToIndexNode castToLongNode; + + private final BranchProfile errorProfile = BranchProfile.create(); @Specialization(guards = "isNoValue(how)") Object seek(VirtualFrame frame, PMMap self, long dist, @SuppressWarnings("unused") PNone how) { @@ -528,39 +554,59 @@ Object seek(VirtualFrame frame, PMMap self, long dist, @SuppressWarnings("unused } @Specialization - Object seek(VirtualFrame frame, PMMap self, long dist, int how) { + Object seek(VirtualFrame frame, PMMap self, long dist, Object how) { try { - return doSeek(self, dist, how); + SeekableByteChannel channel = self.getChannel(); + long size; + if (self.getLength() == 0) { + size = channel.size() - self.getOffset(); + } else { + size = self.getLength(); + } + long where; + int ihow = castToInt(how); + switch (ihow) { + case 0: /* relative to start */ + where = dist; + break; + case 1: /* relative to current position */ + where = position(channel) + dist; + break; + case 2: /* relative to end */ + where = size + dist; + break; + default: + errorProfile.enter(); + throw raise(PythonBuiltinClassType.ValueError, "unknown seek type"); + } + if (where > size || where < 0) { + errorProfile.enter(); + throw raise(PythonBuiltinClassType.ValueError, "seek out of range"); + } + doSeek(channel, where); + return PNone.NONE; } catch (IOException e) { + errorProfile.enter(); throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); } } - @TruffleBoundary - private Object doSeek(PMMap self, long dist, int how) throws IOException { - SeekableByteChannel channel = self.getChannel(); - long where; - switch (how) { - case 0: /* relative to start */ - where = dist; - break; - case 1: /* relative to current position */ - where = channel.position() + dist; - break; - case 2: /* relative to end */ - long size; - if (self.getLength() == 0) { - size = channel.size() - self.getOffset(); - } else { - size = self.getLength(); - } - where = size + dist; - break; - default: - throw raise(PythonBuiltinClassType.ValueError, "unknown seek type"); - } + @TruffleBoundary(allowInlining = true) + private static long position(SeekableByteChannel channel) throws IOException { + return channel.position(); + } + + @TruffleBoundary(allowInlining = true) + private static void doSeek(SeekableByteChannel channel, long where) throws IOException { channel.position(where); - return PNone.NONE; + } + + private int castToInt(Object val) { + if (castToLongNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + castToLongNode = insert(CastToIndexNode.create()); + } + return castToLongNode.execute(val); } } From 12b5176f494cb3e613f88b548818489756c00574 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 29 Jan 2019 16:59:44 +0100 Subject: [PATCH 151/202] Add 'test_mmap' and make a basic set of tests pass. --- .../src/tests/test_mmap.py | 184 ++++++++++++++++++ .../builtins/modules/MMapModuleBuiltins.java | 34 ++-- .../builtins/objects/mmap/MMapBuiltins.java | 17 +- .../graal/python/nodes/util/ChannelNodes.java | 2 +- 4 files changed, 220 insertions(+), 17 deletions(-) create mode 100644 graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py b/graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py new file mode 100644 index 0000000000..3ec3237d60 --- /dev/null +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py @@ -0,0 +1,184 @@ +from test.support import (TESTFN, run_unittest, import_module, unlink, + requires, _2G, _4G, gc_collect, cpython_only) +import unittest +import os +import re +import itertools +import socket +import sys +import weakref + +# Skip test if we can't import mmap. +mmap = import_module('mmap') + +PAGESIZE = mmap.PAGESIZE + +class MmapTests(unittest.TestCase): + + def setUp(self): + if os.path.exists(TESTFN): + os.unlink(TESTFN) + + def tearDown(self): + try: + os.unlink(TESTFN) + except OSError: + pass + + def test_basic(self): + # Test mmap module on Unix systems and Windows + + # Create a file to be mmap'ed. + f = open(TESTFN, 'bw+') + try: + # Write 2 pages worth of data to the file + f.write(b'\0'* PAGESIZE) + f.write(b'foo') + f.write(b'\0'* (PAGESIZE-3) ) + f.flush() + m = mmap.mmap(f.fileno(), 2 * PAGESIZE) + finally: + f.close() + + # Simple sanity checks + + tp = str(type(m)) # SF bug 128713: segfaulted on Linux + self.assertEqual(m.find(b'foo'), PAGESIZE) + + self.assertEqual(len(m), 2*PAGESIZE) + + self.assertEqual(m[0], 0) + self.assertEqual(m[0:3], b'\0\0\0') + + # Shouldn't crash on boundary (Issue #5292) + self.assertRaises(IndexError, m.__getitem__, len(m)) + self.assertRaises(IndexError, m.__setitem__, len(m), b'\0') + + # Modify the file's content + m[0] = b'3'[0] + m[PAGESIZE +3: PAGESIZE +3+3] = b'bar' + + # Check that the modification worked + self.assertEqual(m[0], b'3'[0]) + self.assertEqual(m[0:3], b'3\0\0') + self.assertEqual(m[PAGESIZE-1 : PAGESIZE + 7], b'\0foobar\0') + + m.flush() + + # Test doing a regular expression match in an mmap'ed file + match = re.search(b'[A-Za-z]+', m) + if match is None: + self.fail('regex match on mmap failed!') + else: + start, end = match.span(0) + length = end - start + + self.assertEqual(start, PAGESIZE) + self.assertEqual(end, PAGESIZE + 6) + + # test seeking around (try to overflow the seek implementation) + m.seek(0,0) + self.assertEqual(m.tell(), 0) + m.seek(42,1) + self.assertEqual(m.tell(), 42) + m.seek(0,2) + self.assertEqual(m.tell(), len(m)) + + # Try to seek to negative position... + self.assertRaises(ValueError, m.seek, -1) + + # Try to seek beyond end of mmap... + self.assertRaises(ValueError, m.seek, 1, 2) + + # Try to seek to negative position... + self.assertRaises(ValueError, m.seek, -len(m)-1, 2) + + # Try resizing map +# try: +# m.resize(512) +# except SystemError: +# # resize() not supported +# # No messages are printed, since the output of this test suite +# # would then be different across platforms. +# pass +# else: +# # resize() is supported +# self.assertEqual(len(m), 512) +# # Check that we can no longer seek beyond the new size. +# self.assertRaises(ValueError, m.seek, 513, 0) +# +# # Check that the underlying file is truncated too +# # (bug #728515) +# f = open(TESTFN, 'rb') +# try: +# f.seek(0, 2) +# self.assertEqual(f.tell(), 512) +# finally: +# f.close() +# self.assertEqual(m.size(), 512) + + m.close() + + + def test_bad_file_desc(self): + # Try opening a bad file descriptor... + self.assertRaises(OSError, mmap.mmap, -2, 4096) + + + def test_anonymous(self): + # anonymous mmap.mmap(-1, PAGE) + m = mmap.mmap(-1, PAGESIZE) + for x in range(PAGESIZE): + self.assertEqual(m[x], 0, + "anonymously mmap'ed contents should be zero") + + for x in range(PAGESIZE): + b = x & 0xff + m[x] = b + self.assertEqual(m[x], b) + + def test_read_all(self): + m = mmap.mmap(-1, 16) + + # With no parameters, or None or a negative argument, reads all + m.write(bytes(range(16))) + m.seek(0) + self.assertEqual(m.read(), bytes(range(16))) + m.seek(8) + self.assertEqual(m.read(), bytes(range(8, 16))) + m.seek(16) + self.assertEqual(m.read(), b'') + m.seek(3) + self.assertEqual(m.read(None), bytes(range(3, 16))) + m.seek(4) + self.assertEqual(m.read(-1), bytes(range(4, 16))) + m.seek(5) + self.assertEqual(m.read(-2), bytes(range(5, 16))) + m.seek(9) + self.assertEqual(m.read(-42), bytes(range(9, 16))) + m.close() + + + + def test_context_manager(self): + with mmap.mmap(-1, 10) as m: + self.assertFalse(m.closed) + self.assertTrue(m.closed) + + def test_context_manager_exception(self): + # Test that the OSError gets passed through + with self.assertRaises(Exception) as exc: + with mmap.mmap(-1, 10) as m: + raise OSError + self.assertIsInstance(exc.exception, OSError, + "wrong exception raised in context manager") + self.assertTrue(m.closed, "context manager failed") + + + +def test_main(): + #run_unittest(MmapTests, LargeMmapTests) + run_unittest(MmapTests) + +if __name__ == '__main__': + test_main() diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java index 16a56cff5d..1f9111cf56 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java @@ -44,9 +44,8 @@ import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError; import java.io.IOException; -import java.nio.channels.FileChannel.MapMode; import java.nio.ByteBuffer; -import java.nio.channels.ByteChannel; +import java.nio.channels.FileChannel.MapMode; import java.nio.channels.SeekableByteChannel; import java.nio.file.StandardOpenOption; import java.util.HashSet; @@ -67,7 +66,6 @@ import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.api.profiles.ValueProfile; @CoreFunctions(defineModule = "mmap") public class MMapModuleBuiltins extends PythonBuiltins { @@ -92,13 +90,13 @@ public MMapModuleBuiltins() { @GenerateNodeFactory public abstract static class MMapNode extends PythonBuiltinNode { - private final ValueProfile classProfile = ValueProfile.createClassProfile(); private final BranchProfile invalidLengthProfile = BranchProfile.create(); - @Specialization(guards = {"fd < 0", "isNoValue(access)", "isNoValue(offset)"}) - PMMap doAnonymous(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access, @SuppressWarnings("unused") PNone offset) { + @Specialization(guards = {"isAnonymous(fd)", "isNoValue(access)", "isNoValue(offset)"}) + PMMap doAnonymous(LazyPythonClass clazz, @SuppressWarnings("unused") int fd, int length, @SuppressWarnings("unused") Object tagname, @SuppressWarnings("unused") PNone access, + @SuppressWarnings("unused") PNone offset) { checkLength(length); - return new PMMap(clazz, new AnonymousMap(length), length, 0); + return factory().createMMap(clazz, new AnonymousMap(length), length, 0); } @Specialization(guards = {"fd >= 0", "isNoValue(access)", "isNoValue(offset)"}) @@ -108,14 +106,13 @@ PMMap doIt(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressW // mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset]) @Specialization(guards = "fd >= 0") - PMMap doFile(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, int access, long offset) { + PMMap doFile(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, @SuppressWarnings("unused") int access, long offset) { checkLength(length); String path = getContext().getResources().getFilePath(fd); TruffleFile truffleFile = getContext().getEnv().getTruffleFile(path); // TODO(fa) correctly honor access flags - MapMode mode = convertAccessToMapMode(access); Set options = new HashSet<>(); options.add(StandardOpenOption.READ); options.add(StandardOpenOption.WRITE); @@ -125,12 +122,27 @@ PMMap doFile(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unuse try { fileChannel = truffleFile.newByteChannel(options); fileChannel.position(offset); - return new PMMap(PythonBuiltinClassType.PMMap, fileChannel, length, offset); + return factory().createMMap(clazz, fileChannel, length, offset); } catch (IOException e) { throw raise(ValueError, "cannot mmap file"); } } + @Specialization(guards = "isIllegal(fd)") + @SuppressWarnings("unused") + PMMap doAnonymous(LazyPythonClass clazz, int fd, Object length, Object tagname, PNone access, PNone offset) { + throw raise(PythonBuiltinClassType.OSError); + } + + protected static boolean isAnonymous(int fd) { + return fd == -1; + } + + protected static boolean isIllegal(int fd) { + return fd < -1; + } + + @SuppressWarnings("unused") private MapMode convertAccessToMapMode(int access) { switch (access) { case 0: @@ -189,7 +201,7 @@ public long position() throws IOException { } public SeekableByteChannel position(long newPosition) throws IOException { - if (newPosition < 0 || newPosition >= data.length) { + if (newPosition < 0) { throw new IllegalArgumentException(); } cur = (int) newPosition; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index 34838671a9..1fa3df16d8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -246,7 +246,7 @@ int doSingle(VirtualFrame frame, PMMap self, Object idxObj, long oldPos = channel.position(); channel.position(idx); - int res = readByteNode.execute(channel); + int res = readByteNode.execute(channel) & 0xFF; // restore position channel.position(oldPos); @@ -458,9 +458,11 @@ int readByte(PMMap self, @TypeSystemReference(PythonArithmeticTypes.class) abstract static class ReadNode extends PythonBuiltinNode { - @Specialization(guards = "isNoValue(n)") - PBytes read(PMMap self, @SuppressWarnings("unused") PNone n, + @Specialization + PBytes readUnlimited(PMMap self, @SuppressWarnings("unused") PNone n, @Cached("create()") ReadFromChannelNode readChannelNode) { + // intentionally accept NO_VALUE and NONE; both mean that we read unlimited amount of + // bytes ByteSequenceStorage res = readChannelNode.execute(self.getChannel(), ReadFromChannelNode.MAX_READ); return factory().createBytes(res); } @@ -468,8 +470,13 @@ PBytes read(PMMap self, @SuppressWarnings("unused") PNone n, @Specialization(guards = "!isNoValue(n)") PBytes read(PMMap self, Object n, @Cached("create()") ReadFromChannelNode readChannelNode, - @Cached("create()") CastToIndexNode castToIndexNode) { - ByteSequenceStorage res = readChannelNode.execute(self.getChannel(), castToIndexNode.execute(n)); + @Cached("create()") CastToIndexNode castToIndexNode, + @Cached("createBinaryProfile()") ConditionProfile negativeProfile) { + int nread = castToIndexNode.execute(n); + if (negativeProfile.profile(nread < 0)) { + return readUnlimited(self, PNone.NO_VALUE, readChannelNode); + } + ByteSequenceStorage res = readChannelNode.execute(self.getChannel(), nread); return factory().createBytes(res); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java index 5615ce7c35..b4b1c58469 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java @@ -178,7 +178,7 @@ int readByte(ReadableByteChannel channel, if (readProfile.profile(read != 1)) { return handleError(channel); } - return get(buf); + return get(buf) & 0xFF; } private int handleError(Channel channel) { From 15b7c4214ec7a9851c31cb4a1f1e87d876987c32 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 10:04:05 +0100 Subject: [PATCH 152/202] Fix: use 'default' instead of 'static' in interface. --- .../graal/python/builtins/objects/mmap/MMapBuiltins.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index 1fa3df16d8..ce2d77d7e9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -115,7 +115,7 @@ public class MMapBuiltins extends PythonBuiltins { protected interface ByteReadingNode { - static ReadByteFromChannelNode createValueError() { + default ReadByteFromChannelNode createValueError() { return ReadByteFromChannelNode.create(() -> new ChannelNodes.ReadByteErrorHandler() { @Override @@ -125,7 +125,7 @@ public int execute(Channel channel) { }); } - static ReadByteFromChannelNode createIndexError() { + default ReadByteFromChannelNode createIndexError() { return ReadByteFromChannelNode.create(() -> new ChannelNodes.ReadByteErrorHandler() { @Override @@ -139,7 +139,7 @@ public int execute(Channel channel) { protected interface ByteWritingNode { - static WriteByteToChannelNode createValueError() { + default WriteByteToChannelNode createValueError() { return WriteByteToChannelNode.create(() -> new ChannelNodes.WriteByteErrorHandler() { @Override @@ -149,7 +149,7 @@ public void execute(Channel channel, byte b) { }); } - static WriteByteToChannelNode createIndexError() { + default WriteByteToChannelNode createIndexError() { return WriteByteToChannelNode.create(() -> new ChannelNodes.WriteByteErrorHandler() { @Override From ad9d3d373930d203fc2cf227908ea50a76043cf9 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 10:11:47 +0100 Subject: [PATCH 153/202] Fix copyrights. --- .../src/tests/test_mmap.py | 4 ++ .../builtins/modules/MMapModuleBuiltins.java | 2 +- .../graal/python/nodes/util/ChannelNodes.java | 40 +++++++++++++++++++ graalpython/lib-graalpython/mmap.py | 2 +- mx.graalpython/copyrights/overrides | 1 + 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py b/graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py index 3ec3237d60..bd84d3cede 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py @@ -1,3 +1,7 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# Copyright (C) 1996-2017 Python Software Foundation +# +# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 from test.support import (TESTFN, run_unittest, import_module, unlink, requires, _2G, _4G, gc_collect, cpython_only) import unittest diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java index 1f9111cf56..503e9aa20a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java index b4b1c58469..a2acb4463f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java @@ -1,3 +1,43 @@ +/* + * Copyright (c) 2019, 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 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ package com.oracle.graal.python.nodes.util; import static com.oracle.graal.python.builtins.PythonBuiltinClassType.OSError; diff --git a/graalpython/lib-graalpython/mmap.py b/graalpython/lib-graalpython/mmap.py index 2d33028688..c795f5b7bd 100644 --- a/graalpython/lib-graalpython/mmap.py +++ b/graalpython/lib-graalpython/mmap.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2019, 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 diff --git a/mx.graalpython/copyrights/overrides b/mx.graalpython/copyrights/overrides index 7c1949ba73..93ac6aadd6 100644 --- a/mx.graalpython/copyrights/overrides +++ b/mx.graalpython/copyrights/overrides @@ -239,6 +239,7 @@ graalpython/com.oracle.graal.python.test/src/tests/test_math.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_memoryview.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_mm2d_naive.py,zippy.copyright graalpython/com.oracle.graal.python.test/src/tests/test_mm2d_random_naive_5.py,zippy.copyright +graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_raise-try.py,zippy.copyright graalpython/com.oracle.graal.python.test/src/tests/test_random.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_re.py,python.copyright From 5295d9a7eb30c20475669dff1c527c23376d1707 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 10:17:06 +0100 Subject: [PATCH 154/202] Fix: recursive invocation of 'create'. --- .../com/oracle/graal/python/nodes/util/CastToByteNode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java index a3671b21d0..58418b23ae 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToByteNode.java @@ -154,10 +154,10 @@ public static CastToByteNode create(boolean coerce) { } public static CastToByteNode create(Function rangeErrorHandler, Function typeErrorHandler) { - return CastToByteNodeGen.create(rangeErrorHandler, typeErrorHandler); + return CastToByteNodeGen.create(rangeErrorHandler, typeErrorHandler, false); } public static CastToByteNode create(Function rangeErrorHandler, Function typeErrorHandler, boolean coerce) { return CastToByteNodeGen.create(rangeErrorHandler, typeErrorHandler, coerce); } -} \ No newline at end of file +} From e0c4558164c77952bbb80cb118effe63f3a4445c Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 30 Jan 2019 10:40:30 +0100 Subject: [PATCH 155/202] Fix style. --- .../graal/python/builtins/modules/PosixModuleBuiltins.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index 643acc2298..1bea44753e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -1020,8 +1020,8 @@ Object readOpaque(@SuppressWarnings("unused") VirtualFrame frame, int fd, long r @Cached("create()") ReadFromChannelNode readNode) { if (OpaqueBytes.isInOpaqueFilesystem(getResources().getFilePath(fd), getContext())) { Channel channel = getResources().getFileChannel(fd, channelClassProfile); - ByteSequenceStorage bytes = readNode.execute(channel, ReadFromChannelNode.MAX_READ); - return new OpaqueBytes(Arrays.copyOf(bytes.getInternalByteArray(), bytes.length())); + ByteSequenceStorage bytes = readNode.execute(channel, ReadFromChannelNode.MAX_READ); + return new OpaqueBytes(Arrays.copyOf(bytes.getInternalByteArray(), bytes.length())); } return read(frame, fd, requestedSize, channelClassProfile, readNode); } From 72ea768a141c587957e32e5c551a24a0eae485b6 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 6 Feb 2019 16:07:51 +0100 Subject: [PATCH 156/202] Add benchmark 'mmap-anonymous'. --- .../benchmarks/src/micro/mmap-anonymous.py | 65 +++++++++++++++++++ mx.graalpython/mx_graalpython_bench_param.py | 1 + 2 files changed, 66 insertions(+) create mode 100644 graalpython/benchmarks/src/micro/mmap-anonymous.py diff --git a/graalpython/benchmarks/src/micro/mmap-anonymous.py b/graalpython/benchmarks/src/micro/mmap-anonymous.py new file mode 100644 index 0000000000..464d5bcd7d --- /dev/null +++ b/graalpython/benchmarks/src/micro/mmap-anonymous.py @@ -0,0 +1,65 @@ +# Copyright (c) 2019, 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 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import mmap + +# create 64 MB anonymous mmap +size = 64*1024 +mm = mmap.mmap(-1, size) +data = b"Hello World" +ndata = len(data) +niter = size // ndata + + +def fill(): + # sequential access + mm.seek(0) + for i in range(niter): + mm.write(data) + + +def measure(num): + for i in range(num): + fill() + print(mm[0:ndata]) + + +def __benchmark__(num=100): + measure(num) + diff --git a/mx.graalpython/mx_graalpython_bench_param.py b/mx.graalpython/mx_graalpython_bench_param.py index e068a05020..4196a094e8 100644 --- a/mx.graalpython/mx_graalpython_bench_param.py +++ b/mx.graalpython/mx_graalpython_bench_param.py @@ -96,6 +96,7 @@ 'magic-iter': ITER_10 + ['50000000'], 'instantiation': ITER_10 + ['50000000'], 'call-classmethod': ITER_15 + ['50000000'], + 'mmap-anonymous': ITER_15 + ['1000'], } From 98f0ec9674b6abed6b46fcceda3d16b304c11b20 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 6 Feb 2019 17:09:04 +0100 Subject: [PATCH 157/202] Improve placing of TruffleBoundaries. --- .../builtins/modules/MMapModuleBuiltins.java | 20 ++++-- .../objects/common/SequenceStorageNodes.java | 2 - .../builtins/objects/mmap/MMapBuiltins.java | 66 ++++++++++--------- .../graal/python/nodes/util/ChannelNodes.java | 42 ++++++------ .../graal/python/runtime/PosixResources.java | 2 +- 5 files changed, 72 insertions(+), 60 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java index 503e9aa20a..709535e873 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java @@ -62,6 +62,7 @@ import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.truffle.api.TruffleFile; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; @@ -113,21 +114,28 @@ PMMap doFile(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unuse TruffleFile truffleFile = getContext().getEnv().getTruffleFile(path); // TODO(fa) correctly honor access flags - Set options = new HashSet<>(); - options.add(StandardOpenOption.READ); - options.add(StandardOpenOption.WRITE); + Set options = set(StandardOpenOption.READ, StandardOpenOption.WRITE); // we create a new channel otherwise we cannot guarantee that the cursor is exclusive SeekableByteChannel fileChannel; try { fileChannel = truffleFile.newByteChannel(options); - fileChannel.position(offset); + position(fileChannel, offset); return factory().createMMap(clazz, fileChannel, length, offset); } catch (IOException e) { throw raise(ValueError, "cannot mmap file"); } } + @TruffleBoundary + private static Set set(StandardOpenOption... options) { + Set s = new HashSet<>(); + for (StandardOpenOption o : options) { + s.add(o); + } + return s; + } + @Specialization(guards = "isIllegal(fd)") @SuppressWarnings("unused") PMMap doAnonymous(LazyPythonClass clazz, int fd, Object length, Object tagname, PNone access, PNone offset) { @@ -164,6 +172,10 @@ private void checkLength(int length) { } } + @TruffleBoundary + private static void position(SeekableByteChannel ch, long offset) throws IOException { + ch.position(offset); + } } private static class AnonymousMap implements SeekableByteChannel { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java index 680a796a9c..7c3c5ae6eb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java @@ -128,7 +128,6 @@ import com.oracle.graal.python.runtime.sequence.storage.TypedSequenceStorage; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.ImportStatic; @@ -1745,7 +1744,6 @@ byte[] doFallback(@SuppressWarnings("unused") SequenceStorage s) { throw raise(TypeError, "expected a bytes-like object"); } - @TruffleBoundary(transferToInterpreterOnException = false) private static byte[] exactCopy(byte[] barr, int len) { return Arrays.copyOf(barr, len); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index ce2d77d7e9..e965d71215 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -113,7 +113,19 @@ @CoreFunctions(extendClasses = PythonBuiltinClassType.PMMap) public class MMapBuiltins extends PythonBuiltins { - protected interface ByteReadingNode { + protected interface MMapBaseNode { + @TruffleBoundary + default long position(SeekableByteChannel ch) throws IOException { + return ch.position(); + } + + @TruffleBoundary + default void position(SeekableByteChannel ch, long offset) throws IOException { + ch.position(offset); + } + } + + protected interface ByteReadingNode extends MMapBaseNode { default ReadByteFromChannelNode createValueError() { return ReadByteFromChannelNode.create(() -> new ChannelNodes.ReadByteErrorHandler() { @@ -137,7 +149,7 @@ public int execute(Channel channel) { } } - protected interface ByteWritingNode { + protected interface ByteWritingNode extends MMapBaseNode { default WriteByteToChannelNode createValueError() { return WriteByteToChannelNode.create(() -> new ChannelNodes.WriteByteErrorHandler() { @@ -243,13 +255,13 @@ int doSingle(VirtualFrame frame, PMMap self, Object idxObj, long idx = i < 0 ? i + len : i; // save current position - long oldPos = channel.position(); + long oldPos = position(channel); - channel.position(idx); + position(channel, idx); int res = readByteNode.execute(channel) & 0xFF; // restore position - channel.position(oldPos); + position(channel, oldPos); return res; @@ -268,13 +280,13 @@ Object doSlice(VirtualFrame frame, PMMap self, PSlice idx, SeekableByteChannel channel = self.getChannel(); // save current position - long oldPos = channel.position(); + long oldPos = position(channel); - channel.position(info.start); + position(channel, info.start); ByteSequenceStorage s = readNode.execute(channel, info.length); // restore position - channel.position(oldPos); + position(channel, oldPos); return factory().createBytes(s); } catch (IOException e) { @@ -307,13 +319,13 @@ PNone doSingle(VirtualFrame frame, PMMap self, Object idxObj, Object val, } // save current position - long oldPos = channel.position(); + long oldPos = position(channel); - channel.position(idx); + position(channel, idx); writeByteNode.execute(channel, castToByteNode.execute(val)); // restore position - channel.position(oldPos); + position(channel, oldPos); return PNone.NONE; @@ -339,13 +351,13 @@ PNone doSlice(VirtualFrame frame, PMMap self, PSlice idx, PIBytesLike val, } // save current position - long oldPos = channel.position(); + long oldPos = position(channel); - channel.position(info.start); + position(channel, info.start); writeNode.execute(channel, getStorageNode.execute(val), info.length); // restore position - channel.position(oldPos); + position(channel, oldPos); return PNone.NONE; @@ -428,13 +440,13 @@ long size(VirtualFrame frame, PMMap self, @Builtin(name = "tell", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - abstract static class TellNode extends PythonBuiltinNode { + abstract static class TellNode extends PythonBuiltinNode implements ByteReadingNode { @Specialization long readline(VirtualFrame frame, PMMap self) { try { SeekableByteChannel channel = self.getChannel(); - return channel.position() - self.getOffset(); + return position(channel) - self.getOffset(); } catch (IOException e) { throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); } @@ -484,7 +496,7 @@ PBytes read(PMMap self, Object n, @Builtin(name = "readline", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - abstract static class ReadlineNode extends PythonBuiltinNode { + abstract static class ReadlineNode extends PythonUnaryBuiltinNode implements ByteReadingNode { @Specialization Object readline(PMMap self, @@ -504,7 +516,7 @@ Object readline(PMMap self, appendNode.execute(res, b); } else { // recover correct position (i.e. number of remaining bytes in buffer) - channel.position(channel.position() - buf.remaining() - 1); + position(channel, position(channel) - buf.remaining() - 1); break outer; } } @@ -550,7 +562,7 @@ int writeMemoryview(PMMap self, PMemoryView memoryView, @Builtin(name = "seek", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3) @GenerateNodeFactory @TypeSystemReference(PythonArithmeticTypes.class) - abstract static class SeekNode extends PythonBuiltinNode { + abstract static class SeekNode extends PythonBuiltinNode implements MMapBaseNode { @Child private CastToIndexNode castToLongNode; private final BranchProfile errorProfile = BranchProfile.create(); @@ -590,7 +602,7 @@ Object seek(VirtualFrame frame, PMMap self, long dist, Object how) { errorProfile.enter(); throw raise(PythonBuiltinClassType.ValueError, "seek out of range"); } - doSeek(channel, where); + position(channel, where); return PNone.NONE; } catch (IOException e) { errorProfile.enter(); @@ -598,16 +610,6 @@ Object seek(VirtualFrame frame, PMMap self, long dist, Object how) { } } - @TruffleBoundary(allowInlining = true) - private static long position(SeekableByteChannel channel) throws IOException { - return channel.position(); - } - - @TruffleBoundary(allowInlining = true) - private static void doSeek(SeekableByteChannel channel, long where) throws IOException { - channel.position(where); - } - private int castToInt(Object val) { if (castToLongNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -653,7 +655,7 @@ long find(PMMap primary, PIBytesLike sub, Object starting, Object ending, // TODO implement a more efficient algorithm outer: for (long i = start; i < end; i++) { // TODO(fa) don't seek but use circular buffer - channel.position(i); + position(channel, i); for (int j = 0; j < len2; j++) { int hb = readByteNode.execute(channel); int nb = getGetRightItemNode().executeInt(needle, j); @@ -682,7 +684,7 @@ long find(PMMap primary, int sub, Object starting, @SuppressWarnings("unused") O long start = s < 0 ? s + len1 : s; long end = Math.max(e < 0 ? e + len1 : e, len1); - channel.position(start); + position(channel, start); for (long i = start; i < end; i++) { int hb = readByteNode.execute(channel); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java index a2acb4463f..586f8e827a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/ChannelNodes.java @@ -78,64 +78,64 @@ public abstract static class WriteByteErrorHandler extends PNodeWithContext { public abstract void execute(Channel channel, byte b); } - abstract static class ReadFromChannelBaseNode extends PNodeWithContext { - - private final BranchProfile gotException = BranchProfile.create(); - + protected interface ChannelBaseNode { @TruffleBoundary(allowInlining = true) - protected static ByteBuffer allocate(int n) { + default ByteBuffer allocate(int n) { return ByteBuffer.allocate(n); } @TruffleBoundary(transferToInterpreterOnException = false) - protected static long availableSize(SeekableByteChannel channel) throws IOException { + default long availableSize(SeekableByteChannel channel) throws IOException { return channel.size() - channel.position(); } + } + + abstract static class ReadFromChannelBaseNode extends PNodeWithContext implements ChannelBaseNode { + + private final BranchProfile gotException = BranchProfile.create(); @TruffleBoundary(allowInlining = true) protected static byte[] getByteBufferArray(ByteBuffer dst) { return dst.array(); } - @TruffleBoundary(allowInlining = true) protected int readIntoBuffer(ReadableByteChannel readableChannel, ByteBuffer dst) { try { - return readableChannel.read(dst); + return read(readableChannel, dst); } catch (IOException e) { gotException.enter(); throw raise(OSError, e); } } + + @TruffleBoundary(allowInlining = true, transferToInterpreterOnException = false) + private static int read(ReadableByteChannel readableChannel, ByteBuffer dst) throws IOException { + return readableChannel.read(dst); + } } - abstract static class WriteToChannelBaseNode extends PNodeWithContext { + abstract static class WriteToChannelBaseNode extends PNodeWithContext implements ChannelBaseNode { private final BranchProfile gotException = BranchProfile.create(); - @TruffleBoundary(allowInlining = true) - protected static ByteBuffer allocate(int n) { - return ByteBuffer.allocate(n); - } - - @TruffleBoundary(transferToInterpreterOnException = false) - protected static long availableSize(SeekableByteChannel channel) throws IOException { - return channel.size() - channel.position(); - } - @TruffleBoundary(allowInlining = true) protected static byte[] getByteBufferArray(ByteBuffer dst) { return dst.array(); } - @TruffleBoundary(allowInlining = true) protected int writeFromBuffer(WritableByteChannel writableChannel, ByteBuffer src) { try { - return writableChannel.write(src); + return write(writableChannel, src); } catch (IOException e) { gotException.enter(); throw raise(OSError, e); } } + + @TruffleBoundary(allowInlining = true, transferToInterpreterOnException = false) + private static int write(WritableByteChannel writableChannel, ByteBuffer src) throws IOException { + return writableChannel.write(src); + } } public abstract static class ReadFromChannelNode extends ReadFromChannelBaseNode { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java index 42371deffb..907acf346e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java @@ -105,7 +105,7 @@ public Channel getFileChannel(int fd) { return null; } - @TruffleBoundary(allowInlining = true) + @TruffleBoundary public String getFilePath(int fd) { if (filePaths.size() > fd) { return filePaths.get(fd); From 4fe35eb846e213b7d8b9515dbbcb5ec8ceaf9ec6 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 6 Feb 2019 17:09:29 +0100 Subject: [PATCH 158/202] Add benchmark 'mmap-file'. --- graalpython/benchmarks/src/micro/mmap-file.py | 70 +++++++++++++++++++ mx.graalpython/mx_graalpython_bench_param.py | 1 + 2 files changed, 71 insertions(+) create mode 100644 graalpython/benchmarks/src/micro/mmap-file.py diff --git a/graalpython/benchmarks/src/micro/mmap-file.py b/graalpython/benchmarks/src/micro/mmap-file.py new file mode 100644 index 0000000000..fa04afaa40 --- /dev/null +++ b/graalpython/benchmarks/src/micro/mmap-file.py @@ -0,0 +1,70 @@ +# Copyright (c) 2019, 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 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import mmap +import tempfile + +# create temporary file +data = b"Hello World" +ndata = len(data) + + +def fill(mm, size): + # sequential access + mm.seek(0) + for i in range(size // ndata): + mm.write(data) + + +def measure(num): + tmp_path = tempfile.mkstemp() + with open(tmp_path[1], "wb") as f: + f.write(b'\x00' * (64 * 1024)) + + with open(tmp_path[1], "r+b") as f: + mm = mmap.mmap(f.fileno(), 0) + size = mm.size() + for i in range(num): + fill(mm, size) + print(mm[0:ndata]) + + +def __benchmark__(num=100): + measure(num) + diff --git a/mx.graalpython/mx_graalpython_bench_param.py b/mx.graalpython/mx_graalpython_bench_param.py index 4196a094e8..7c26ad96e0 100644 --- a/mx.graalpython/mx_graalpython_bench_param.py +++ b/mx.graalpython/mx_graalpython_bench_param.py @@ -97,6 +97,7 @@ 'instantiation': ITER_10 + ['50000000'], 'call-classmethod': ITER_15 + ['50000000'], 'mmap-anonymous': ITER_15 + ['1000'], + 'mmap-file': ITER_15 + ['1000'], } From bfea05daa5ccb04e02b86152a1c8ea9a5fce88a3 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 6 Feb 2019 17:13:50 +0100 Subject: [PATCH 159/202] Fix merge conflicts. --- .../python/builtins/objects/common/SequenceStorageNodes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java index 7c3c5ae6eb..338f7457f2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java @@ -128,6 +128,7 @@ import com.oracle.graal.python.runtime.sequence.storage.TypedSequenceStorage; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.ImportStatic; @@ -3013,7 +3014,6 @@ Object[] doFallback(@SuppressWarnings("unused") SequenceStorage s) { throw raise(TypeError, "unsupported sequence type"); } - @TruffleBoundary private static T[] exactCopy(T[] barr, int len) { return Arrays.copyOf(barr, len); } From 018acc7e9071a4e5be4d662bf37bf3959c0874e7 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 6 Feb 2019 17:32:09 +0100 Subject: [PATCH 160/202] Fix: use appropriate default value for seek mode. --- .../oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index e965d71215..3ee3a93fec 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -613,7 +613,7 @@ Object seek(VirtualFrame frame, PMMap self, long dist, Object how) { private int castToInt(Object val) { if (castToLongNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castToLongNode = insert(CastToIndexNode.create()); + castToLongNode = insert(CastToIndexNode.create(PythonBuiltinClassType.TypeError, (obj) -> 0)); } return castToLongNode.execute(val); } From 0ef8a06c2e2544d22560405141ab2b34e74cec79 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 7 Feb 2019 13:22:46 +0100 Subject: [PATCH 161/202] Fix: Add missing specialization for 'mmap' constructor. --- .../graal/python/builtins/modules/MMapModuleBuiltins.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java index 709535e873..deb76c2355 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java @@ -101,10 +101,15 @@ PMMap doAnonymous(LazyPythonClass clazz, @SuppressWarnings("unused") int fd, int } @Specialization(guards = {"fd >= 0", "isNoValue(access)", "isNoValue(offset)"}) - PMMap doIt(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access, @SuppressWarnings("unused") PNone offset) { + PMMap doFile(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access, @SuppressWarnings("unused") PNone offset) { return doFile(clazz, fd, length, tagname, ACCESS_DEFAULT, 0); } + @Specialization(guards = {"fd >= 0", "isNoValue(offset)"}) + PMMap doFile(LazyPythonClass clazz, int fd, int length, Object tagname, int access, @SuppressWarnings("unused") PNone offset) { + return doFile(clazz, fd, length, tagname, access, 0); + } + // mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset]) @Specialization(guards = "fd >= 0") PMMap doFile(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, @SuppressWarnings("unused") int access, long offset) { From 1a8b353f4e63746d174a4c5744d13c953125194a Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 7 Feb 2019 13:28:11 +0100 Subject: [PATCH 162/202] Add missing TruffleBoundary. --- .../builtins/objects/mmap/MMapBuiltins.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index 3ee3a93fec..5bdece4b8d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -123,6 +123,11 @@ default long position(SeekableByteChannel ch) throws IOException { default void position(SeekableByteChannel ch, long offset) throws IOException { ch.position(offset); } + + @TruffleBoundary + default long size(SeekableByteChannel ch) throws IOException { + return ch.size(); + } } protected interface ByteReadingNode extends MMapBaseNode { @@ -407,14 +412,19 @@ Object size(PMMap self, @SuppressWarnings("unused") Object typ, @SuppressWarning abstract static class CloseNode extends PythonUnaryBuiltinNode { @Specialization - PNone close(PMMap self) { + PNone doClose(PMMap self) { try { - self.getChannel().close(); + close(self); } catch (IOException e) { // TODO(fa): ignore ? } return PNone.NONE; } + + @TruffleBoundary + private static void close(PMMap self) throws IOException { + self.getChannel().close(); + } } @Builtin(name = "closed", fixedNumOfPositionalArgs = 1, isGetter = true) @@ -422,6 +432,7 @@ PNone close(PMMap self) { abstract static class ClosedNode extends PythonUnaryBuiltinNode { @Specialization + @TruffleBoundary boolean close(PMMap self) { return !self.getChannel().isOpen(); } @@ -578,7 +589,7 @@ Object seek(VirtualFrame frame, PMMap self, long dist, Object how) { SeekableByteChannel channel = self.getChannel(); long size; if (self.getLength() == 0) { - size = channel.size() - self.getOffset(); + size = size(channel) - self.getOffset(); } else { size = self.getLength(); } @@ -635,7 +646,7 @@ long find(PMMap primary, PIBytesLike sub, Object starting, Object ending, @Cached("createValueError()") ReadByteFromChannelNode readByteNode) { try { SeekableByteChannel channel = primary.getChannel(); - long len1 = channel.size(); + long len1 = size(channel); SequenceStorage needle = sub.getSequenceStorage(); int len2 = needle.length(); @@ -676,7 +687,7 @@ long find(PMMap primary, int sub, Object starting, @SuppressWarnings("unused") O @Cached("createValueError()") ReadByteFromChannelNode readByteNode) { try { SeekableByteChannel channel = primary.getChannel(); - long len1 = channel.size(); + long len1 = size(channel); long s = castToLong(starting, 0); long e = castToLong(ending, len1); @@ -721,7 +732,7 @@ private SequenceStorageNodes.GetItemNode getGetRightItemNode() { } } - abstract static class InternalLenNode extends PNodeWithContext { + abstract static class InternalLenNode extends PNodeWithContext implements MMapBaseNode { public abstract long execute(VirtualFrame frame, PMMap self); @@ -729,7 +740,7 @@ abstract static class InternalLenNode extends PNodeWithContext { long doFull(VirtualFrame frame, PMMap self, @Cached("create()") BranchProfile profile) { try { - return self.getChannel().size() - self.getOffset(); + return size(self.getChannel()) - self.getOffset(); } catch (IOException e) { profile.enter(); throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); @@ -745,7 +756,7 @@ long doWindow(@SuppressWarnings("unused") VirtualFrame frame, PMMap self) { long doGeneric(VirtualFrame frame, PMMap self) { if (self.getLength() == 0) { try { - return self.getChannel().size() - self.getOffset(); + return size(self.getChannel()) - self.getOffset(); } catch (IOException e) { throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); } From 21bcbba62c586c2ad9ab4fa10d35afe7a6a22264 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 7 Feb 2019 13:28:20 +0100 Subject: [PATCH 163/202] Fix copyrights. --- .../python/builtins/objects/cext/PySequenceArrayWrapperMR.java | 2 +- mx.graalpython/copyrights/overrides | 1 + mx.graalpython/mx_graalpython_bench_param.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java index df2a7e8c1a..a7c3eb9ea9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/mx.graalpython/copyrights/overrides b/mx.graalpython/copyrights/overrides index 93ac6aadd6..989cb03507 100644 --- a/mx.graalpython/copyrights/overrides +++ b/mx.graalpython/copyrights/overrides @@ -110,6 +110,7 @@ graalpython/com.oracle.graal.python.cext/modules/_bz2.c,python.copyright graalpython/com.oracle.graal.python.cext/modules/_cpython_sre.c,python.copyright graalpython/com.oracle.graal.python.cext/modules/_cpython_unicodedata.c,python.copyright graalpython/com.oracle.graal.python.cext/modules/_memoryview.c,python.copyright +graalpython/com.oracle.graal.python.cext/modules/_mmap.c,python.copyright graalpython/com.oracle.graal.python.cext/modules/_struct.c,python.copyright graalpython/com.oracle.graal.python.cext/modules/sre_constants.h,python.copyright graalpython/com.oracle.graal.python.cext/modules/sre.h,python.copyright diff --git a/mx.graalpython/mx_graalpython_bench_param.py b/mx.graalpython/mx_graalpython_bench_param.py index 7c26ad96e0..6931acfd34 100644 --- a/mx.graalpython/mx_graalpython_bench_param.py +++ b/mx.graalpython/mx_graalpython_bench_param.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. +# Copyright (c) 2017, 2019, Oracle and/or its affiliates. # Copyright (c) 2013, Regents of the University of California # # All rights reserved. From 74bceee5ae1e763ddc85b9aa6b527c3d966fe8bc Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 7 Feb 2019 17:27:58 +0100 Subject: [PATCH 164/202] Support native buffer protocol for 'mmap'. --- .../modules/_mmap.c | 92 +++++++ .../builtins/modules/ImpModuleBuiltins.java | 2 + .../objects/cext/NativeMemberNames.java | 1 + .../cext/PySequenceArrayWrapperMR.java | 52 +++- .../cext/PythonObjectNativeWrapperMR.java | 258 +++++++++++------- .../builtins/objects/mmap/MMapBuiltins.java | 11 +- .../oracle/graal/python/nodes/PGuards.java | 5 + graalpython/lib-graalpython/mmap.py | 8 + graalpython/lib-graalpython/python_cext.py | 21 +- 9 files changed, 331 insertions(+), 119 deletions(-) create mode 100644 graalpython/com.oracle.graal.python.cext/modules/_mmap.c diff --git a/graalpython/com.oracle.graal.python.cext/modules/_mmap.c b/graalpython/com.oracle.graal.python.cext/modules/_mmap.c new file mode 100644 index 0000000000..f3dc9b7d02 --- /dev/null +++ b/graalpython/com.oracle.graal.python.cext/modules/_mmap.c @@ -0,0 +1,92 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. + * Copyright (C) 1996-2017 Python Software Foundation + * + * Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 + */ + +#include "../src/capi.h" + +typedef enum +{ + ACCESS_DEFAULT, + ACCESS_READ, + ACCESS_WRITE, + ACCESS_COPY +} access_mode; + +typedef struct { + PyObject_HEAD + char * data; + Py_ssize_t size; + Py_ssize_t pos; /* relative to offset */ +#ifdef MS_WINDOWS + long long offset; +#else + off_t offset; +#endif + int exports; + +#ifdef MS_WINDOWS + HANDLE map_handle; + HANDLE file_handle; + char * tagname; +#endif + +#ifdef UNIX + int fd; +#endif + + PyObject *weakreflist; + access_mode access; +} mmap_object; + + +POLYGLOT_DECLARE_TYPE(mmap_object); +static PyTypeObject mmap_object_type = PY_TRUFFLE_TYPE("mmap.mmap", NULL, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, sizeof(mmap_object)); + +int mmap_getbuffer(PyObject *self, Py_buffer *view, int flags) { + // TODO(fa) readonly flag + return PyBuffer_FillInfo(view, (PyObject*)self, ((mmap_object *)self)->data, PyObject_Size((PyObject *)self), 0, flags); +} + +static PyObject* mmap_init_bufferprotocol(PyObject* self, PyObject* mmap_type) { + assert(PyType_Check(mmap_type)); + initialize_type_structure(&mmap_object_type, mmap_type, polyglot_mmap_object_typeid()); + + polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_SetBufferProcs", native_to_java(mmap_type), (getbufferproc) mmap_getbuffer, (releasebufferproc) NULL); + return Py_None; +} + +static struct PyMethodDef module_functions[] = { + {"init_bufferprotocol", mmap_init_bufferprotocol, METH_O, NULL}, + {NULL, NULL} /* sentinel */ +}; + +static struct PyModuleDef mmapmodule = { + PyModuleDef_HEAD_INIT, + "_mmap", + NULL, + -1, + module_functions, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit__mmap(void) +{ + PyObject *dict, *module; + + module = PyModule_Create(&mmapmodule); + if (module == NULL) { + return NULL; + } + dict = PyModule_GetDict(module); + if (!dict) { + return NULL; + } + + return module; +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java index 181ef06674..42dd25e977 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java @@ -145,6 +145,7 @@ public boolean run() { public abstract static class CreateDynamic extends PythonBuiltinNode { protected static final String INITIALIZE_CAPI = "initialize_capi"; protected static final String IMPORT_NATIVE_MEMORYVIEW = "import_native_memoryview"; + protected static final String RUN_CAPI_LOADED_HOOKS = "run_capi_loaded_hooks"; private static final String LLVM_LANGUAGE = "llvm"; @Child private SetItemNode setItemNode; @Child private CheckFunctionResultNode checkResultNode; @@ -246,6 +247,7 @@ private void ensureCapiWasLoaded() { CallUnaryMethodNode callNode = insert(CallUnaryMethodNode.create()); callNode.executeObject(readNode.execute(ctxt.getCore().lookupBuiltinModule("python_cext"), INITIALIZE_CAPI), capi); ctxt.setCapiWasLoaded(capi); + callNode.executeObject(readNode.execute(ctxt.getCore().lookupBuiltinModule("python_cext"), RUN_CAPI_LOADED_HOOKS), capi); // initialization needs to be finished already but load memoryview implemenation // immediately diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java index b821e55dd9..3822aedd78 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeMemberNames.java @@ -127,6 +127,7 @@ public final class NativeMemberNames { public static final String M_ML = "m_ml"; public static final String DATETIME_DATA = "data"; public static final String SET_USED = "used"; + public static final String MMAP_DATA = "data"; @CompilationFinal(dimensions = 1) public static final String[] values; static { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java index a7c3eb9ea9..9d7f4d50b6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java @@ -60,9 +60,14 @@ import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.ListGeneralizationNode; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NormalizeIndexNode; import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.StorageToNativeNode; +import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.builtins.objects.list.ListBuiltins; import com.oracle.graal.python.builtins.objects.list.ListBuiltinsFactory; import com.oracle.graal.python.builtins.objects.list.PList; +import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView; +import com.oracle.graal.python.builtins.objects.mmap.MMapBuiltins; +import com.oracle.graal.python.builtins.objects.mmap.PMMap; +import com.oracle.graal.python.builtins.objects.slice.PSlice; import com.oracle.graal.python.builtins.objects.tuple.PTuple; import com.oracle.graal.python.builtins.objects.tuple.TupleBuiltins; import com.oracle.graal.python.builtins.objects.tuple.TupleBuiltinsFactory; @@ -82,6 +87,7 @@ import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.MessageResolution; @@ -111,8 +117,8 @@ public Object access(PySequenceArrayWrapper object) { abstract static class ReadNode extends Node { @Child private ReadArrayItemNode readArrayItemNode; - public Object access(PySequenceArrayWrapper object, Object key) { - return getReadArrayItemNode().execute(object.getDelegate(), key); + public Object access(VirtualFrame frame, PySequenceArrayWrapper object, Object key) { + return getReadArrayItemNode().execute(frame, object.getDelegate(), key); } private ReadArrayItemNode getReadArrayItemNode() { @@ -144,20 +150,20 @@ public Object access(PySequenceArrayWrapper object, Object key, Object value) { @ImportStatic(SpecialMethodNames.class) @TypeSystemReference(PythonTypes.class) - abstract static class ReadArrayItemNode extends Node { + abstract static class ReadArrayItemNode extends PNodeWithContext { @Child private ToSulongNode toSulongNode; - public abstract Object execute(Object arrayObject, Object idx); + public abstract Object execute(VirtualFrame frame, Object arrayObject, Object idx); @Specialization - Object doTuple(PTuple tuple, long idx, + Object doTuple(@SuppressWarnings("unused") VirtualFrame frame, PTuple tuple, long idx, @Cached("createTupleGetItem()") TupleBuiltins.GetItemNode getItemNode) { return getToSulongNode().execute(getItemNode.execute(tuple, idx)); } @Specialization - Object doTuple(PList list, long idx, + Object doTuple(@SuppressWarnings("unused") VirtualFrame frame, PList list, long idx, @Cached("createListGetItem()") ListBuiltins.GetItemNode getItemNode) { return getToSulongNode().execute(getItemNode.execute(list, idx)); } @@ -168,7 +174,7 @@ Object doTuple(PList list, long idx, * {@code uint64_t} since we do not know how many bytes are requested. */ @Specialization - long doBytesI64(PIBytesLike bytesLike, long byteIdx, + long doBytesI64(@SuppressWarnings("unused") VirtualFrame frame, PIBytesLike bytesLike, long byteIdx, @Cached("createClassProfile()") ValueProfile profile, @Cached("create()") SequenceStorageNodes.LenNode lenNode, @Cached("create()") SequenceStorageNodes.GetItemNode getItemNode) { @@ -179,9 +185,13 @@ long doBytesI64(PIBytesLike bytesLike, long byteIdx, return 0L; } int i = (int) byteIdx; - long result = 0; SequenceStorage store = profiled.getSequenceStorage(); - result |= getItemNode.executeInt(store, i); + return packLong(store, getItemNode, len, i); + } + + private static long packLong(SequenceStorage store, SequenceStorageNodes.GetItemNode getItemNode, int len, int i) { + long result = 0; + result |= getItemNode.executeInt(store, i) & 0xFFL; if (i + 1 < len) result |= ((long) getItemNode.executeInt(store, i + 1) << 8L) & 0xFF00L; if (i + 2 < len) @@ -199,8 +209,28 @@ long doBytesI64(PIBytesLike bytesLike, long byteIdx, return result; } + @Specialization + long doMMap(VirtualFrame frame, PMMap list, long idx, + @Cached("create()") MMapBuiltins.GetItemNode getItemNode, + @Cached("create()") SequenceNodes.GetSequenceStorageNode getStorageNode, + @Cached("create()") SequenceStorageNodes.LenNode lenNode, + @Cached("create()") SequenceStorageNodes.GetItemNode getStoreItemNode) { + try { + int i = PInt.intValueExact(idx); + PSlice sl = factory().createSlice(i, i + 8, 1); + Object bytes = getItemNode.executeObject(frame, list, sl); + SequenceStorage storage = getStorageNode.execute(bytes); + int storageLen = lenNode.execute(storage); + return packLong(storage, getStoreItemNode, storageLen, 0); + } catch (ArithmeticException e) { + // TODO raise native exception + CompilerDirectives.transferToInterpreter(); + throw new IllegalArgumentException(); + } + } + @Specialization(guards = {"!isTuple(object)", "!isList(object)"}) - Object doGeneric(Object object, long idx, + Object doGeneric(@SuppressWarnings("unused") VirtualFrame frame, Object object, long idx, @Cached("create(__GETITEM__)") LookupAndCallBinaryNode getItemNode) { return getToSulongNode().execute(getItemNode.executeObject(object, idx)); } @@ -515,7 +545,7 @@ Object doPtrArrayMultiCtx(@SuppressWarnings("unused") PSequence object) { } protected static boolean hasByteArrayContent(Object object) { - return object instanceof PBytes || object instanceof PByteArray; + return object instanceof PBytes || object instanceof PByteArray || object instanceof PMemoryView || object instanceof PMMap; } public static GetTypeIDNode create() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java index b3c1cd348d..3c4a9b6b4f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java @@ -68,7 +68,9 @@ import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapperMRFactory.InvalidateNativeObjectsAllManagedNodeGen; import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapperMRFactory.PAsPointerNodeGen; import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapperMRFactory.PGetDynamicTypeNodeGen; -import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapperMRFactory.ReadNativeMemberNodeGen; +import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapperMRFactory.ReadNativeMemberDispatchNodeGen; +import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapperMRFactory.ReadObjectNativeMemberNodeGen; +import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapperMRFactory.ReadTypeNativeMemberNodeGen; import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapperMRFactory.ToPyObjectNodeGen; import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapperMRFactory.WriteNativeMemberNodeGen; import com.oracle.graal.python.builtins.objects.cext.UnicodeObjectNodes.UnicodeAsWideCharNode; @@ -89,15 +91,16 @@ import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView; import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod; import com.oracle.graal.python.builtins.objects.method.PMethod; +import com.oracle.graal.python.builtins.objects.mmap.PMMap; import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.set.PSet; import com.oracle.graal.python.builtins.objects.slice.PSlice; import com.oracle.graal.python.builtins.objects.str.PString; -import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; -import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; +import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; import com.oracle.graal.python.builtins.objects.type.PythonClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.TypeBuiltins; import com.oracle.graal.python.builtins.objects.type.TypeNodes; import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode; @@ -121,9 +124,9 @@ import com.oracle.graal.python.nodes.object.GetLazyClassNode; import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes; +import com.oracle.graal.python.nodes.truffle.PythonTypes; import com.oracle.graal.python.nodes.util.CastToIndexNode; import com.oracle.graal.python.nodes.util.CastToIntegerFromIntNode; -import com.oracle.graal.python.runtime.PythonCore; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.interop.PythonMessageResolution; import com.oracle.graal.python.runtime.sequence.PSequence; @@ -298,7 +301,7 @@ public static GetSulongTypeNode create() { @Resolve(message = "READ") abstract static class ReadNode extends Node { - @Child private ReadNativeMemberNode readNativeMemberNode; + @Child private ReadNativeMemberDispatchNode readNativeMemberNode; @Child private AsPythonObjectNode getDelegate; @CompilationFinal private String cachedObBase; @@ -327,12 +330,43 @@ public Object access(PythonNativeWrapper object, String key) { } if (readNativeMemberNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - readNativeMemberNode = insert(ReadNativeMemberNode.create()); + readNativeMemberNode = insert(ReadNativeMemberDispatchNode.create()); } return readNativeMemberNode.execute(delegate, key); } } + @ImportStatic(PGuards.class) + @TypeSystemReference(PythonTypes.class) + abstract static class ReadNativeMemberDispatchNode extends Node { + @Child private ReadTypeNativeMemberNode readTypeMemberNode; + @Child private ReadObjectNativeMemberNode readObjectMemberNode; + + abstract Object execute(Object receiver, String key); + + @Specialization + Object doClass(PythonManagedClass clazz, String key) { + if (readTypeMemberNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + readTypeMemberNode = insert(ReadTypeNativeMemberNode.create()); + } + return readTypeMemberNode.execute(clazz, key); + } + + @Specialization(guards = "!isManagedClass(clazz)") + Object doObject(Object clazz, String key) { + if (readObjectMemberNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + readObjectMemberNode = insert(ReadObjectNativeMemberNode.create()); + } + return readObjectMemberNode.execute(clazz, key); + } + + public static ReadNativeMemberDispatchNode create() { + return ReadNativeMemberDispatchNodeGen.create(); + } + } + @ImportStatic({NativeMemberNames.class, SpecialMethodNames.class, SpecialAttributeNames.class}) @TypeSystemReference(PythonArithmeticTypes.class) abstract static class ReadNativeMemberNode extends PNodeWithContext { @@ -349,16 +383,6 @@ Object doObBase(Object o, @SuppressWarnings("unused") String key) { return getToSulongNode().execute(o); } - @Specialization(guards = "eq(D_COMMON, key)") - Object doDCommon(Object o, @SuppressWarnings("unused") String key) { - return getToSulongNode().execute(o); - } - - @Specialization(guards = "eq(_BASE, key)") - Object doObBase(PString o, @SuppressWarnings("unused") String key) { - return getToSulongNode().execute(o); - } - @Specialization(guards = "eq(OB_REFCNT, key)") int doObRefcnt(@SuppressWarnings("unused") Object o, @SuppressWarnings("unused") String key) { return 0; @@ -369,47 +393,59 @@ Object doObType(Object object, @SuppressWarnings("unused") String key) { return getToSulongNode().execute(getClass(object)); } - @Specialization(guards = "eq(OB_SIZE, key)") - long doObSize(Object object, @SuppressWarnings("unused") String key, - @Cached("create(__LEN__)") LookupAndCallUnaryNode callLenNode) { - try { - return callLenNode.executeInt(object); - } catch (UnexpectedResultException e) { - return -1; + protected HashingStorageNodes.GetItemNode getGetItemNode() { + if (getItemNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getItemNode = insert(GetItemNode.create()); } + return getItemNode; } - @Specialization(guards = "eq(MA_USED, key)") - int doMaUsed(PDict object, @SuppressWarnings("unused") String key, - @Cached("create(__LEN__)") LookupAndCallUnaryNode callLenNode) { - try { - return callLenNode.executeInt(object); - } catch (UnexpectedResultException e) { - return -1; + protected ToSulongNode getToSulongNode() { + if (toSulongNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + toSulongNode = insert(ToSulongNode.create()); } + return toSulongNode; } - @Specialization(guards = "eq(OB_SVAL, key)") - Object doObSval(PBytes object, @SuppressWarnings("unused") String key) { - return new PySequenceArrayWrapper(object, 1); + protected int sizeofWchar() { + if (sizeofWcharNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + sizeofWcharNode = insert(CExtNodes.SizeofWCharNode.create()); + } + return (int) sizeofWcharNode.execute(); } - @Specialization(guards = "eq(OB_START, key)") - Object doObStart(PByteArray object, @SuppressWarnings("unused") String key) { - return new PySequenceArrayWrapper(object, 1); + protected PythonAbstractClass getClass(Object obj) { + if (getClassNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getClassNode = insert(GetClassNode.create()); + } + return getClassNode.execute(obj); } - @Specialization(guards = "eq(OB_FVAL, key)") - Object doObFval(Object object, @SuppressWarnings("unused") String key, - @Cached("createClassProfile()") ValueProfile profile) { - Object profiled = profile.profile(object); - if (profiled instanceof PFloat) { - return ((PFloat) profiled).getValue(); - } else if (profiled instanceof Double) { - return object; + protected String getClassName(Object obj) { + if (getNameNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getNameNode = insert(TypeNodes.GetNameNode.create()); } - throw UnsupportedMessageException.raise(Message.READ); + return getNameNode.execute(getClass(obj)); + } + + protected boolean eq(String expected, String actual) { + return expected.equals(actual); + } + + protected static Object getSliceComponent(int sliceComponent) { + if (sliceComponent == PSlice.MISSING_INDEX) { + return PNone.NONE; + } + return sliceComponent; } + } + + abstract static class ReadTypeNativeMemberNode extends ReadNativeMemberNode { @Specialization(guards = "eq(TP_FLAGS, key)") long doTpFlags(PythonManagedClass object, @SuppressWarnings("unused") String key, @@ -455,30 +491,29 @@ Object doTpAsBuffer(PythonManagedClass object, @SuppressWarnings("unused") Strin @Cached("create()") BranchProfile notMemoryview, @Cached("create()") BranchProfile notBuffer, @Cached("create()") BranchProfile notMmap) { - PythonCore core = getCore(); - PythonBuiltinClass pBytes = core.lookupType(PythonBuiltinClassType.PBytes); + PythonBuiltinClass pBytes = getBuiltinPythonClass(PythonBuiltinClassType.PBytes); if (isSubtype.execute(object, pBytes)) { return new PyBufferProcsWrapper(pBytes); } notBytes.enter(); - PythonBuiltinClass pBytearray = core.lookupType(PythonBuiltinClassType.PByteArray); + PythonBuiltinClass pBytearray = getBuiltinPythonClass(PythonBuiltinClassType.PByteArray); if (isSubtype.execute(object, pBytearray)) { return new PyBufferProcsWrapper(pBytearray); } notBytearray.enter(); - PythonBuiltinClass pMemoryview = core.lookupType(PythonBuiltinClassType.PMemoryView); + PythonBuiltinClass pMemoryview = getBuiltinPythonClass(PythonBuiltinClassType.PMemoryView); if (isSubtype.execute(object, pMemoryview)) { return new PyBufferProcsWrapper(pMemoryview); } notMemoryview.enter(); - PythonBuiltinClass pBuffer = core.lookupType(PythonBuiltinClassType.PBuffer); + PythonBuiltinClass pBuffer = getBuiltinPythonClass(PythonBuiltinClassType.PBuffer); if (isSubtype.execute(object, pBuffer)) { return new PyBufferProcsWrapper(pBuffer); } notBuffer.enter(); - PythonBuiltinClass pMmap = core.lookupType(PythonBuiltinClassType.PMMap); + PythonBuiltinClass pMmap = getBuiltinPythonClass(PythonBuiltinClassType.PMMap); if (isSubtype.execute(object, pMmap)) { - return new PyBufferProcsWrapper(pMemoryview); + return new PyBufferProcsWrapper(pMmap); } notMmap.enter(); // NULL pointer @@ -595,6 +630,65 @@ Object doTpIternext(PythonManagedClass object, @SuppressWarnings("unused") Strin return getToSulongNode().execute(lookupAttrNode.execute(object)); } + public static ReadTypeNativeMemberNode create() { + return ReadTypeNativeMemberNodeGen.create(); + } + } + + abstract static class ReadObjectNativeMemberNode extends ReadNativeMemberNode { + + @Specialization(guards = "eq(D_COMMON, key)") + Object doDCommon(Object o, @SuppressWarnings("unused") String key) { + return getToSulongNode().execute(o); + } + + @Specialization(guards = "eq(_BASE, key)") + Object doObBase(PString o, @SuppressWarnings("unused") String key) { + return getToSulongNode().execute(o); + } + + @Specialization(guards = "eq(OB_SIZE, key)") + long doObSize(Object object, @SuppressWarnings("unused") String key, + @Cached("create(__LEN__)") LookupAndCallUnaryNode callLenNode) { + try { + return callLenNode.executeInt(object); + } catch (UnexpectedResultException e) { + return -1; + } + } + + @Specialization(guards = "eq(MA_USED, key)") + int doMaUsed(PDict object, @SuppressWarnings("unused") String key, + @Cached("create(__LEN__)") LookupAndCallUnaryNode callLenNode) { + try { + return callLenNode.executeInt(object); + } catch (UnexpectedResultException e) { + return -1; + } + } + + @Specialization(guards = "eq(OB_SVAL, key)") + Object doObSval(PBytes object, @SuppressWarnings("unused") String key) { + return new PySequenceArrayWrapper(object, 1); + } + + @Specialization(guards = "eq(OB_START, key)") + Object doObStart(PByteArray object, @SuppressWarnings("unused") String key) { + return new PySequenceArrayWrapper(object, 1); + } + + @Specialization(guards = "eq(OB_FVAL, key)") + Object doObFval(Object object, @SuppressWarnings("unused") String key, + @Cached("createClassProfile()") ValueProfile profile) { + Object profiled = profile.profile(object); + if (profiled instanceof PFloat) { + return ((PFloat) profiled).getValue(); + } else if (profiled instanceof Double) { + return object; + } + throw UnsupportedMessageException.raise(Message.READ); + } + @Specialization(guards = "eq(OB_ITEM, key)") Object doObItem(PSequence object, @SuppressWarnings("unused") String key) { return new PySequenceArrayWrapper(object, 4); @@ -775,6 +869,11 @@ Object doMemoryview(PMemoryView object, String key, throw new IllegalStateException("delegate of memoryview object is not native"); } + @Specialization(guards = "eq(MMAP_DATA, key)") + Object doMmapData(PMMap object, @SuppressWarnings("unused") String key) { + return new PySequenceArrayWrapper(object, 1); + } + protected boolean isPyDateTimeCAPI(PythonObject object) { return getClassName(object).equals("PyDateTime_CAPI"); } @@ -814,59 +913,8 @@ private static void logGeneric(String key) { PythonLanguage.getLogger().log(Level.FINE, "read of Python struct native member " + key); } - protected boolean eq(String expected, String actual) { - return expected.equals(actual); - } - - public static ReadNativeMemberNode create() { - return ReadNativeMemberNodeGen.create(); - } - - private HashingStorageNodes.GetItemNode getGetItemNode() { - if (getItemNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - getItemNode = insert(GetItemNode.create()); - } - return getItemNode; - } - - private ToSulongNode getToSulongNode() { - if (toSulongNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - toSulongNode = insert(ToSulongNode.create()); - } - return toSulongNode; - } - - private int sizeofWchar() { - if (sizeofWcharNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - sizeofWcharNode = insert(CExtNodes.SizeofWCharNode.create()); - } - return (int) sizeofWcharNode.execute(); - } - - private PythonAbstractClass getClass(Object obj) { - if (getClassNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - getClassNode = insert(GetClassNode.create()); - } - return getClassNode.execute(obj); - } - - private String getClassName(Object obj) { - if (getNameNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - getNameNode = insert(TypeNodes.GetNameNode.create()); - } - return getNameNode.execute(getClass(obj)); - } - - private static Object getSliceComponent(int sliceComponent) { - if (sliceComponent == PSlice.MISSING_INDEX) { - return PNone.NONE; - } - return sliceComponent; + public static ReadObjectNativeMemberNode create() { + return ReadObjectNativeMemberNodeGen.create(); } protected Node createReadNode() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index 5bdece4b8d..c47bdae658 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -245,7 +245,13 @@ abstract static class ReprNode extends StrNode { @Builtin(name = __GETITEM__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - abstract static class GetItemNode extends PythonBuiltinNode implements ByteReadingNode { + public abstract static class GetItemNode extends PythonBuiltinNode implements ByteReadingNode { + + public abstract Object executeObject(VirtualFrame frame, PMMap self, Object idxObj); + + public abstract int executeInt(VirtualFrame frame, PMMap self, Object idxObj); + + public abstract long executeLong(VirtualFrame frame, PMMap self, Object idxObj); @Specialization(guards = "!isPSlice(idxObj)") int doSingle(VirtualFrame frame, PMMap self, Object idxObj, @@ -299,6 +305,9 @@ Object doSlice(VirtualFrame frame, PMMap self, PSlice idx, } } + public static GetItemNode create() { + return MMapBuiltinsFactory.GetItemNodeFactory.create(null); + } } @Builtin(name = SpecialMethodNames.__SETITEM__, fixedNumOfPositionalArgs = 3) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java index 1627082475..a8a4714b93 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java @@ -68,6 +68,7 @@ import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; +import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.runtime.sequence.PSequence; import com.oracle.graal.python.runtime.sequence.storage.BasicSequenceStorage; import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage; @@ -259,6 +260,10 @@ public static boolean isNativeObject(Object object) { return PythonNativeObject.isInstance(object); } + public static boolean isManagedClass(Object klass) { + return klass instanceof PythonManagedClass; + } + public static boolean isNativeClass(Object klass) { return PythonNativeClass.isInstance(klass); } diff --git a/graalpython/lib-graalpython/mmap.py b/graalpython/lib-graalpython/mmap.py index c795f5b7bd..8d8242ecbb 100644 --- a/graalpython/lib-graalpython/mmap.py +++ b/graalpython/lib-graalpython/mmap.py @@ -50,3 +50,11 @@ PROT_EXEC=0x4 PAGESIZE = 4096 + +from python_cext import register_capi_hook + +def __register_buffer(): + import _mmap + _mmap.init_bufferprotocol(mmap) + +register_capi_hook(__register_buffer) diff --git a/graalpython/lib-graalpython/python_cext.py b/graalpython/lib-graalpython/python_cext.py index 842cb8f331..8808820314 100644 --- a/graalpython/lib-graalpython/python_cext.py +++ b/graalpython/lib-graalpython/python_cext.py @@ -39,9 +39,19 @@ import _imp import sys -import python_cext _thread = None +capi = capi_to_java = None +_capi_hooks = [] + + +def register_capi_hook(hook): + assert callable(hook) + if capi: + hook() + else: + _capi_hooks.append(hook) + def may_raise(error_result=native_null): if isinstance(error_result, type(may_raise)): @@ -1190,7 +1200,6 @@ def import_c_func(name): return CreateFunction(name, capi[name]) -capi = capi_to_java = None def initialize_capi(capi_library): """This method is called from a C API constructor function""" global capi @@ -1200,6 +1209,14 @@ def initialize_capi(capi_library): initialize_member_accessors() initialize_datetime_capi() + + +# run C API initialize hooks +def run_capi_loaded_hooks(capi_library): + local_hooks = _capi_hooks.copy() + _capi_hooks.clear() + for hook in local_hooks: + hook() def import_native_memoryview(capi_library): From 66f382e672f4afe691edc0a95e74d5f9438abdae Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 8 Feb 2019 10:38:08 +0100 Subject: [PATCH 165/202] allow -CC and -LD despite environment arguments --- .../oracle/graal/python/shell/GraalPythonMain.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java index 6311dad41a..14b39ae868 100644 --- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java +++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java @@ -78,7 +78,8 @@ public static void main(String[] args) { @Override protected List preprocessArguments(List givenArgs, Map polyglotOptions) { ArrayList unrecognized = new ArrayList<>(); - ArrayList inputArgs = new ArrayList<>(getDefaultEnvironmentArgs()); + List defaultEnvironmentArgs = getDefaultEnvironmentArgs(); + ArrayList inputArgs = new ArrayList<>(defaultEnvironmentArgs); inputArgs.addAll(givenArgs); givenArguments = new ArrayList<>(inputArgs); List arguments = new ArrayList<>(inputArgs); @@ -142,15 +143,15 @@ protected List preprocessArguments(List givenArgs, Map Date: Fri, 8 Feb 2019 10:53:00 +0100 Subject: [PATCH 166/202] fix logging of updated sys-prefix --- .../src/com/oracle/graal/python/PythonLanguage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index faec67b538..b76a552afd 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -173,7 +173,8 @@ private void ensureHomeInOptions(Env env) { if (home != null) { if (sysPrefix.isEmpty()) { - env.getOptions().set(PythonOptions.SysPrefix, home.getAbsoluteFile().getPath()); + sysPrefix = home.getAbsoluteFile().getPath(); + env.getOptions().set(PythonOptions.SysPrefix, sysPrefix); } if (coreHome.isEmpty()) { From 8d19acf12149517ea45edb36116f55919f9402f0 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 8 Feb 2019 10:55:41 +0100 Subject: [PATCH 167/202] pass the sys prefix when creating a venv --- graalpython/lib-python/3/venv/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graalpython/lib-python/3/venv/__init__.py b/graalpython/lib-python/3/venv/__init__.py index 45d0c46631..6268239eb4 100644 --- a/graalpython/lib-python/3/venv/__init__.py +++ b/graalpython/lib-python/3/venv/__init__.py @@ -326,9 +326,10 @@ def replace_variables(self, text, context): # Truffle change: we need to set some extra options for the launcher to work text = text.replace( '__VENV_GRAAL_PYTHON_OPTIONS__', - "--python.CoreHome='%s' --python.StdLibHome='%s' --python.Executable='%s'" % ( + "--python.CoreHome='%s' --python.StdLibHome='%s' --python.SysPrefix='%s' --python.Executable='%s'" % ( sys.graal_python_core_home, sys.graal_python_stdlib_home, + sys.prefix, context.env_exe, ) ) From b5c5bffeffdb517f9bfe6c43a169f3c81d68b37b Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 8 Feb 2019 11:14:42 +0100 Subject: [PATCH 168/202] disambiguate sys.prefix and sys.base_prefix. This is needed for correct venv behaviour when compiling native modules, for example. --- .../com/oracle/graal/python/PythonLanguage.java | 16 ++++++++++++---- .../builtins/modules/SysModuleBuiltins.java | 9 ++++++++- .../oracle/graal/python/runtime/PythonCore.java | 16 +++++++++++++++- .../graal/python/runtime/PythonOptions.java | 3 +++ graalpython/lib-python/3/venv/__init__.py | 5 +++-- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index b76a552afd..57573b5a13 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -146,14 +146,16 @@ protected PythonContext createContext(Env env) { private void ensureHomeInOptions(Env env) { String languageHome = getLanguageHome(); String sysPrefix = env.getOptions().get(PythonOptions.SysPrefix); + String basePrefix = env.getOptions().get(PythonOptions.SysBasePrefix); String coreHome = env.getOptions().get(PythonOptions.CoreHome); String stdLibHome = env.getOptions().get(PythonOptions.StdLibHome); PythonCore.writeInfo((MessageFormat.format("Initial locations:" + "\n\tLanguage home: {0}" + "\n\tSysPrefix: {1}" + - "\n\tCoreHome: {2}" + - "\n\tStdLibHome: {3}", languageHome, sysPrefix, coreHome, stdLibHome))); + "\n\tBaseSysPrefix: {2}" + + "\n\tCoreHome: {3}" + + "\n\tStdLibHome: {4}", languageHome, sysPrefix, basePrefix, coreHome, stdLibHome))); TruffleFile home = null; if (languageHome != null) { @@ -177,6 +179,11 @@ private void ensureHomeInOptions(Env env) { env.getOptions().set(PythonOptions.SysPrefix, sysPrefix); } + if (basePrefix.isEmpty()) { + basePrefix = home.getAbsoluteFile().getPath(); + env.getOptions().set(PythonOptions.SysBasePrefix, basePrefix); + } + if (coreHome.isEmpty()) { try { for (TruffleFile f : home.list()) { @@ -210,8 +217,9 @@ private void ensureHomeInOptions(Env env) { PythonCore.writeInfo((MessageFormat.format("Updated locations:" + "\n\tLanguage home: {0}" + "\n\tSysPrefix: {1}" + - "\n\tCoreHome: {2}" + - "\n\tStdLibHome: {3}", home.getPath(), sysPrefix, coreHome, stdLibHome))); + "\n\tSysBasePrefix: {2}" + + "\n\tCoreHome: {3}" + + "\n\tStdLibHome: {4}", home.getPath(), sysPrefix, basePrefix, coreHome, stdLibHome))); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java index 5565e4686d..fe01ed9054 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java @@ -104,7 +104,8 @@ public class SysModuleBuiltins extends PythonBuiltins { COMPILE_TIME = compile_time; } - public static final String[] SYS_PREFIX_ATTRIBUTES = new String[]{"prefix", "exec_prefix", "base_prefix", "base_exec_prefix"}; + public static final String[] SYS_PREFIX_ATTRIBUTES = new String[]{"prefix", "exec_prefix"}; + public static final String[] BASE_PREFIX_ATTRIBUTES = new String[]{"base_prefix", "base_exec_prefix"}; @Override protected List> getNodeFactories() { @@ -159,11 +160,17 @@ public void postInitialize(PythonCore core) { PythonContext context = core.getContext(); String[] args = context.getEnv().getApplicationArguments(); sys.setAttribute("argv", core.factory().createList(Arrays.copyOf(args, args.length, Object[].class))); + String prefix = PythonCore.getSysPrefix(context.getEnv()); for (String name : SysModuleBuiltins.SYS_PREFIX_ATTRIBUTES) { sys.setAttribute(name, prefix); } + String base_prefix = PythonCore.getSysBasePrefix(context.getEnv()); + for (String name : SysModuleBuiltins.BASE_PREFIX_ATTRIBUTES) { + sys.setAttribute(name, base_prefix); + } + sys.setAttribute("executable", PythonOptions.getOption(context, PythonOptions.Executable)); sys.setAttribute("graal_python_home", context.getLanguage().getHome()); sys.setAttribute("graal_python_core_home", PythonOptions.getOption(context, PythonOptions.CoreHome)); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java index 8b7c8a615e..8d6dd92c92 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java @@ -120,7 +120,21 @@ public static String getSysPrefix(TruffleLanguage.Env env) { if (sysPrefix.isEmpty()) { writeWarning(NO_PREFIX_WARNING); env.getOptions().set(PythonOptions.SysPrefix, PREFIX); - return LIB_GRAALPYTHON; + return PREFIX; + } + return sysPrefix; + } + + @TruffleBoundary + public static String getSysBasePrefix(TruffleLanguage.Env env) { + String sysPrefix = env.getOptions().get(PythonOptions.SysBasePrefix); + if (sysPrefix.isEmpty()) { + String homePrefix = PythonLanguage.getCurrent().getHome(); + if (homePrefix.isEmpty()) { + homePrefix = PREFIX; + } + env.getOptions().set(PythonOptions.SysBasePrefix, homePrefix); + return homePrefix; } return sysPrefix; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java index 622135becf..8fa34d5e92 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java @@ -44,6 +44,9 @@ private PythonOptions() { @Option(category = OptionCategory.USER, help = "Set the location of sys.prefix. Overrides any environment variables or Java options.") // public static final OptionKey SysPrefix = new OptionKey<>(""); + @Option(category = OptionCategory.EXPERT, help = "Set the location of sys.base_prefix. Overrides any environment variables or Java options.") // + public static final OptionKey SysBasePrefix = new OptionKey<>(""); + @Option(category = OptionCategory.USER, help = "Set the location of lib-graalpython. Overrides any environment variables or Java options.") // public static final OptionKey CoreHome = new OptionKey<>(""); diff --git a/graalpython/lib-python/3/venv/__init__.py b/graalpython/lib-python/3/venv/__init__.py index 6268239eb4..da5c5177fd 100644 --- a/graalpython/lib-python/3/venv/__init__.py +++ b/graalpython/lib-python/3/venv/__init__.py @@ -326,10 +326,11 @@ def replace_variables(self, text, context): # Truffle change: we need to set some extra options for the launcher to work text = text.replace( '__VENV_GRAAL_PYTHON_OPTIONS__', - "--python.CoreHome='%s' --python.StdLibHome='%s' --python.SysPrefix='%s' --python.Executable='%s'" % ( + "--python.CoreHome='%s' --python.StdLibHome='%s' --python.SysPrefix='%s' --python.SysBasePrefix='%s' --python.Executable='%s'" % ( sys.graal_python_core_home, sys.graal_python_stdlib_home, - sys.prefix, + context.env_dir, + sys.base_prefix, context.env_exe, ) ) From 54a470d8ee20f3b7f5813d692a60be926943547f Mon Sep 17 00:00:00 2001 From: Cosmin Basca Date: Fri, 8 Feb 2019 15:47:50 +0100 Subject: [PATCH 169/202] fix __truffle_source__ builtin for generator functions --- .../python/builtins/objects/function/PFunction.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java index 865fe0cf58..18a980b731 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. @@ -33,6 +33,7 @@ import com.oracle.graal.python.builtins.objects.object.PythonObject; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; import com.oracle.graal.python.nodes.SpecialMethodNames; +import com.oracle.graal.python.nodes.generator.GeneratorFunctionRootNode; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; @@ -144,7 +145,11 @@ public void setDefaults(Object[] defaults) { @TruffleBoundary public String getSourceCode() { - SourceSection sourceSection = callTarget.getRootNode().getSourceSection(); + RootNode rootNode = callTarget.getRootNode(); + if (rootNode instanceof GeneratorFunctionRootNode) { + rootNode = ((GeneratorFunctionRootNode) rootNode).getFunctionRootNode(); + } + SourceSection sourceSection = rootNode.getSourceSection(); if (sourceSection != null) { return sourceSection.getCharacters().toString(); } From c7a0bac6a7c10bf3d36a6a623bd56b1d557c49f5 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 12 Feb 2019 15:29:34 +0100 Subject: [PATCH 170/202] Fix: Do not use 'Throwable.getMessage' without TruffleBoundary. --- .../builtins/objects/mmap/MMapBuiltins.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java index c47bdae658..f4828d9279 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java @@ -277,7 +277,7 @@ int doSingle(VirtualFrame frame, PMMap self, Object idxObj, return res; } catch (IOException e) { - throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + throw raise(PythonBuiltinClassType.OSError, getMessage(e)); } } @@ -301,7 +301,7 @@ Object doSlice(VirtualFrame frame, PMMap self, PSlice idx, return factory().createBytes(s); } catch (IOException e) { - throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + throw raise(PythonBuiltinClassType.OSError, getMessage(e)); } } @@ -344,7 +344,7 @@ PNone doSingle(VirtualFrame frame, PMMap self, Object idxObj, Object val, return PNone.NONE; } catch (IOException e) { - throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + throw raise(PythonBuiltinClassType.OSError, getMessage(e)); } } @@ -376,7 +376,7 @@ PNone doSlice(VirtualFrame frame, PMMap self, PSlice idx, PIBytesLike val, return PNone.NONE; } catch (IOException e) { - throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + throw raise(PythonBuiltinClassType.OSError, getMessage(e)); } } @@ -468,7 +468,7 @@ long readline(VirtualFrame frame, PMMap self) { SeekableByteChannel channel = self.getChannel(); return position(channel) - self.getOffset(); } catch (IOException e) { - throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + throw raiseOSError(frame, OSErrorEnum.EIO, getMessage(e)); } } } @@ -544,7 +544,7 @@ Object readline(PMMap self, } return factory().createBytes(res); } catch (IOException e) { - throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + throw raise(PythonBuiltinClassType.OSError, getMessage(e)); } } @@ -626,7 +626,7 @@ Object seek(VirtualFrame frame, PMMap self, long dist, Object how) { return PNone.NONE; } catch (IOException e) { errorProfile.enter(); - throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + throw raiseOSError(frame, OSErrorEnum.EIO, getMessage(e)); } } @@ -687,7 +687,7 @@ long find(PMMap primary, PIBytesLike sub, Object starting, Object ending, } return -1; } catch (IOException e) { - throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + throw raise(PythonBuiltinClassType.OSError, getMessage(e)); } } @@ -714,7 +714,7 @@ long find(PMMap primary, int sub, Object starting, @SuppressWarnings("unused") O } return -1; } catch (IOException e) { - throw raise(PythonBuiltinClassType.OSError, e.getMessage()); + throw raise(PythonBuiltinClassType.OSError, getMessage(e)); } } @@ -752,7 +752,7 @@ long doFull(VirtualFrame frame, PMMap self, return size(self.getChannel()) - self.getOffset(); } catch (IOException e) { profile.enter(); - throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + throw raiseOSError(frame, OSErrorEnum.EIO, getMessage(e)); } } @@ -767,7 +767,7 @@ long doGeneric(VirtualFrame frame, PMMap self) { try { return size(self.getChannel()) - self.getOffset(); } catch (IOException e) { - throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage()); + throw raiseOSError(frame, OSErrorEnum.EIO, getMessage(e)); } } return self.getLength(); From 1d34ed981edc25de9d23bd482336868f8a51025f Mon Sep 17 00:00:00 2001 From: Cosmin Basca Date: Wed, 13 Feb 2019 11:49:27 +0100 Subject: [PATCH 171/202] PCode: handle module root node for pro extraction + codestring (source code) - fix getFreeVars in PClosureRootNode - fix extractCode - create calltarget from source --- .../builtins/modules/BuiltinFunctions.java | 15 +++++++- .../python/builtins/objects/code/PCode.java | 37 +++++++++++++++++-- .../graal/python/nodes/PClosureRootNode.java | 11 ++++-- .../nodes/expression/ExpressionNode.java | 10 ++++- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 28addcec15..0b70e17856 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -171,6 +171,7 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.debug.Debugger; import com.oracle.truffle.api.dsl.Cached; @@ -193,6 +194,7 @@ import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.source.Source; +import org.graalvm.polyglot.io.ByteSequence; @CoreFunctions(defineModule = "builtins") public final class BuiltinFunctions extends PythonBuiltins { @@ -681,7 +683,18 @@ Object execCustomGlobalsGlobalLocals(Object source, PDict globals, @SuppressWarn // fall back (like their CPython counterparts) to writing to the globals. We only need // to ensure that the `locals()` call still gives us the globals dict PArguments.setPFrame(args, factory().createPFrame(globals)); - return indirectCallNode.call(code.getRootCallTarget(), args); + RootCallTarget rootCallTarget = code.getRootCallTarget(); + if (rootCallTarget == null) { + Source src = Source.newBuilder("python", new String(code.getCodestring()), code.getName()).build(); + Node root = getCore().getParser().parse(ParserMode.File, getCore(), src, null); + if (root instanceof RootNode) { + rootCallTarget = Truffle.getRuntime().createCallTarget((RootNode) root); + } + } + if (rootCallTarget == null) { + throw raise(ValueError, "cannot create the rootCallTarget from the code object: %p", code); + } + return indirectCallNode.call(rootCallTarget, args); } @Specialization(guards = {"isMapping(locals)"}) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java index 117609aa0e..3b69b601ae 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -45,6 +45,7 @@ import java.util.List; import java.util.Set; +import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.objects.function.Arity; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; @@ -53,19 +54,25 @@ import com.oracle.graal.python.nodes.argument.ReadKeywordNode; import com.oracle.graal.python.nodes.argument.ReadVarArgsNode; import com.oracle.graal.python.nodes.argument.ReadVarKeywordsNode; +import com.oracle.graal.python.nodes.control.TopLevelExceptionHandler; import com.oracle.graal.python.nodes.frame.FrameSlotIDs; import com.oracle.graal.python.nodes.frame.WriteIdentifierNode; import com.oracle.graal.python.nodes.function.FunctionRootNode; import com.oracle.graal.python.nodes.generator.GeneratorFunctionRootNode; +import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.PythonCore; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.graal.python.runtime.PythonParser; +import com.oracle.graal.python.runtime.exception.PException; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeUtil; import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; +import org.graalvm.polyglot.io.ByteSequence; public final class PCode extends PythonBuiltinObject { private final long FLAG_POS_GENERATOR = 5; @@ -158,6 +165,8 @@ private static String[] extractFreeVars(RootNode rootNode) { return ((FunctionRootNode) rootNode).getFreeVars(); } else if (rootNode instanceof GeneratorFunctionRootNode) { return ((GeneratorFunctionRootNode) rootNode).getFreeVars(); + } else if (rootNode instanceof ModuleRootNode) { + return ((ModuleRootNode) rootNode).getFreeVars(); } else { return null; } @@ -168,6 +177,8 @@ private static String[] extractCellVars(RootNode rootNode) { return ((FunctionRootNode) rootNode).getCellVars(); } else if (rootNode instanceof GeneratorFunctionRootNode) { return ((GeneratorFunctionRootNode) rootNode).getCellVars(); + } else if (rootNode instanceof ModuleRootNode) { + return new String[0]; } else { return null; } @@ -189,13 +200,16 @@ private static String extractFileName(RootNode rootNode) { private static int extractFirstLineno(RootNode rootNode) { RootNode funcRootNode = (rootNode instanceof GeneratorFunctionRootNode) ? ((GeneratorFunctionRootNode) rootNode).getFunctionRootNode() : rootNode; SourceSection sourceSection = funcRootNode.getSourceSection(); - return (sourceSection != null) ? sourceSection.getStartLine() : 1; + if (sourceSection != null) { + return sourceSection.getStartLine(); + } + return 1; } private static String extractName(RootNode rootNode) { String name; if (rootNode instanceof ModuleRootNode) { - name = ""; + name = rootNode.getName(); } else if (rootNode instanceof FunctionRootNode) { name = ((FunctionRootNode) rootNode).getFunctionName(); } else { @@ -299,6 +313,18 @@ private void extractArgStats() { this.nlocals = varnamesSet.size(); } + @TruffleBoundary + public void extractCodeString(RootNode rootNode) { + RootNode funcRootNode = rootNode; + if (rootNode instanceof GeneratorFunctionRootNode) { + funcRootNode = ((GeneratorFunctionRootNode) rootNode).getFunctionRootNode(); + } + SourceSection sourceSection = funcRootNode.getSourceSection(); + if (sourceSection != null) { + this.codestring = sourceSection.getCharacters().toString().getBytes(); + } + } + public RootNode getRootNode() { return rootNode; } @@ -389,6 +415,9 @@ public Object[] getVarnames() { } public byte[] getCodestring() { + if (codestring == null && hasRootNode()) { + extractCodeString(getRootNode()); + } return codestring; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PClosureRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PClosureRootNode.java index 0dbfd930a5..2ec3f88039 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PClosureRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PClosureRootNode.java @@ -90,10 +90,13 @@ public boolean hasFreeVars() { } public String[] getFreeVars() { - String[] freeVars = new String[freeVarSlots.length]; - for (int i = 0; i < freeVarSlots.length; i++) { - freeVars[i] = (String) freeVarSlots[i].getIdentifier(); + if (freeVarSlots != null) { + String[] freeVars = new String[freeVarSlots.length]; + for (int i = 0; i < freeVarSlots.length; i++) { + freeVars[i] = (String) freeVarSlots[i].getIdentifier(); + } + return freeVars; } - return freeVars; + return null; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/ExpressionNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/ExpressionNode.java index b4f3c868fe..13d39718ed 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/ExpressionNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/ExpressionNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -53,6 +53,8 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.UnexpectedResultException; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.source.SourceSection; /** * Base class for all expressions. Expressions always return a value. @@ -176,7 +178,11 @@ public static final class ExpressionWithSideEffects extends ExpressionNode { private ExpressionWithSideEffects(ExpressionNode node, StatementNode[] sideEffects) { this.node = node; this.sideEffects = sideEffects; - this.assignSourceSection(node.getSourceSection()); + SourceSection sourceSection = node.getSourceSection(); + if (sourceSection!=null) { + Source source = sourceSection.getSource(); + this.assignSourceSection(source.createSection(0, source.getLength())); + } } @Override From f74c176b2290dd1a45b5cc3cc730bfceac74f277 Mon Sep 17 00:00:00 2001 From: Cosmin Basca Date: Thu, 14 Feb 2019 10:57:48 +0100 Subject: [PATCH 172/202] add test module code unitttest --- .../src/tests/test_code.py | 30 ++++++++++++++++++- .../graal/python/nodes/PClosureRootNode.java | 2 +- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_code.py b/graalpython/com.oracle.graal.python.test/src/tests/test_code.py index a318b50b3d..5a53af459c 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_code.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_code.py @@ -77,6 +77,8 @@ def test_firstlineno(): def test_code_attributes(): + import sys + code = wrapper().__code__ assert code.co_argcount == 3 assert code.co_kwonlyargcount == 0 @@ -85,7 +87,8 @@ def test_code_attributes(): assert code.co_flags & (1 << 5) assert not code.co_flags & (1 << 2) assert not code.co_flags & (1 << 3) - # assert code.co_code + if sys.implementation.name == 'graalpython': + assert code.co_code.decode().strip() == wrapper().__truffle_source__.strip() # assert code.co_consts # assert set(code.co_names) == {'set', 'TypeError', 'print'} assert set(code.co_varnames) == {'arg_l', 'kwarg_case', 'kwarg_other', 'loc_1', 'loc_3', 'inner_func'} @@ -133,3 +136,28 @@ def test_code_copy(): assert code.co_lnotab == code2.co_lnotab assert set(code.co_freevars) == set(code2.co_freevars) assert set(code.co_cellvars) == set(code2.co_cellvars) + + +def test_module_code(): + import sys + m = __import__('package.moduleA') + with open(m.__file__, 'r') as MODULE: + source = MODULE.read() + code = compile(source, m.__file__, 'exec') + assert code.co_argcount == 0 + assert code.co_kwonlyargcount == 0 + assert code.co_nlocals == 0 + # assert code.co_stacksize == 0 + # assert code.co_flags == 0 + if sys.implementation.name == 'graalpython': + assert code.co_code.decode().strip() == source.strip() + # assert code.co_consts == tuple() + # assert set(code.co_names) == set() + assert set(code.co_varnames) == set() + assert code.co_filename.endswith("__init__.py") + assert code.co_name.startswith(" Date: Thu, 14 Feb 2019 11:02:26 +0100 Subject: [PATCH 173/202] missing truffle boundary style fix --- .../builtins/modules/BuiltinFunctions.java | 17 ++++++++++++----- .../graal/python/nodes/PClosureRootNode.java | 2 +- .../python/nodes/expression/ExpressionNode.java | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index 0b70e17856..d1d901b770 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -163,6 +163,7 @@ import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.PythonCore; import com.oracle.graal.python.runtime.PythonOptions; +import com.oracle.graal.python.runtime.PythonParser; import com.oracle.graal.python.runtime.PythonParser.ParserMode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.exception.PythonErrorType; @@ -685,11 +686,7 @@ Object execCustomGlobalsGlobalLocals(Object source, PDict globals, @SuppressWarn PArguments.setPFrame(args, factory().createPFrame(globals)); RootCallTarget rootCallTarget = code.getRootCallTarget(); if (rootCallTarget == null) { - Source src = Source.newBuilder("python", new String(code.getCodestring()), code.getName()).build(); - Node root = getCore().getParser().parse(ParserMode.File, getCore(), src, null); - if (root instanceof RootNode) { - rootCallTarget = Truffle.getRuntime().createCallTarget((RootNode) root); - } + rootCallTarget = extractRootCallTargetFromSource(code); } if (rootCallTarget == null) { throw raise(ValueError, "cannot create the rootCallTarget from the code object: %p", code); @@ -697,6 +694,16 @@ Object execCustomGlobalsGlobalLocals(Object source, PDict globals, @SuppressWarn return indirectCallNode.call(rootCallTarget, args); } + @TruffleBoundary + private RootCallTarget extractRootCallTargetFromSource(PCode code) { + Source src = Source.newBuilder("python", new String(code.getCodestring()), code.getName()).build(); + Node root = getCore().getParser().parse(ParserMode.File, getCore(), src, null); + if (root instanceof RootNode) { + return Truffle.getRuntime().createCallTarget((RootNode) root); + } + return null; + } + @Specialization(guards = {"isMapping(locals)"}) Object execInheritGlobalsCustomLocals(VirtualFrame frame, Object source, @SuppressWarnings("unused") PNone globals, Object locals, @Cached("create()") ReadCallerFrameNode readCallerFrameNode) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PClosureRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PClosureRootNode.java index 8e484cd1c9..2b925c8d9c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PClosureRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PClosureRootNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/ExpressionNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/ExpressionNode.java index 13d39718ed..f9e8652400 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/ExpressionNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/ExpressionNode.java @@ -179,7 +179,7 @@ private ExpressionWithSideEffects(ExpressionNode node, StatementNode[] sideEffec this.node = node; this.sideEffects = sideEffects; SourceSection sourceSection = node.getSourceSection(); - if (sourceSection!=null) { + if (sourceSection != null) { Source source = sourceSection.getSource(); this.assignSourceSection(source.createSection(0, source.getLength())); } From c5e9b2ef77fb2afafacab14c0d79584f0e5d242f Mon Sep 17 00:00:00 2001 From: Cosmin Basca Date: Thu, 14 Feb 2019 11:13:27 +0100 Subject: [PATCH 174/202] style fix --- .../python/builtins/modules/BuiltinFunctions.java | 2 -- .../graal/python/builtins/objects/code/PCode.java | 14 ++++---------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index d1d901b770..f49b35f233 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -163,7 +163,6 @@ import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.PythonCore; import com.oracle.graal.python.runtime.PythonOptions; -import com.oracle.graal.python.runtime.PythonParser; import com.oracle.graal.python.runtime.PythonParser.ParserMode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.exception.PythonErrorType; @@ -195,7 +194,6 @@ import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.source.Source; -import org.graalvm.polyglot.io.ByteSequence; @CoreFunctions(defineModule = "builtins") public final class BuiltinFunctions extends PythonBuiltins { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java index 3b69b601ae..43ef28a765 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java @@ -45,7 +45,6 @@ import java.util.List; import java.util.Set; -import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.objects.function.Arity; import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; @@ -54,15 +53,11 @@ import com.oracle.graal.python.nodes.argument.ReadKeywordNode; import com.oracle.graal.python.nodes.argument.ReadVarArgsNode; import com.oracle.graal.python.nodes.argument.ReadVarKeywordsNode; -import com.oracle.graal.python.nodes.control.TopLevelExceptionHandler; import com.oracle.graal.python.nodes.frame.FrameSlotIDs; import com.oracle.graal.python.nodes.frame.WriteIdentifierNode; import com.oracle.graal.python.nodes.function.FunctionRootNode; import com.oracle.graal.python.nodes.generator.GeneratorFunctionRootNode; -import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.PythonCore; -import com.oracle.graal.python.runtime.PythonParser; -import com.oracle.graal.python.runtime.exception.PException; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; @@ -70,9 +65,7 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeUtil; import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; -import org.graalvm.polyglot.io.ByteSequence; public final class PCode extends PythonBuiltinObject { private final long FLAG_POS_GENERATOR = 5; @@ -314,15 +307,16 @@ private void extractArgStats() { } @TruffleBoundary - public void extractCodeString(RootNode rootNode) { + private static byte[] extractCodeString(RootNode rootNode) { RootNode funcRootNode = rootNode; if (rootNode instanceof GeneratorFunctionRootNode) { funcRootNode = ((GeneratorFunctionRootNode) rootNode).getFunctionRootNode(); } SourceSection sourceSection = funcRootNode.getSourceSection(); if (sourceSection != null) { - this.codestring = sourceSection.getCharacters().toString().getBytes(); + return sourceSection.getCharacters().toString().getBytes(); } + return null; } public RootNode getRootNode() { @@ -416,7 +410,7 @@ public Object[] getVarnames() { public byte[] getCodestring() { if (codestring == null && hasRootNode()) { - extractCodeString(getRootNode()); + this.codestring = extractCodeString(getRootNode()); } return codestring; } From 788296989b913496d7eb1aebd6035b085b751b52 Mon Sep 17 00:00:00 2001 From: Lukas Stadler Date: Thu, 14 Feb 2019 16:57:17 +0100 Subject: [PATCH 175/202] prevent toggling of frame slot kinds to let code stabilize --- .../python/nodes/frame/FrameSlotNode.java | 2 +- .../nodes/frame/WriteLocalVariableNode.java | 41 +++++-------------- .../nodes/generator/FrameTransferNode.java | 2 +- .../WriteGeneratorFrameVariableNode.java | 40 +++++++----------- 4 files changed, 28 insertions(+), 57 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java index 28e3766214..4eb7b93eb6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java @@ -104,7 +104,7 @@ protected final boolean isLongOrObjectKind(Frame frame) { return isKind(frame, FrameSlotKind.Long) || isKind(frame, FrameSlotKind.Object); } - protected final boolean isObjectKind(Frame frame) { + protected final boolean isOrSetObjectKind(Frame frame) { if (frame.getFrameDescriptor().getFrameSlotKind(frameSlot) != FrameSlotKind.Object) { CompilerDirectives.transferToInterpreter(); frame.getFrameDescriptor().setFrameSlotKind(frameSlot, FrameSlotKind.Object); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java index 16fd6752e3..7b8aab2f9c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java @@ -25,9 +25,6 @@ */ package com.oracle.graal.python.nodes.frame; -import com.oracle.graal.python.builtins.objects.PNone; -import com.oracle.graal.python.builtins.objects.common.KeywordsStorage; -import com.oracle.graal.python.builtins.objects.function.PKeyword; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.nodes.expression.ExpressionNode; import com.oracle.graal.python.nodes.frame.WriteLocalVariableNodeGen.WriteLocalFrameSlotNodeGen; @@ -35,9 +32,7 @@ import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameSlot; -import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; @@ -86,12 +81,6 @@ public final boolean executeBoolean(VirtualFrame frame) { public abstract Object executeWith(VirtualFrame frame, Object value); - @Specialization(guards = "isBooleanKind(frame)") - public PNone write(VirtualFrame frame, PNone right) { - frame.setObject(frameSlot, PNone.NONE); - return right; - } - @Specialization(guards = "isBooleanKind(frame)") public boolean write(VirtualFrame frame, boolean right) { frame.setBoolean(frameSlot, right); @@ -104,18 +93,18 @@ public int write(VirtualFrame frame, int value) { return value; } - @Specialization(guards = {"isLongOrObjectKind(frame)", "isPrimitiveInt(value)", "!value.isNative()"}, rewriteOn = ArithmeticException.class) - public PInt writePIntAsLong(VirtualFrame frame, PInt value) { - frame.getFrameDescriptor().setFrameSlotKind(frameSlot, FrameSlotKind.Long); - frame.setLong(frameSlot, value.longValueExact()); - return value; + @Specialization(guards = {"isPrimitiveInt(value)", "!value.isNative()", "isLongKind(frame)"}, rewriteOn = ArithmeticException.class) + public long writeSmallPIntAsLong(VirtualFrame frame, PInt value) { + long longValue = value.longValueExact(); + frame.setLong(frameSlot, longValue); + return longValue; } - @Specialization(guards = "isLongOrObjectKind(frame)") - public PInt writePIntAsObject(VirtualFrame frame, PInt value) { - frame.getFrameDescriptor().setFrameSlotKind(frameSlot, FrameSlotKind.Object); - frame.setObject(frameSlot, value); - return value; + @Specialization(guards = {"isPrimitiveInt(value)", "!value.isNative()", "isOrSetObjectKind(frame)"}, rewriteOn = ArithmeticException.class) + public long writeSmallPIntAsObject(VirtualFrame frame, PInt value) { + long longValue = value.longValueExact(); + frame.setObject(frameSlot, longValue); + return longValue; } @Specialization(guards = "isDoubleKind(frame)") @@ -124,14 +113,7 @@ public double write(VirtualFrame frame, double right) { return right; } - @Specialization(guards = "isObjectKind(frame)") - @ExplodeLoop - public Object write(VirtualFrame frame, PKeyword[] right) { - frame.setObject(frameSlot, factory().createDict(KeywordsStorage.create(right))); - return right; - } - - @Specialization(guards = "isObjectKind(frame)") + @Specialization(guards = "isOrSetObjectKind(frame)") public Object write(VirtualFrame frame, Object right) { frame.setObject(frameSlot, right); return right; @@ -139,7 +121,6 @@ public Object write(VirtualFrame frame, Object right) { } public WriteLocalVariableNode(FrameSlot slot) { - super(); this.writeNode = WriteLocalFrameSlotNodeGen.create(slot); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java index 72d9035b1b..1ceaa69326 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java @@ -90,7 +90,7 @@ public double doDouble(VirtualFrame frame, double right) { return right; } - @Specialization(guards = "isObjectKind(frame)") + @Specialization(guards = "isOrSetObjectKind(frame)") public Object write(VirtualFrame frame, Object right) { setObject(getCargoFrame(frame), right); return right; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java index e364172893..25e206fb99 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java @@ -25,7 +25,6 @@ */ package com.oracle.graal.python.nodes.generator; -import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.function.PArguments; import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.nodes.expression.ExpressionNode; @@ -37,7 +36,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameSlot; -import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.profiles.ValueProfile; @@ -96,51 +94,43 @@ public final boolean executeBoolean(VirtualFrame frame) { public abstract Object executeWith(VirtualFrame frame, Object value); - private Frame getGeneratorFrame(VirtualFrame frame) { + protected Frame getGeneratorFrame(VirtualFrame frame) { return frameProfile.profile(PArguments.getGeneratorFrame(frame)); } - @Specialization(guards = "isBooleanKind(frame)") - public PNone write(VirtualFrame frame, PNone right) { - getGeneratorFrame(frame).setObject(frameSlot, PNone.NONE); - return right; - } - - @Specialization(guards = "isBooleanKind(frame)") + @Specialization(guards = "isBooleanKind(getGeneratorFrame(frame))") public boolean write(VirtualFrame frame, boolean right) { getGeneratorFrame(frame).setBoolean(frameSlot, right); return right; } - @Specialization(guards = "isIntegerKind(frame)") + @Specialization(guards = "isIntegerKind(getGeneratorFrame(frame))") public int write(VirtualFrame frame, int value) { getGeneratorFrame(frame).setInt(frameSlot, value); return value; } - @Specialization(guards = {"isLongOrObjectKind(frame)", "isPrimitiveInt(value)", "!value.isNative()"}, rewriteOn = ArithmeticException.class) - public PInt writePIntAsLong(VirtualFrame frame, PInt value) { - Frame generatorFrame = getGeneratorFrame(frame); - generatorFrame.getFrameDescriptor().setFrameSlotKind(frameSlot, FrameSlotKind.Long); - generatorFrame.setLong(frameSlot, value.longValueExact()); - return value; + @Specialization(guards = {"isPrimitiveInt(value)", "!value.isNative()", "isLongKind(getGeneratorFrame(frame))"}, rewriteOn = ArithmeticException.class) + public long writeSmallPIntAsLong(VirtualFrame frame, PInt value) { + long longValue = value.longValueExact(); + getGeneratorFrame(frame).setLong(frameSlot, longValue); + return longValue; } - @Specialization(guards = "isLongOrObjectKind(frame)") - public PInt writePIntAsObject(VirtualFrame frame, PInt value) { - Frame generatorFrame = getGeneratorFrame(frame); - generatorFrame.getFrameDescriptor().setFrameSlotKind(frameSlot, FrameSlotKind.Object); - generatorFrame.setObject(frameSlot, value); - return value; + @Specialization(guards = {"isPrimitiveInt(value)", "!value.isNative()", "isOrSetObjectKind(getGeneratorFrame(frame))"}, rewriteOn = ArithmeticException.class) + public long writeSmallPIntAsObject(VirtualFrame frame, PInt value) { + long longValue = value.longValueExact(); + getGeneratorFrame(frame).setObject(frameSlot, longValue); + return longValue; } - @Specialization(guards = "isDoubleKind(frame)") + @Specialization(guards = "isDoubleKind(getGeneratorFrame(frame))") public double write(VirtualFrame frame, double right) { getGeneratorFrame(frame).setDouble(frameSlot, right); return right; } - @Specialization(guards = "isObjectKind(frame)") + @Specialization(guards = "isOrSetObjectKind(getGeneratorFrame(frame))") public Object write(VirtualFrame frame, Object right) { getGeneratorFrame(frame).setObject(frameSlot, right); return right; From eb56e199631f767be9adab942b9fe4ee1befbf45 Mon Sep 17 00:00:00 2001 From: Lukas Stadler Date: Thu, 14 Feb 2019 16:57:34 +0100 Subject: [PATCH 176/202] comment some code that doesn't work on darwin currently --- graalpython/lib-python/3/platform.py | 6 ++++-- graalpython/lib-python/3/urllib/request.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/graalpython/lib-python/3/platform.py b/graalpython/lib-python/3/platform.py index cc2db9870d..7ab17d910d 100755 --- a/graalpython/lib-python/3/platform.py +++ b/graalpython/lib-python/3/platform.py @@ -555,8 +555,10 @@ def _mac_ver_xml(): except ImportError: return None - with open(fn, 'rb') as f: - pl = plistlib.load(f) + # this would require xml parsing + # with open(fn, 'rb') as f: + # pl = plistlib.load(f) + pl = {'ProductVersion': '10.14.1'} release = pl['ProductVersion'] versioninfo = ('', '', '') machine = os.uname().machine diff --git a/graalpython/lib-python/3/urllib/request.py b/graalpython/lib-python/3/urllib/request.py index 96921440ed..19ad6fe14f 100644 --- a/graalpython/lib-python/3/urllib/request.py +++ b/graalpython/lib-python/3/urllib/request.py @@ -2581,7 +2581,7 @@ def ip2num(ipAddr): return False -if sys.platform == 'darwin': +if sys.platform == 'darwin' and False: # changed: use default path in darwin from _scproxy import _get_proxy_settings, _get_proxies def proxy_bypass_macosx_sysconf(host): From 797e87a8c21893ef302f693b329806aece91bc9a Mon Sep 17 00:00:00 2001 From: Lukas Stadler Date: Thu, 14 Feb 2019 17:12:45 +0100 Subject: [PATCH 177/202] update copyright years --- .../src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java | 2 +- .../oracle/graal/python/nodes/frame/WriteLocalVariableNode.java | 2 +- .../oracle/graal/python/nodes/generator/FrameTransferNode.java | 2 +- .../python/nodes/generator/WriteGeneratorFrameVariableNode.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java index 4eb7b93eb6..f5fcbeed42 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java index 7b8aab2f9c..c55da194db 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java index 1ceaa69326..6a5752c462 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java index 25e206fb99..9fc4f0ed70 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. From 06d419753a358cbf19150ec39473a7c04f2f8b43 Mon Sep 17 00:00:00 2001 From: Petr Pisl Date: Thu, 14 Feb 2019 17:15:35 +0100 Subject: [PATCH 178/202] [GR-13918] option -c doesn't work as expected. --- .../src/com/oracle/graal/python/shell/GraalPythonMain.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java index 14b39ae868..e84776f90d 100644 --- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java +++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java @@ -93,6 +93,7 @@ protected List preprocessArguments(List givenArgs, Map preprocessArguments(List givenArgs, Map Date: Thu, 14 Feb 2019 17:18:13 +0100 Subject: [PATCH 179/202] Correcting OSError implementation. --- graalpython/lib-graalpython/exceptions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/lib-graalpython/exceptions.py b/graalpython/lib-graalpython/exceptions.py index c9bb2d7daf..ebb631977b 100644 --- a/graalpython/lib-graalpython/exceptions.py +++ b/graalpython/lib-graalpython/exceptions.py @@ -165,7 +165,7 @@ def OSError__new__(subtype, *args, **kwds): def OSError__init__(self, *args, **kwds): if (not _oserror_use_init(type(self))): return None - _oserror_init(self, *arg) + _oserror_init(self, *args) def OSError__str__(self): if (self.filename): @@ -175,7 +175,7 @@ def OSError__str__(self): return "[Errno %i] %s: %s" % (self.errno, self.strerror, self.filename) if(self.errno and self.strerror): return "[Errno %i] %s" % (self.errno, self.strerror) - return BaseException.str(self) + return BaseException.__str__(self) OSError.__new__ = OSError__new__ OSError.__init__ = OSError__init__ From 85fdf49ed7d11f128eb38cca88fda77fe050c41d Mon Sep 17 00:00:00 2001 From: Cosmin Basca Date: Fri, 15 Feb 2019 10:07:37 +0100 Subject: [PATCH 180/202] remove patches for zlib (GR-9146), gzip (GR-9147), bz2 (GR-9148) --- .../lib-python/3/test/support/__init__.py | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/graalpython/lib-python/3/test/support/__init__.py b/graalpython/lib-python/3/test/support/__init__.py index d2d7007a43..65ae23b345 100644 --- a/graalpython/lib-python/3/test/support/__init__.py +++ b/graalpython/lib-python/3/test/support/__init__.py @@ -49,27 +49,21 @@ # multiprocessing = None multiprocessing = None -# TODO: Truffle reenable me once supported (GR-9146) -# try: -# import zlib -# except ImportError: -# zlib = None -zlib = None +try: + import zlib +except ImportError: + zlib = None -# TODO: Truffle reenable me once supported (GR-9147) -# try: -# import gzip -# except ImportError: -# gzip = None -gzip = None +try: + import gzip +except ImportError: + gzip = None -# TODO: Truffle reenable me once supported (GR-9148) -# try: -# import bz2 -# except ImportError: -# bz2 = None -bz2 = None +try: + import bz2 +except ImportError: + bz2 = None # TODO: Truffle reenable me once supported (GR-9149) # try: From b4ede76ec5748dcdad30ad9ccd9771a50fce6fcb Mon Sep 17 00:00:00 2001 From: Lukas Stadler Date: Fri, 15 Feb 2019 10:48:48 +0100 Subject: [PATCH 181/202] invalidate code when changing frame slot kinds --- .../com/oracle/graal/python/nodes/frame/FrameSlotNode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java index f5fcbeed42..5484feddbb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java @@ -106,7 +106,7 @@ protected final boolean isLongOrObjectKind(Frame frame) { protected final boolean isOrSetObjectKind(Frame frame) { if (frame.getFrameDescriptor().getFrameSlotKind(frameSlot) != FrameSlotKind.Object) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); frame.getFrameDescriptor().setFrameSlotKind(frameSlot, FrameSlotKind.Object); } return true; @@ -118,7 +118,7 @@ private boolean isKind(Frame frame, FrameSlotKind kind) { private boolean initialSetKind(Frame frame, FrameSlotKind kind) { if (frame.getFrameDescriptor().getFrameSlotKind(frameSlot) == FrameSlotKind.Illegal) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); frame.getFrameDescriptor().setFrameSlotKind(frameSlot, kind); return true; } From 4e47c223184cf5aba3b43d2baabfea1b8022760c Mon Sep 17 00:00:00 2001 From: Lukas Stadler Date: Fri, 15 Feb 2019 10:49:12 +0100 Subject: [PATCH 182/202] don't switch to object kind in guards --- .../python/nodes/frame/FrameSlotNode.java | 2 +- .../nodes/frame/WriteLocalVariableNode.java | 24 ++++++++-------- .../nodes/generator/FrameTransferNode.java | 28 ++++++++----------- .../WriteGeneratorFrameVariableNode.java | 24 ++++++++-------- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java index 5484feddbb..3d5d0cd395 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/FrameSlotNode.java @@ -104,7 +104,7 @@ protected final boolean isLongOrObjectKind(Frame frame) { return isKind(frame, FrameSlotKind.Long) || isKind(frame, FrameSlotKind.Object); } - protected final boolean isOrSetObjectKind(Frame frame) { + protected final boolean ensureObjectKind(Frame frame) { if (frame.getFrameDescriptor().getFrameSlotKind(frameSlot) != FrameSlotKind.Object) { CompilerDirectives.transferToInterpreterAndInvalidate(); frame.getFrameDescriptor().setFrameSlotKind(frameSlot, FrameSlotKind.Object); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java index c55da194db..604ddf2219 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/WriteLocalVariableNode.java @@ -82,9 +82,9 @@ public final boolean executeBoolean(VirtualFrame frame) { public abstract Object executeWith(VirtualFrame frame, Object value); @Specialization(guards = "isBooleanKind(frame)") - public boolean write(VirtualFrame frame, boolean right) { - frame.setBoolean(frameSlot, right); - return right; + public boolean write(VirtualFrame frame, boolean value) { + frame.setBoolean(frameSlot, value); + return value; } @Specialization(guards = "isIntegerKind(frame)") @@ -100,23 +100,25 @@ public long writeSmallPIntAsLong(VirtualFrame frame, PInt value) { return longValue; } - @Specialization(guards = {"isPrimitiveInt(value)", "!value.isNative()", "isOrSetObjectKind(frame)"}, rewriteOn = ArithmeticException.class) + @Specialization(guards = {"isPrimitiveInt(value)", "!value.isNative()"}, rewriteOn = ArithmeticException.class) public long writeSmallPIntAsObject(VirtualFrame frame, PInt value) { + ensureObjectKind(frame); long longValue = value.longValueExact(); frame.setObject(frameSlot, longValue); return longValue; } @Specialization(guards = "isDoubleKind(frame)") - public double write(VirtualFrame frame, double right) { - frame.setDouble(frameSlot, right); - return right; + public double write(VirtualFrame frame, double value) { + frame.setDouble(frameSlot, value); + return value; } - @Specialization(guards = "isOrSetObjectKind(frame)") - public Object write(VirtualFrame frame, Object right) { - frame.setObject(frameSlot, right); - return right; + @Specialization + public Object write(VirtualFrame frame, Object value) { + ensureObjectKind(frame); + frame.setObject(frameSlot, value); + return value; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java index 6a5752c462..3133424c02 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/FrameTransferNode.java @@ -26,7 +26,6 @@ package com.oracle.graal.python.nodes.generator; import com.oracle.graal.python.builtins.objects.function.PArguments; -import com.oracle.graal.python.builtins.objects.ints.PInt; import com.oracle.graal.python.nodes.expression.ExpressionNode; import com.oracle.graal.python.nodes.frame.FrameSlotNode; import com.oracle.truffle.api.dsl.GenerateNodeFactory; @@ -61,9 +60,9 @@ private Frame getCargoFrame(VirtualFrame frame) { } @Specialization(guards = "isBooleanKind(frame)") - public boolean write(VirtualFrame frame, boolean right) { - getCargoFrame(frame).setBoolean(frameSlot, right); - return right; + public boolean write(VirtualFrame frame, boolean value) { + getCargoFrame(frame).setBoolean(frameSlot, value); + return value; } @Specialization(guards = "isIntegerKind(frame)") @@ -72,12 +71,6 @@ public int doInteger(VirtualFrame frame, int value) { return value; } - @Specialization(guards = "isIntOrObjectKind(frame)") - public PInt write(VirtualFrame frame, PInt value) { - setObject(getCargoFrame(frame), value); - return value; - } - @Specialization(guards = "isLongKind(frame)") public long doLong(VirtualFrame frame, long value) { getCargoFrame(frame).setLong(frameSlot, value); @@ -85,14 +78,15 @@ public long doLong(VirtualFrame frame, long value) { } @Specialization(guards = "isDoubleKind(frame)") - public double doDouble(VirtualFrame frame, double right) { - getCargoFrame(frame).setDouble(frameSlot, right); - return right; + public double doDouble(VirtualFrame frame, double value) { + getCargoFrame(frame).setDouble(frameSlot, value); + return value; } - @Specialization(guards = "isOrSetObjectKind(frame)") - public Object write(VirtualFrame frame, Object right) { - setObject(getCargoFrame(frame), right); - return right; + @Specialization + public Object write(VirtualFrame frame, Object value) { + ensureObjectKind(frame); + setObject(getCargoFrame(frame), value); + return value; } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java index 9fc4f0ed70..cca6bf9fe5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java @@ -99,9 +99,9 @@ protected Frame getGeneratorFrame(VirtualFrame frame) { } @Specialization(guards = "isBooleanKind(getGeneratorFrame(frame))") - public boolean write(VirtualFrame frame, boolean right) { - getGeneratorFrame(frame).setBoolean(frameSlot, right); - return right; + public boolean write(VirtualFrame frame, boolean value) { + getGeneratorFrame(frame).setBoolean(frameSlot, value); + return value; } @Specialization(guards = "isIntegerKind(getGeneratorFrame(frame))") @@ -117,23 +117,25 @@ public long writeSmallPIntAsLong(VirtualFrame frame, PInt value) { return longValue; } - @Specialization(guards = {"isPrimitiveInt(value)", "!value.isNative()", "isOrSetObjectKind(getGeneratorFrame(frame))"}, rewriteOn = ArithmeticException.class) + @Specialization(guards = {"isPrimitiveInt(value)", "!value.isNative()"}, rewriteOn = ArithmeticException.class) public long writeSmallPIntAsObject(VirtualFrame frame, PInt value) { + ensureObjectKind(frame); long longValue = value.longValueExact(); getGeneratorFrame(frame).setObject(frameSlot, longValue); return longValue; } @Specialization(guards = "isDoubleKind(getGeneratorFrame(frame))") - public double write(VirtualFrame frame, double right) { - getGeneratorFrame(frame).setDouble(frameSlot, right); - return right; + public double write(VirtualFrame frame, double value) { + getGeneratorFrame(frame).setDouble(frameSlot, value); + return value; } - @Specialization(guards = "isOrSetObjectKind(getGeneratorFrame(frame))") - public Object write(VirtualFrame frame, Object right) { - getGeneratorFrame(frame).setObject(frameSlot, right); - return right; + @Specialization + public Object write(VirtualFrame frame, Object value) { + ensureObjectKind(frame); + getGeneratorFrame(frame).setObject(frameSlot, value); + return value; } } From 097987fd38cbca15bfd06210d111779134a5ca76 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Sat, 16 Feb 2019 11:34:14 +0100 Subject: [PATCH 183/202] Fix: Convert 'NULL' to 'None' for 'PySet_New'. --- graalpython/com.oracle.graal.python.cext/src/setobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python.cext/src/setobject.c b/graalpython/com.oracle.graal.python.cext/src/setobject.c index bbb8778467..a2d6deca02 100644 --- a/graalpython/com.oracle.graal.python.cext/src/setobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/setobject.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -45,7 +45,7 @@ PyTypeObject PyFrozenSet_Type = PY_TRUFFLE_TYPE("frozenset", &PyType_Type, Py_TP UPCALL_ID(PySet_New); PyObject * PySet_New(PyObject *iterable) { - return UPCALL_CEXT_O(_jls_PySet_New, native_to_java(iterable)); + return UPCALL_CEXT_O(_jls_PySet_New, native_to_java(iterable != NULL ? iterable : Py_None)); } UPCALL_ID(PyFrozenSet_New); From d3c3234815dd4dfef70a406410cc0ac2bb948032 Mon Sep 17 00:00:00 2001 From: Petr Pisl Date: Tue, 19 Feb 2019 11:30:43 +0100 Subject: [PATCH 184/202] [GR-13976] Support marshal.dumps and marshal.loads for PCode --- .../src/tests/test_marshal.py | 172 +++++ .../modules/MarshalModuleBuiltins.java | 603 +++++++++++++++++- mx.graalpython/copyrights/overrides | 1 + 3 files changed, 769 insertions(+), 7 deletions(-) create mode 100644 graalpython/com.oracle.graal.python.test/src/tests/test_marshal.py diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_marshal.py b/graalpython/com.oracle.graal.python.test/src/tests/test_marshal.py new file mode 100644 index 0000000000..2255d80a57 --- /dev/null +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_marshal.py @@ -0,0 +1,172 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# Copyright (C) 1996-2017 Python Software Foundation +# +# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 + +import unittest +import marshal +import array +import types +import sys + +class BaseMarshalUnmarshal: + def helper(self, sample, *extra): + new = marshal.loads(marshal.dumps(sample, *extra)) + self.assertEqual(sample, new) + +class IntTest (unittest.TestCase, BaseMarshalUnmarshal): + + def test_ints(self): + # Test a range of Python ints larger than the machine word size. + n = sys.maxsize ** 20 + while n: + for expected in (-n, n): + self.helper(expected) + n = n >> 1 + + def test_int64(self): + # Simulate int marshaling with TYPE_INT64. + maxint64 = (1 << 63) - 1 + minint64 = -maxint64-1 + for base in maxint64, minint64, -maxint64, -(minint64 >> 1): + while base: + self.helper(base) + if base == -1: # a fixed-point for shifting right 1 + base = 0 + else: + base >>= 1 + + self.helper(0x1032547698badcfe) + self.helper(-0x1032547698badcff) + self.helper(0x7f6e5d4c3b2a1908) + self.helper(-0x7f6e5d4c3b2a1909) + + def test_bool(self): + for b in (True, False): + self.helper(b) + +class FloatTest(unittest.TestCase, BaseMarshalUnmarshal): + def test_floats(self): + # Test a few floats + small = 1e-25 + n = sys.maxsize * 3.7e250 + while n > small: + for expected in (-n, n): + self.helper(float(expected)) + n /= 123.4567 + + f = 0.0 + s = marshal.dumps(f, 2) + got = marshal.loads(s) + self.assertEqual(f, got) + # and with version <= 1 (floats marshalled differently then) + s = marshal.dumps(f, 1) + got = marshal.loads(s) + self.assertEqual(f, got) + + n = sys.maxsize * 3.7e-250 + while n < small: + for expected in (-n, n): + f = float(expected) + self.helper(f) + self.helper(f, 1) + n *= 123.4567 + +class StringTest(unittest.TestCase, BaseMarshalUnmarshal): + def test_unicode(self): + for s in ["", "Andr\xe8 Previn", "abc", " "*10000]: + self.helper(marshal.loads(marshal.dumps(s))) + + def test_string(self): + for s in ["", "Andr\xe8 Previn", "abc", " "*10000]: + self.helper(s) + + def test_bytes(self): + for s in [b"", b"Andr\xe8 Previn", b"abc", b" "*10000]: + self.helper(s) + +class ExceptionTest(unittest.TestCase): + + def test_exceptions(self): + new = marshal.loads(marshal.dumps(StopIteration)) + self.assertEqual(StopIteration, new) + +class CodeTest(unittest.TestCase): + + # TODO, currently the object created from serialized data is not equal. + #def test_code(self): + # co = ExceptionTest.test_exceptions.__code__ + # new = marshal.loads(marshal.dumps(co)) + # self.assertEqual(co, new) + + def test_many_codeobjects(self): + # Issue2957: bad recursion count on code objects + count = 5000 # more than MAX_MARSHAL_STACK_DEPTH + codes = (ExceptionTest.test_exceptions.__code__,) * count + marshal.loads(marshal.dumps(codes)) + + def test_different_filenames(self): + co1 = compile("x", "f1", "exec") + co2 = compile("y", "f2", "exec") + co1, co2 = marshal.loads(marshal.dumps((co1, co2))) + self.assertEqual(co1.co_filename, "f1") + self.assertEqual(co2.co_filename, "f2") + + def test_same_filename_used(self): + s = """def f(): pass\ndef g(): pass""" + co = compile(s, "myfile", "exec") + co = marshal.loads(marshal.dumps(co)) + for obj in co.co_consts: + if isinstance(obj, types.CodeType): + self.assertIs(co.co_filename, obj.co_filename) + +class ContainerTest(unittest.TestCase, BaseMarshalUnmarshal): + d = {'astring': 'foo@bar.baz.spam', + 'afloat': 7283.43, + 'anint': 2**20, + 'ashortlong': 2, + 'alist': ['.zyx.41'], + 'atuple': ('.zyx.41',)*10, + 'aboolean': False, + 'aunicode': "Andr\xe8 Previn" + } + + def test_dict(self): + self.helper(self.d) + + def test_list(self): + self.helper(list(self.d.items())) + + def test_tuple(self): + self.helper(tuple(self.d.keys())) + + def test_sets(self): + for constructor in (set, frozenset): + self.helper(constructor(self.d.keys())) + + # TODO enable this test, when GR-13961 and GR-13962 will be fixed + #def test_empty_frozenset_singleton(self): + # # marshal.loads() must reuse the empty frozenset singleton + # obj = frozenset() + # obj2 = marshal.loads(marshal.dumps(obj)) + # self.assertIs(obj2, obj) + +class BufferTest(unittest.TestCase, BaseMarshalUnmarshal): + + def test_bytearray(self): + b = bytearray(b"abc") + self.helper(b) + new = marshal.loads(marshal.dumps(b)) + self.assertEqual(type(new), bytes) + + def test_memoryview(self): + b = memoryview(b"abc") + #self.helper(b) + new = marshal.loads(marshal.dumps(b)) + self.assertEqual(type(new), bytes) + + ## TODO currently we don't support all the variation of arrays. + #def test_array(self): + # a = array.array('b', b"abc") + # new = marshal.loads(marshal.dumps(a)) + # self.assertEqual(new, b"abc") diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java index b11d46b16e..076ce5a805 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java @@ -26,18 +26,53 @@ package com.oracle.graal.python.builtins.modules; import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError; +import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError; import java.util.List; import com.oracle.graal.python.builtins.Builtin; import com.oracle.graal.python.builtins.CoreFunctions; +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.array.PArray; +import com.oracle.graal.python.builtins.objects.bytes.BytesNodes; +import com.oracle.graal.python.builtins.objects.bytes.PByteArray; +import com.oracle.graal.python.builtins.objects.bytes.PBytes; +import com.oracle.graal.python.builtins.objects.bytes.PIBytesLike; +import com.oracle.graal.python.builtins.objects.code.PCode; +import com.oracle.graal.python.builtins.objects.common.EconomicMapStorage; +import com.oracle.graal.python.builtins.objects.common.HashingStorage; +import com.oracle.graal.python.builtins.objects.common.HashingStorage.DictEntry; +import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; +import com.oracle.graal.python.builtins.objects.complex.PComplex; +import com.oracle.graal.python.builtins.objects.dict.PDict; +import com.oracle.graal.python.builtins.objects.floats.PFloat; +import com.oracle.graal.python.builtins.objects.ints.PInt; +import com.oracle.graal.python.builtins.objects.list.PList; +import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView; +import com.oracle.graal.python.builtins.objects.set.PFrozenSet; +import com.oracle.graal.python.builtins.objects.set.PSet; +import com.oracle.graal.python.builtins.objects.str.PString; +import com.oracle.graal.python.builtins.objects.tuple.PTuple; +import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; +import com.oracle.graal.python.nodes.PNodeWithContext; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; import com.oracle.graal.python.nodes.function.PythonBuiltinNode; +import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateNodeFactory; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.dsl.Specialization; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.HashMap; @CoreFunctions(defineModule = "marshal") public final class MarshalModuleBuiltins extends PythonBuiltins { @@ -59,12 +94,33 @@ Object doit(Object value, Object file, Object version) { @Builtin(name = "dumps", minNumOfPositionalArgs = 1, keywordArguments = {"version"}) @GenerateNodeFactory abstract static class DumpsNode extends PythonBuiltinNode { - @SuppressWarnings("unused") - @CompilerDirectives.TruffleBoundary + + private @Child MarshallerNode marshaller = MarshallerNode.create(); + + private byte[] dump(Object o, int version) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream buffer = new DataOutputStream(baos); + marshaller.resetRecursionDepth(); + marshaller.execute(o, version, buffer); + try { + buffer.flush(); + byte[] result = baos.toByteArray(); + baos.close(); + buffer.close(); + return result; + } catch (IOException e) { + throw raise(ValueError, "Was not possible to marshal %p", o); + } + } + @Specialization - Object doit(Object value, Object version) { - // TODO this is just fake implemention, which satisfy pip installer - return factory().createBytes(value.toString().getBytes()); + Object doit(Object value, int version) { + return factory().createBytes(dump(value, version)); + } + + @Specialization + Object doit(Object value, @SuppressWarnings("unused") PNone version) { + return factory().createBytes(dump(value, CURRENT_VERSION)); } } @@ -81,10 +137,543 @@ Object doit(Object file) { @Builtin(name = "loads", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory abstract static class LoadsNode extends PythonBuiltinNode { + + private @Child UnmarshallerNode marshaller = UnmarshallerNode.create(); + @SuppressWarnings("unused") @Specialization - Object doit(Object bytes) { - throw raise(NotImplementedError, "marshal.loads"); + Object doit(PBytes bytes, + @Cached("create()") BytesNodes.ToBytesNode toBytesNode) { + return marshaller.execute(toBytesNode.execute(bytes), CURRENT_VERSION); + } + + @SuppressWarnings("unused") + @Specialization + Object doit(PByteArray bytes, + @Cached("create()") BytesNodes.ToBytesNode toBytesNode) { + return marshaller.execute(toBytesNode.execute(bytes), CURRENT_VERSION); + } + } + + private final static char TYPE_NULL = '0'; + private final static char TYPE_NONE = 'N'; + private final static char TYPE_NOVALUE = 'n'; + private final static char TYPE_FALSE = 'F'; + private final static char TYPE_TRUE = 'T'; + private final static char TYPE_STOPITER = 'S'; + private final static char TYPE_ELLIPSIS = '.'; + private final static char TYPE_INT = 'i'; + private final static char TYPE_INT64 = 'I'; // just for backward compatibility with CPython + private final static char TYPE_FLOAT = 'f'; + // private final static char TYPE_BINARY_FLOAT = 'g'; + private final static char TYPE_COMPLEX = 'x'; + private final static char TYPE_BINARY_COMPLEX = 'y'; + private final static char TYPE_LONG = 'l'; + private final static char TYPE_PINT = 'L'; + private final static char TYPE_STRING = 's'; + // private final static char TYPE_INTERNED = 't'; + // private final static char TYPE_STRINGREF = 'R'; + private final static char TYPE_BYTESLIKE = 'b'; + private final static char TYPE_TUPLE = '('; + private final static char TYPE_LIST = '['; + private final static char TYPE_DICT = '{'; + private final static char TYPE_CODE = 'c'; + // private final static char TYPE_UNICODE = 'u'; + private final static char TYPE_UNKNOWN = '?'; + private final static char TYPE_SET = '<'; + private final static char TYPE_FROZENSET = '>'; + private final static int MAX_MARSHAL_STACK_DEPTH = 2000; + private final static int CURRENT_VERSION = 1; + + public static abstract class MarshallerNode extends PNodeWithContext { + + public abstract void execute(Object x, int version, DataOutputStream buffer); + + @Child private MarshallerNode recursiveNode; + private int depth = 0; + private IsBuiltinClassProfile isBuiltinProfile; + + protected MarshallerNode getRecursiveNode() { + if (recursiveNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + recursiveNode = insert(create()); + recursiveNode.depth += 1; + } + return recursiveNode; + } + + private void handleIOException(Object v) { + throw raise(ValueError, "Was not possible to marshal %p", v); + } + + public void resetRecursionDepth() { + depth = 0; + } + + @Specialization + public void writeByte(char v, @SuppressWarnings("unused") int version, DataOutputStream buffer) { + try { + buffer.write(v); + } catch (IOException e) { + handleIOException(v); + } + } + + private void writeBytes(byte[] bytes, int version, DataOutputStream buffer) { + int len = bytes.length; + writeInt(len, version, buffer); + try { + buffer.write(bytes); + } catch (IOException e) { + throw raise(ValueError, "Was not possible to marshal"); + } + } + + private void writeShort(short x, int version, DataOutputStream buffer) { + writeByte((char) (x & 0xff), version, buffer); + writeByte((char) ((x >> 8) & 0xff), version, buffer); + } + + private void writeInt(int v, @SuppressWarnings("unused") int version, DataOutputStream buffer) { + try { + buffer.writeInt(v); + } catch (IOException e) { + handleIOException(v); + } + } + + @Specialization + public void handleInt(int v, int version, DataOutputStream buffer) { + writeByte(TYPE_INT, version, buffer); + writeInt(v, version, buffer); + } + + private void writeLong(long v, int version, DataOutputStream buffer) { + writeInt((int) (v & 0xffffffff), version, buffer); + writeInt((int) ((v >> 32) & 0xffffffff), version, buffer); + } + + @Specialization + public void handleLong(long v, int version, DataOutputStream buffer) { + writeByte(TYPE_LONG, version, buffer); + writeLong(v, version, buffer); + } + + @Specialization + @TruffleBoundary + public void handlePInt(PInt v, int version, DataOutputStream buffer) { + writeByte(TYPE_PINT, version, buffer); + writeBytes(v.getValue().toByteArray(), version, buffer); + } + + private void writeDouble(double v, int version, DataOutputStream buffer) { + writeLong(Double.doubleToLongBits(v), version, buffer); + } + + @Specialization + public void handleFloat(float v, int version, DataOutputStream buffer) { + handleDouble(v, version, buffer); + } + + @Specialization + public void handleDouble(double v, int version, DataOutputStream buffer) { + writeByte(TYPE_FLOAT, version, buffer); + writeDouble(v, version, buffer); + } + + @Specialization + public void handlePFloat(PFloat v, int version, DataOutputStream buffer) { + handleDouble(v.getValue(), version, buffer); + } + + @Specialization + public void handlePComplex(PComplex v, int version, DataOutputStream buffer) { + writeByte(TYPE_COMPLEX, version, buffer); + writeDouble(v.getReal(), version, buffer); + writeDouble(v.getImag(), version, buffer); + } + + @Specialization + public void writeBoolean(boolean v, int version, DataOutputStream buffer) { + if (v) { + writeByte(TYPE_TRUE, version, buffer); + } else { + writeByte(TYPE_FALSE, version, buffer); + } + } + + private void writeString(String v, int version, DataOutputStream buffer) { + byte[] bytes = v.getBytes(); + writeInt(bytes.length, version, buffer); + try { + buffer.write(bytes); + } catch (IOException e) { + handleIOException(v); + } + } + + @Specialization + public void handleString(String v, int version, DataOutputStream buffer) { + writeByte(TYPE_STRING, version, buffer); + writeString(v, version, buffer); + } + + @Specialization + public void handlePString(PString v, int version, DataOutputStream buffer) { + writeByte(TYPE_STRING, version, buffer); + writeString(v.getValue(), version, buffer); + } + + @Specialization + public void handleBytesLike(PIBytesLike v, int version, DataOutputStream buffer, + @Cached("create()") BytesNodes.ToBytesNode toBytesNode) { + writeByte(TYPE_BYTESLIKE, version, buffer); + writeBytes(toBytesNode.execute(v), version, buffer); + } + + @Specialization + public void handleMemoryView(PMemoryView v, int version, DataOutputStream buffer, + @Cached("create()") BytesNodes.ToBytesNode toBytesNode) { + writeByte(TYPE_BYTESLIKE, version, buffer); + writeBytes(toBytesNode.execute(v), version, buffer); + } + + @Specialization + public void handlePArray(PArray v, @SuppressWarnings("unused")int version, @SuppressWarnings("unused")DataOutputStream buffer) { + throw raise(NotImplementedError, "marshal.dumps(array)"); + } + + @Specialization + public void handlePTuple(PTuple t, int version, DataOutputStream buffer) { + writeByte(TYPE_TUPLE, version, buffer); + Object[] items = t.getArray(); + writeInt(items.length, version, buffer); + for (int i = 0; i < items.length; i++) { + getRecursiveNode().execute(items[i], version, buffer); + } + } + + @Specialization + public void handlePList(PList l, int version, DataOutputStream buffer) { + writeByte(TYPE_LIST, version, buffer); + Object[] items = l.getSequenceStorage().getInternalArray(); + writeInt(items.length, version, buffer); + for (int i = 0; i < items.length; i++) { + getRecursiveNode().execute(items[i], version, buffer); + } + } + + @Specialization + public void handlePDict(PDict d, int version, DataOutputStream buffer) { + writeByte(TYPE_DICT, version, buffer); + HashingStorage storage = d.getDictStorage(); + writeInt(storage.length(), version, buffer); + for (DictEntry entry : storage.entries()) { + getRecursiveNode().execute(entry.key, version, buffer); + getRecursiveNode().execute(entry.value, version, buffer); + } + } + + @Specialization + public void handlePCode(PCode c, int version, DataOutputStream buffer) { + writeByte(TYPE_CODE, version, buffer); + writeInt(c.getArgcount(), version, buffer); + writeInt(c.getKwonlyargcount(), version, buffer); + writeInt(c.getNlocals(), version, buffer); + writeInt(c.getStacksize(), version, buffer); + writeInt(c.getFlags(), version, buffer); + writeBytes(c.getCodestring() == null ? new byte[0] : c.getCodestring(), version, buffer); + getRecursiveNode().execute(factory().createTuple(c.getConstants() == null ? new Object[0] : c.getConstants()), version, buffer); + getRecursiveNode().execute(factory().createTuple(c.getNames() == null ? new Object[0] : c.getNames()), version, buffer); + getRecursiveNode().execute(factory().createTuple(c.getVarnames() == null ? new Object[0] : c.getVarnames()), version, buffer); + getRecursiveNode().execute(factory().createTuple(c.getFreeVars() == null ? new Object[0] : c.getFreeVars()), version, buffer); + getRecursiveNode().execute(factory().createTuple(c.getCellVars() == null ? new Object[0] : c.getCellVars()), version, buffer); + getRecursiveNode().execute(c.getFilename(), version, buffer); + getRecursiveNode().execute(c.getName(), version, buffer); + writeInt(c.getFirstLineNo(), version, buffer); + writeBytes(c.getLnotab() == null ? new byte[0] : c.getLnotab(), version, buffer); + } + + @Specialization + public void handlePSet(PSet s, int version, DataOutputStream buffer) { + writeByte(TYPE_SET, version, buffer); + HashingStorage dictStorage = s.getDictStorage(); + int len = dictStorage.length(); + writeInt(len, version, buffer); + for (DictEntry entry : dictStorage.entries()) { + getRecursiveNode().execute(entry.key, version, buffer); + } + } + + @Specialization + public void handlePForzenSet(PFrozenSet s, int version, DataOutputStream buffer) { + writeByte(TYPE_FROZENSET, version, buffer); + HashingStorage dictStorage = s.getDictStorage(); + int len = dictStorage.length(); + writeInt(len, version, buffer); + for (DictEntry entry : dictStorage.entries()) { + getRecursiveNode().execute(entry.key, version, buffer); + } + } + + @Specialization + public void handlePNone(PNone v, int version, DataOutputStream buffer) { + if (v == PNone.NONE) { + writeByte(TYPE_NONE, version, buffer); + } else if (v == PNone.NO_VALUE) { + writeByte(TYPE_NOVALUE, version, buffer); + } + } + + @Fallback + public void writeObject(Object v, int version, DataOutputStream buffer) { + if (depth >= MAX_MARSHAL_STACK_DEPTH) { + throw raise(ValueError, "Maximum marshal stack depth"); + } else if (v == null) { + writeByte(TYPE_NULL, version, buffer); + } else if (v == PNone.NONE) { + writeByte(TYPE_NONE, version, buffer); + } else if (v instanceof LazyPythonClass) { + if (isBuiltinProfile == null) { + isBuiltinProfile = IsBuiltinClassProfile.create(); + } + if (isBuiltinProfile.profileClass((LazyPythonClass) v, PythonBuiltinClassType.StopIteration)) { + writeByte(TYPE_STOPITER, version, buffer); + } else { + writeByte(TYPE_UNKNOWN, version, buffer); + } + } else if (v == PythonBuiltinClassType.PEllipsis) { + writeByte(TYPE_ELLIPSIS, version, buffer); + } else { + writeByte(TYPE_UNKNOWN, version, buffer); + } + depth--; + } + + public static MarshallerNode create() { + return MarshalModuleBuiltinsFactory.MarshallerNodeGen.create(); + } + } + + public static abstract class UnmarshallerNode extends PNodeWithContext { + public abstract Object execute(byte[] data, int version); + + @Child private HashingStorageNodes.SetItemNode setItemNode; + + private int index; + private byte[] data; + + public void reset() { + index = 0; + } + + private int readByte() { + return data[index++]; + } + + private int readInt() { + int ch1 = readByte() & 0xFF; + int ch2 = readByte() & 0xFF; + int ch3 = readByte() & 0xFF; + int ch4 = readByte() & 0xFF; + return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); + } + + private long read_long64() { // cpython calls this r_long64 + long lo4 = readInt(); + long hi4 = readInt(); + long x = (hi4 << 32) | (lo4 & 0xFFFFFFFFL); + return x; + } + + private PInt readPInt() { + byte[] bytes = readBytes(); + return factory().createInt(new BigInteger(bytes)); + } + + private double readDouble() { + long n = read_long64(); + return Double.longBitsToDouble(n); + } + + private String readString() { + int len = readInt(); + String text = new String(data, index, len); + index += len; + return text; + } + + private byte[] readBytes() { + int len = readInt(); + byte[] bytes = Arrays.copyOfRange(data, index, index + len); + index += len; + return bytes; + } + + private PBytes readBytesLike() { + byte[] bytes = readBytes(); + return factory().createBytes(bytes); + } + + private PCode readCode(int depth) { + int argcount = readInt(); + int kwonlyargcount = readInt(); + int nlocals = readInt(); + int stacksize = readInt(); + int flags = readInt(); + byte[] codestring = readBytes(); + Object[] constants = ((PTuple) readObject(depth + 1)).getArray(); + Object[] names = ((PTuple) readObject(depth + 1)).getArray(); + Object[] varnames = ((PTuple) readObject(depth + 1)).getArray(); + Object[] freevars = ((PTuple) readObject(depth + 1)).getArray(); + Object[] cellvars = ((PTuple) readObject(depth + 1)).getArray(); + String filename = ((String) readObject(depth + 1)); + String name = ((String) readObject(depth + 1)); + int firstlineno = readInt(); + byte[] lnotab = readBytes(); + + return factory().createCode(PythonBuiltinClassType.PCode, argcount, kwonlyargcount, + nlocals, stacksize, flags, codestring, constants, names, + varnames, freevars, cellvars, filename, name, firstlineno, lnotab); + } + + private PDict readDict(int depth) { + int len = readInt(); + HashMap map = new HashMap<>(len); + for (int i = 0; i < len; i++) { + Object key = readObject(depth + 1); + if (key == null) { + break; + } + Object value = readObject(depth + 1); + if (value != null) { + map.put(key, value); + } + } + return factory().createDict(map); + } + + private PList readList(int depth) { + int n = readInt(); + if (n < 0) { + throw raise(ValueError, "bad marshal data"); + } + Object items[] = new Object[n]; + for (int i = 0; i < n; i++) { + Object item = readObject(depth + 1); + if (item == null) { + throw raise(ValueError, "bad marshal data"); + } + items[i] = item; + } + return factory().createList(items); + } + + private PSet readSet(int depth) { + int n = readInt(); + if (n < 0) { + throw raise(ValueError, "bad marshal data"); + } + HashingStorage newStorage = EconomicMapStorage.create(n, true); + if (n > 0 && setItemNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setItemNode = insert(HashingStorageNodes.SetItemNode.create()); + } + for (int i = 0; i < n; i++) { + Object key = readObject(depth + 1); + setItemNode.execute(newStorage, key, PNone.NO_VALUE); + } + + return factory().createSet(newStorage); + } + + private PFrozenSet readFrozenSet(int depth) { + int n = readInt(); + if (n < 0) { + throw raise(ValueError, "bad marshal data"); + } + HashingStorage newStorage = EconomicMapStorage.create(n, true); + if (n > 0 && setItemNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setItemNode = insert(HashingStorageNodes.SetItemNode.create()); + } + for (int i = 0; i < n; i++) { + Object key = readObject(depth + 1); + setItemNode.execute(newStorage, key, PNone.NO_VALUE); + } + + return factory().createFrozenSet(newStorage); + } + + private Object readObject(int depth) { + if (depth >= MAX_MARSHAL_STACK_DEPTH) { + throw raise(ValueError, "Maximum marshal stack depth"); + } + int type = readByte(); + switch (type) { + case TYPE_NULL: + return null; + case TYPE_NONE: + return PNone.NONE; + case TYPE_NOVALUE: + return PNone.NO_VALUE; + case TYPE_STOPITER: + return getBuiltinPythonClass(PythonBuiltinClassType.StopIteration); + case TYPE_ELLIPSIS: + return PythonBuiltinClassType.PEllipsis; + case TYPE_FALSE: + return false; + case TYPE_TRUE: + return true; + case TYPE_INT: + return readInt(); + case TYPE_INT64: + return read_long64(); + case TYPE_LONG: + return read_long64(); + case TYPE_PINT: + return readPInt(); + case TYPE_FLOAT: + return readDouble(); + case TYPE_STRING: + return readString(); + case TYPE_BYTESLIKE: + return readBytesLike(); + case TYPE_TUPLE: { + int n = readInt(); + if (n < 0) { + throw raise(ValueError, "bad marshal data"); + } + Object items[] = new Object[n]; + for (int i = 0; i < n; i++) { + items[i] = readObject(depth + 1); + } + return factory().createTuple(items); + } + case TYPE_DICT: + return readDict(depth); + case TYPE_LIST: + return readList(depth); + case TYPE_SET: + return readSet(depth); + case TYPE_FROZENSET: + return readFrozenSet(depth); + case TYPE_CODE: + return readCode(depth); + default: + throw raise(ValueError, "bad marshal data"); + } + } + + @Specialization + public Object readObject(byte[] data, int version) { + reset(); + this.data = data; + return readObject(0); + } + + public static UnmarshallerNode create() { + return MarshalModuleBuiltinsFactory.UnmarshallerNodeGen.create(); } } } diff --git a/mx.graalpython/copyrights/overrides b/mx.graalpython/copyrights/overrides index 989cb03507..5b28a92167 100644 --- a/mx.graalpython/copyrights/overrides +++ b/mx.graalpython/copyrights/overrides @@ -237,6 +237,7 @@ graalpython/com.oracle.graal.python.test/src/tests/test_list.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_builtin.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_mandelbrot3.py,benchmarks.copyright graalpython/com.oracle.graal.python.test/src/tests/test_math.py,python.copyright +graalpython/com.oracle.graal.python.test/src/tests/test_marshal.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_memoryview.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_mm2d_naive.py,zippy.copyright graalpython/com.oracle.graal.python.test/src/tests/test_mm2d_random_naive_5.py,zippy.copyright From f7ee446090b45a1bb20b12d8879d413b1ced2e0c Mon Sep 17 00:00:00 2001 From: Petr Pisl Date: Tue, 19 Feb 2019 11:52:10 +0100 Subject: [PATCH 185/202] Style. --- .../modules/MarshalModuleBuiltins.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java index 076ce5a805..ab57ab9a18 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java @@ -167,7 +167,7 @@ Object doit(PByteArray bytes, private final static char TYPE_FLOAT = 'f'; // private final static char TYPE_BINARY_FLOAT = 'g'; private final static char TYPE_COMPLEX = 'x'; - private final static char TYPE_BINARY_COMPLEX = 'y'; + // private final static char TYPE_BINARY_COMPLEX = 'y'; private final static char TYPE_LONG = 'l'; private final static char TYPE_PINT = 'L'; private final static char TYPE_STRING = 's'; @@ -186,7 +186,7 @@ Object doit(PByteArray bytes, private final static int CURRENT_VERSION = 1; public static abstract class MarshallerNode extends PNodeWithContext { - + public abstract void execute(Object x, int version, DataOutputStream buffer); @Child private MarshallerNode recursiveNode; @@ -229,10 +229,10 @@ private void writeBytes(byte[] bytes, int version, DataOutputStream buffer) { } } - private void writeShort(short x, int version, DataOutputStream buffer) { - writeByte((char) (x & 0xff), version, buffer); - writeByte((char) ((x >> 8) & 0xff), version, buffer); - } +// private void writeShort(short x, int version, DataOutputStream buffer) { +// writeByte((char) (x & 0xff), version, buffer); +// writeByte((char) ((x >> 8) & 0xff), version, buffer); +// } private void writeInt(int v, @SuppressWarnings("unused") int version, DataOutputStream buffer) { try { @@ -339,7 +339,7 @@ public void handleMemoryView(PMemoryView v, int version, DataOutputStream buffer } @Specialization - public void handlePArray(PArray v, @SuppressWarnings("unused")int version, @SuppressWarnings("unused")DataOutputStream buffer) { + public void handlePArray(@SuppressWarnings("unused") PArray v, @SuppressWarnings("unused") int version, @SuppressWarnings("unused") DataOutputStream buffer) { throw raise(NotImplementedError, "marshal.dumps(array)"); } @@ -456,7 +456,7 @@ public static MarshallerNode create() { } public static abstract class UnmarshallerNode extends PNodeWithContext { - public abstract Object execute(byte[] data, int version); + public abstract Object execute(byte[] dataBytes, int version); @Child private HashingStorageNodes.SetItemNode setItemNode; @@ -666,9 +666,9 @@ private Object readObject(int depth) { } @Specialization - public Object readObject(byte[] data, int version) { + public Object readObject(byte[] dataBytes, @SuppressWarnings("unused") int version) { reset(); - this.data = data; + this.data = dataBytes; return readObject(0); } From a7c55cd6a59fdeb595e5e044072733aa0a2d5145 Mon Sep 17 00:00:00 2001 From: Petr Pisl Date: Tue, 19 Feb 2019 12:03:17 +0100 Subject: [PATCH 186/202] Adding @TruffleBoundary --- .../python/builtins/modules/MarshalModuleBuiltins.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java index ab57ab9a18..7359a0b267 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java @@ -229,10 +229,10 @@ private void writeBytes(byte[] bytes, int version, DataOutputStream buffer) { } } -// private void writeShort(short x, int version, DataOutputStream buffer) { -// writeByte((char) (x & 0xff), version, buffer); -// writeByte((char) ((x >> 8) & 0xff), version, buffer); -// } + // private void writeShort(short x, int version, DataOutputStream buffer) { + // writeByte((char) (x & 0xff), version, buffer); + // writeByte((char) ((x >> 8) & 0xff), version, buffer); + // } private void writeInt(int v, @SuppressWarnings("unused") int version, DataOutputStream buffer) { try { @@ -605,6 +605,7 @@ private PFrozenSet readFrozenSet(int depth) { return factory().createFrozenSet(newStorage); } + @TruffleBoundary private Object readObject(int depth) { if (depth >= MAX_MARSHAL_STACK_DEPTH) { throw raise(ValueError, "Maximum marshal stack depth"); From 43f4686d48a5a19c3c88c8287f7a9291c27169cd Mon Sep 17 00:00:00 2001 From: Petr Pisl Date: Tue, 19 Feb 2019 12:48:33 +0100 Subject: [PATCH 187/202] Adding @TruffleBoundary --- .../graal/python/builtins/modules/MarshalModuleBuiltins.java | 1 + 1 file changed, 1 insertion(+) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java index 7359a0b267..734c52fa79 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java @@ -97,6 +97,7 @@ abstract static class DumpsNode extends PythonBuiltinNode { private @Child MarshallerNode marshaller = MarshallerNode.create(); + @TruffleBoundary private byte[] dump(Object o, int version) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream buffer = new DataOutputStream(baos); From 24c67c97a4350428c73efafaf8e50eb1a875fb03 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 19 Feb 2019 16:46:52 +0100 Subject: [PATCH 188/202] update mx --- mx.graalpython/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index 925538ab2e..ed1a186f2e 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -4,7 +4,7 @@ # METADATA # # -------------------------------------------------------------------------------------------------------------- - "mxversion": "5.190.1", + "mxversion": "5.210.4", "name": "graalpython", "versionConflictResolution": "latest", From 6c0266b417a2aa54e30ce76b417f6485c3b41782 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Tue, 19 Feb 2019 17:10:02 +0100 Subject: [PATCH 189/202] fix pylint issues --- mx.graalpython/mx_graalpython.py | 28 ++++++++++++---------- mx.graalpython/mx_graalpython_benchmark.py | 4 ++-- mx.graalpython/suite.py | 12 ++++++---- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/mx.graalpython/mx_graalpython.py b/mx.graalpython/mx_graalpython.py index fa8c6960cf..75c78e5435 100644 --- a/mx.graalpython/mx_graalpython.py +++ b/mx.graalpython/mx_graalpython.py @@ -21,6 +21,8 @@ # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import print_function + import os import platform import re @@ -34,11 +36,10 @@ import mx_gate import mx_sdk import mx_subst -import mx_urlrewrites from mx_gate import Task from mx_graalpython_bench_param import PATH_MESO, BENCHMARKS from mx_graalpython_benchmark import PythonBenchmarkSuite, python_vm_registry, CPythonVm, PyPyVm, GraalPythonVm, \ - CONFIGURATION_DEFAULT, CONFIGURATION_EXPERIMENTAL_SPLITTING, CONFIGURATION_SANDBOXED + CONFIGURATION_DEFAULT, CONFIG_EXPERIMENTAL_SPLITTING, CONFIGURATION_SANDBOXED from mx_unittest import unittest SUITE = mx.suite('graalpython') @@ -161,7 +162,7 @@ def punittest(args): # IMPORTANT! This must not be --suite graalpython, because a # --dynamicimports sulong will otherwise not put sulong.jar on the # classpath, which means we cannot run our C extension tests! - unittest(args + ['--regex', '(graal\.python)|(com\.oracle\.truffle\.tck\.tests)', "-Dgraal.TraceTruffleCompilation=true"]) + unittest(args + ['--regex', r'(graal\.python)|(com\.oracle\.truffle\.tck\.tests)', "-Dgraal.TraceTruffleCompilation=true"]) def nativebuild(args): @@ -247,7 +248,8 @@ def python_svm(args): return svm_image -def gate_unittests(args=[], subdir=""): +def gate_unittests(args=None, subdir=""): + args = args or [] _graalpytest_driver = "graalpython/com.oracle.graal.python.test/src/graalpytest.py" _test_project = "graalpython/com.oracle.graal.python.test/" for idx, arg in enumerate(args): @@ -273,7 +275,9 @@ def gate_unittests(args=[], subdir=""): mx.command_function("python")(["--python.CatchAllExceptions=true", "--python.OpaqueFilesystem"] + pre_args + test_args + post_args) -def run_python_unittests(python_binary, args=[], aot_compatible=True, exclude=[]): +def run_python_unittests(python_binary, args=None, aot_compatible=True, exclude=None): + args = args or [] + exclude = exclude or [] # tests root directory tests_folder = os.path.join(SUITE.dir, "graalpython", "com.oracle.graal.python.test", "src", "tests") @@ -602,7 +606,7 @@ def update_import(name, rev="origin/master", callback=None): suitefile = os.path.join(primary.dir, "mx." + primary.name, "suite.py") with open(suitefile, 'r') as f: contents = f.read() - dep_re = re.compile("['\"]name['\"]:\s+['\"]%s['\"],\s+['\"]version['\"]:\s+['\"]([a-z0-9]+)['\"]" % name, re.MULTILINE) + dep_re = re.compile(r"['\"]name['\"]:\s+['\"]%s['\"],\s+['\"]version['\"]:\s+['\"]([a-z0-9]+)['\"]" % name, re.MULTILINE) dep_match = dep_re.search(contents) if dep_match: start = dep_match.start(1) @@ -620,7 +624,7 @@ def update_import_cmd(args): callback = None if name == "sulong": join = os.path.join - callback=lambda: shutil.copy( + callback = lambda: shutil.copy( join(SUITE_SULONG.dir, "include", "truffle.h"), join(SUITE.dir, "graalpython", "com.oracle.graal.python.cext", "include", "truffle.h") ) and shutil.copy( @@ -676,7 +680,7 @@ def import_python_sources(args): pypy_sources = args.pypy import_version = args.msg - print """ + print(""" So you think you want to update the inlined sources? Here is how it will go: 1. We'll first check the copyrights check overrides file to identify the @@ -717,7 +721,7 @@ def import_python_sources(args): python-import. 7. Run the tests and fix any remaining issues. - """.format(mapping) + """.format(mapping)) raw_input("Got it?") cpy_files = [] @@ -743,7 +747,7 @@ def import_python_sources(args): if name.startswith("test_") or name.endswith("_tests.py"): original_file = inlined_file else: - for root, dirs, files in os.walk(pypy_sources): + for root, _, files in os.walk(pypy_sources): if os.path.basename(name) in files: original_file = os.path.join(root, name) try: @@ -761,7 +765,7 @@ def import_python_sources(args): name = os.path.basename(inlined_file) name = mapping.get(name, name) if inlined_file.endswith(".h") or inlined_file.endswith(".c"): - for root, dirs, files in os.walk(python_sources): + for root, _, files in os.walk(python_sources): if os.path.basename(name) in files: original_file = os.path.join(root, name) try: @@ -846,7 +850,7 @@ def _register_vms(namespace): python_vm_registry.add_vm(CPythonVm(CONFIGURATION_DEFAULT), SUITE) python_vm_registry.add_vm(PyPyVm(CONFIGURATION_DEFAULT), SUITE) python_vm_registry.add_vm(GraalPythonVm(config_name=CONFIGURATION_DEFAULT), SUITE, 10) - python_vm_registry.add_vm(GraalPythonVm(config_name=CONFIGURATION_EXPERIMENTAL_SPLITTING, extra_vm_args=[ + python_vm_registry.add_vm(GraalPythonVm(config_name=CONFIG_EXPERIMENTAL_SPLITTING, extra_vm_args=[ '-Dgraal.TruffleExperimentalSplitting=true', '-Dgraal.TruffleExperimentalSplittingAllowForcedSplits=false' ]), SUITE, 10) diff --git a/mx.graalpython/mx_graalpython_benchmark.py b/mx.graalpython/mx_graalpython_benchmark.py index a4c604eb9e..5e35b4d0ce 100644 --- a/mx.graalpython/mx_graalpython_benchmark.py +++ b/mx.graalpython/mx_graalpython_benchmark.py @@ -55,7 +55,7 @@ SUBGROUP_GRAAL_PYTHON = "graalpython" PYTHON_VM_REGISTRY_NAME = "Python" CONFIGURATION_DEFAULT = "default" -CONFIGURATION_EXPERIMENTAL_SPLITTING = "experimental_splitting" +CONFIG_EXPERIMENTAL_SPLITTING = "experimental_splitting" CONFIGURATION_SANDBOXED = "sandboxed" DEFAULT_ITERATIONS = 10 @@ -132,7 +132,7 @@ def __init__(self, config_name, options=None, iterations=None): super(AbstractPythonIterationsControlVm, self).__init__(config_name, options) try: self._iterations = int(iterations) - except Exception: + except: self._iterations = None def _override_iterations_args(self, args): diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index ed1a186f2e..50a054a654 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -1,3 +1,4 @@ +# pylint: disable=anomalous-backslash-in-string suite = { # -------------------------------------------------------------------------------------------------------------- # @@ -163,7 +164,8 @@ "sdk:GRAAL_SDK", "sdk:LAUNCHER_COMMON", ], - "javaCompliance": "1.8", + "javaCompliance": "8+", + "checkstyle": "com.oracle.graal.python", }, # GRAALPYTHON @@ -177,8 +179,8 @@ "regex:TREGEX", ], "buildDependencies": ["com.oracle.graal.python.parser.antlr"], - "checkstyle": "com.oracle.graal.python", - "javaCompliance": "1.8", + "javaCompliance" : "8+", + "checkstyleVersion" : "8.8", "annotationProcessors": ["truffle:TRUFFLE_DSL_PROCESSOR"], "workingSets": "Truffle,Python", }, @@ -194,7 +196,7 @@ "mx:JUNIT" ], "checkstyle": "com.oracle.graal.python", - "javaCompliance": "1.8", + "javaCompliance": "8+", "annotationProcessors": ["truffle:TRUFFLE_DSL_PROCESSOR"], "workingSets": "Truffle,Python", "testProject": True, @@ -208,7 +210,7 @@ "mx:JUNIT" ], "checkstyle": "com.oracle.graal.python", - "javaCompliance": "1.8", + "javaCompliance": "8+", "workingSets": "Truffle,Python", "testProject": True, }, From 8584197a71b74e1783524fb7e79453e198681004 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 20 Feb 2019 09:20:27 +0100 Subject: [PATCH 190/202] fix possible NPE --- .../src/com/oracle/graal/python/shell/GraalPythonLD.java | 6 ++++-- .../src/com/oracle/graal/python/PythonFileDetector.java | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonLD.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonLD.java index 3f9f8c02cf..935f9703e0 100644 --- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonLD.java +++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonLD.java @@ -108,7 +108,8 @@ private void parseOptions(String[] args) { List bcFiles = searchLib(libraryDirs, arg.substring(2)); for (String bcFile : bcFiles) { try { - if (Files.probeContentType(Paths.get(bcFile)).contains(LLVM_IR_BITCODE)) { + String contentType = Files.probeContentType(Paths.get(bcFile)); + if (contentType != null && contentType.contains(LLVM_IR_BITCODE)) { logV("library input:", bcFile); addFile(bcFile); } else { @@ -245,7 +246,8 @@ private Collection arMembers(String path) throws IOException, // seems ok to emulate this at least for the very common case of ar archives with symbol // definitions that overlap what's defined in explicitly include .o files outer: for (String f : members) { - if (Files.probeContentType(Paths.get(f)).contains(LLVM_IR_BITCODE)) { + String contentType = Files.probeContentType(Paths.get(f)); + if (contentType != null && contentType.contains(LLVM_IR_BITCODE)) { HashSet definedFuncs = new HashSet<>(); HashSet definedGlobals = new HashSet<>(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonFileDetector.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonFileDetector.java index 75e2763141..744b76bae8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonFileDetector.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonFileDetector.java @@ -47,7 +47,8 @@ public final class PythonFileDetector extends FileTypeDetector { @Override public String probeContentType(Path path) throws IOException { - if (path.getFileName().toString().endsWith(".py")) { + Path fileName = path.getFileName(); + if (fileName != null && fileName.toString().endsWith(".py")) { return PythonLanguage.MIME_TYPE; } return null; From 8fa6498fae205b2bd2f0969b2d5eb76c0f8ab73f Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 20 Feb 2019 09:20:32 +0100 Subject: [PATCH 191/202] ignore generated files in spotbugs --- mx.graalpython/suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index 50a054a654..de41197498 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -183,6 +183,7 @@ "checkstyleVersion" : "8.8", "annotationProcessors": ["truffle:TRUFFLE_DSL_PROCESSOR"], "workingSets": "Truffle,Python", + "spotbugsIgnoresGenerated" : True, }, # GRAALPYTHON TEST From 2c9f5fb36fabd775b8969bd2a1d308ac1ff84464 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 20 Feb 2019 09:52:09 +0100 Subject: [PATCH 192/202] add basic checkstyle and auto-fix autofixable issues --- .../graal/python/tck/PythonProvider.java | 2 +- .../oracle/graal/python/test/PythonTests.java | 21 +- .../.checkstyle_checks.xml | 206 ++++++++++++++++++ .../modules/BinasciiModuleBuiltins.java | 14 +- .../builtins/modules/BuiltinConstructors.java | 27 ++- .../builtins/modules/BuiltinFunctions.java | 18 +- .../modules/CodecsModuleBuiltins.java | 4 +- .../builtins/modules/MathModuleBuiltins.java | 30 +-- .../builtins/modules/PosixModuleBuiltins.java | 4 +- .../modules/PyExpatModuleBuiltins.java | 2 +- .../modules/SelectModuleBuiltins.java | 2 +- .../modules/SignalModuleBuiltins.java | 6 +- .../modules/SysConfigModuleBuiltins.java | 4 +- .../builtins/modules/SysModuleBuiltins.java | 12 +- .../builtins/modules/TimeModuleBuiltins.java | 25 ++- .../modules/UnicodeDataModuleBuiltins.java | 60 +++-- .../modules/WeakRefModuleBuiltins.java | 2 +- .../builtins/modules/ZLibModuleBuiltins.java | 4 +- .../builtins/objects/cext/CExtNodes.java | 6 +- .../cext/PySequenceArrayWrapperMR.java | 23 +- .../objects/complex/ComplexBuiltins.java | 48 ++-- .../builtins/objects/dict/PDictView.java | 10 +- .../objects/floats/FloatBuiltins.java | 6 +- .../builtins/objects/floats/PFloat.java | 8 +- .../foreign/TruffleObjectBuiltins.java | 2 +- .../function/AbstractFunctionBuiltins.java | 2 +- .../builtins/objects/ints/IntBuiltins.java | 12 +- .../builtins/objects/list/ListBuiltins.java | 6 +- .../memoryview/MemoryviewBuiltins.java | 2 +- .../objects/object/ObjectBuiltins.java | 6 +- .../builtins/objects/socket/PSocket.java | 12 +- .../objects/thread/AbstractPythonLock.java | 6 +- .../builtins/objects/thread/PThread.java | 2 +- .../builtins/objects/tuple/TupleBuiltins.java | 6 +- .../builtins/objects/type/TypeBuiltins.java | 28 +-- .../attributes/LookupAttributeInMRONode.java | 2 +- .../python/nodes/builtins/ListNodes.java | 2 +- .../python/nodes/cell/ReadLocalCellNode.java | 2 +- .../WriteGeneratorFrameVariableNode.java | 2 +- .../python/nodes/util/CastToDoubleNode.java | 2 +- .../graal/python/parser/LoopsBookKeeper.java | 6 +- .../graal/python/runtime/PythonContext.java | 4 +- .../runtime/formatting/StringFormatter.java | 1 + .../sequence/storage/SequenceStorage.java | 4 - 44 files changed, 451 insertions(+), 202 deletions(-) create mode 100644 graalpython/com.oracle.graal.python/.checkstyle_checks.xml diff --git a/graalpython/com.oracle.graal.python.tck/src/com/oracle/graal/python/tck/PythonProvider.java b/graalpython/com.oracle.graal.python.tck/src/com/oracle/graal/python/tck/PythonProvider.java index 36d9ae8998..c456fbc49b 100644 --- a/graalpython/com.oracle.graal.python.tck/src/com/oracle/graal/python/tck/PythonProvider.java +++ b/graalpython/com.oracle.graal.python.tck/src/com/oracle/graal/python/tck/PythonProvider.java @@ -317,7 +317,7 @@ private static Source createSource(String resourceName) throws IOException { return Source.newBuilder(ID, in, scriptName).build(); } - private static abstract class PResultVerifier implements ResultVerifier { + private abstract static class PResultVerifier implements ResultVerifier { } private static class PSequenceMultiplicationVerifier extends PResultVerifier { diff --git a/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/PythonTests.java b/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/PythonTests.java index d15d57defe..e4adc02e45 100644 --- a/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/PythonTests.java +++ b/graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/PythonTests.java @@ -74,10 +74,10 @@ public class PythonTests { } } - final static ByteArrayOutputStream errArray = new ByteArrayOutputStream(); - final static ByteArrayOutputStream outArray = new ByteArrayOutputStream(); - final static PrintStream errStream = new PrintStream(errArray); - final static PrintStream outStream = new PrintStream(outArray); + static final ByteArrayOutputStream errArray = new ByteArrayOutputStream(); + static final ByteArrayOutputStream outArray = new ByteArrayOutputStream(); + static final PrintStream errStream = new PrintStream(errArray); + static final PrintStream outStream = new PrintStream(outArray); private static Engine engine = Engine.newBuilder().out(PythonTests.outStream).err(PythonTests.errStream).build(); private static Context context = null; @@ -128,9 +128,9 @@ public static void assertBenchNoError(Path scriptName, String[] args) { final PrintStream printErrStream = new PrintStream(byteArrayErr); final PrintStream printOutStream = new PrintStream(byteArrayOut); File source = getBenchFile(scriptName); - if (args == null) + if (args == null) { PythonTests.runScript(new String[]{source.toString()}, source, printOutStream, printErrStream); - else { + } else { args[0] = source.toString(); PythonTests.runScript(args, source, printOutStream, printErrStream); } @@ -236,8 +236,9 @@ static void flush(OutputStream out, OutputStream err) { public static File getBenchFile(Path filename) { Path path = Paths.get(GraalPythonEnvVars.graalpythonHome(), "benchmarks", "src"); - if (!Files.isDirectory(path)) + if (!Files.isDirectory(path)) { throw new RuntimeException("Unable to locate benchmarks/src/"); + } Path fullPath = Paths.get(path.toString(), filename.toString()); if (!Files.isReadable(fullPath)) { @@ -261,8 +262,9 @@ private static String getFileContent(File file) { int n = 0; while (n != -1) { n = bufferedReader.read(buffer); - if (n != -1) + if (n != -1) { content.append(buffer, 0, n); + } } } finally { bufferedReader.close(); @@ -307,8 +309,9 @@ public static File getTestFile(Path filename) { Path path = Paths.get(GraalPythonEnvVars.graalpythonHome(), "com.oracle.graal.python.test", "src", "tests", filename.toString()); if (Files.isReadable(path)) { return new File(path.toString()); - } else + } else { throw new RuntimeException("Unable to locate " + path); + } } public static void runScript(String[] args, File path, OutputStream out, OutputStream err) { diff --git a/graalpython/com.oracle.graal.python/.checkstyle_checks.xml b/graalpython/com.oracle.graal.python/.checkstyle_checks.xml new file mode 100644 index 0000000000..794c8d998c --- /dev/null +++ b/graalpython/com.oracle.graal.python/.checkstyle_checks.xml @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java index 364825de37..f6e56149b9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BinasciiModuleBuiltins.java @@ -104,7 +104,7 @@ public void initialize(PythonCore core) { @Builtin(name = "a2b_base64", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - static abstract class A2bBase64Node extends PythonUnaryBuiltinNode { + abstract static class A2bBase64Node extends PythonUnaryBuiltinNode { @Specialization PBytes doString(String data) { return factory().createBytes(b64decode(data)); @@ -133,7 +133,7 @@ private byte[] b64decode(byte[] data) { @Builtin(name = "a2b_hex", fixedNumOfPositionalArgs = 2, declaresExplicitSelf = true) @GenerateNodeFactory - static abstract class A2bHexNode extends PythonBinaryBuiltinNode { + abstract static class A2bHexNode extends PythonBinaryBuiltinNode { private ReadAttributeFromObjectNode getAttrNode; private PException raise(LazyPythonClass klass, String string) { @@ -178,7 +178,7 @@ private ReadAttributeFromObjectNode getAttrNode() { @Builtin(name = "b2a_base64", fixedNumOfPositionalArgs = 1, keywordArguments = {"newline"}) @TypeSystemReference(PythonArithmeticTypes.class) @GenerateNodeFactory - static abstract class B2aBase64Node extends PythonBinaryBuiltinNode { + abstract static class B2aBase64Node extends PythonBinaryBuiltinNode { @Child private SequenceStorageNodes.ToByteArrayNode toByteArray; @Child private CastToIntegerFromIntNode castToIntNode; @@ -298,7 +298,7 @@ PBytes b2sGeneral(Object data, @SuppressWarnings("unused") Object newline) { @Builtin(name = "b2a_hex", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - static abstract class B2aHexNode extends PythonUnaryBuiltinNode { + abstract static class B2aHexNode extends PythonUnaryBuiltinNode { @Specialization @TruffleBoundary String b2a(PBytes data, @@ -318,7 +318,7 @@ String b2a(PBytes data, @Builtin(name = "crc32", fixedNumOfPositionalArgs = 1, keywordArguments = "crc") @GenerateNodeFactory - static abstract class Crc32Node extends PythonBinaryBuiltinNode { + abstract static class Crc32Node extends PythonBinaryBuiltinNode { @Specialization(guards = "isNoValue(crc)") @TruffleBoundary long b2a(PBytes data, @SuppressWarnings("unused") PNone crc, @@ -332,11 +332,11 @@ long b2a(PBytes data, @SuppressWarnings("unused") PNone crc, @Builtin(name = "hexlify", fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - static abstract class HexlifyNode extends B2aHexNode { + abstract static class HexlifyNode extends B2aHexNode { } @Builtin(name = "unhexlify", fixedNumOfPositionalArgs = 2, declaresExplicitSelf = true) @GenerateNodeFactory - static abstract class UnhexlifyNode extends A2bHexNode { + abstract static class UnhexlifyNode extends A2bHexNode { } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java index f7f13d13b3..e422af90c4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java @@ -1499,36 +1499,41 @@ public PSequence rangeStartStopStep(Object cls, long start, long stop, long step public PSequence rangeStartStopStep(Object cls, Object start, Object stop, Object step) { if (isNumber(stop)) { int intStop = 0; - if (stop instanceof Integer) + if (stop instanceof Integer) { intStop = (int) stop; - else if (stop instanceof Long) + } else if (stop instanceof Long) { intStop = ((Long) (stop)).intValue(); - else + } else { intStop = ((PInt) stop).intValue(); + } - if (start instanceof PNone) + if (start instanceof PNone) { return factory().createRange(intStop); + } if (isNumber(start)) { int intStart = 0; - if (start instanceof Integer) + if (start instanceof Integer) { intStart = (int) start; - else if (start instanceof Long) + } else if (start instanceof Long) { intStart = ((Long) (start)).intValue(); - else + } else { intStart = ((PInt) start).intValue(); + } - if (step instanceof PNone) + if (step instanceof PNone) { return factory().createRange(intStart, intStop); + } if (isNumber(step)) { int intStep = 0; - if (step instanceof Integer) + if (step instanceof Integer) { intStep = (int) step; - else if (step instanceof Long) + } else if (step instanceof Long) { intStep = ((Long) (step)).intValue(); - else + } else { intStep = ((PInt) step).intValue(); + } return factory().createRange(intStart, intStop, intStep); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java index f49b35f233..bc00ee8eba 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java @@ -928,7 +928,7 @@ public abstract static class IdNode extends PythonBuiltinNode { * None, NotImplemented, True, False * */ - private static long KNOWN_OBJECTS_COUNT = 4L; + private static final long KNOWN_OBJECTS_COUNT = 4L; // borrowed logic from pypy // -1 - (-maxunicode-1): unichar // 0 - 255: char @@ -936,12 +936,12 @@ public abstract static class IdNode extends PythonBuiltinNode { // 257: empty unicode // 258: empty tuple // 259: empty frozenset - private static long BASE_EMPTY_BYTES = 256; - private static long BASE_EMPTY_UNICODE = 257; - private static long BASE_EMPTY_TUPLE = 258; - private static long BASE_EMPTY_FROZENSET = 259; - private static long IDTAG_SPECIAL = 11; - private static int IDTAG_SHIFT = 4; + private static final long BASE_EMPTY_BYTES = 256; + private static final long BASE_EMPTY_UNICODE = 257; + private static final long BASE_EMPTY_TUPLE = 258; + private static final long BASE_EMPTY_FROZENSET = 259; + private static final long IDTAG_SPECIAL = 11; + private static final int IDTAG_SHIFT = 4; /** * The next available global id. We reserve space for all integers to be their own id + @@ -1227,7 +1227,7 @@ public Object iter(Object callable, Object sentinel) { @GenerateNodeFactory public abstract static class LenNode extends PythonUnaryBuiltinNode { - private static Supplier NO_LEN = () -> new NoAttributeHandler() { + private static final Supplier NO_LEN = () -> new NoAttributeHandler() { @Override public Object execute(Object receiver) { throw raise(TypeError, "object of type '%p' has no len()", receiver); @@ -1735,7 +1735,7 @@ public abstract static class BuiltinNode extends PythonUnaryBuiltinNode { @Specialization @TruffleBoundary - synchronized public Object doIt(PFunction func) { + public synchronized Object doIt(PFunction func) { /* * (tfel): To be compatible with CPython, builtin module functions must be bound to * their respective builtin module. We ignore that builtin functions should really be diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CodecsModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CodecsModuleBuiltins.java index 3777f32b41..5c3c6d766b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CodecsModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CodecsModuleBuiltins.java @@ -81,10 +81,10 @@ @CoreFunctions(defineModule = "_codecs") public class CodecsModuleBuiltins extends PythonBuiltins { - public static String DEFAULT_ENCODING = "utf-8"; + public static final String DEFAULT_ENCODING = "utf-8"; // python to java codecs mapping - private static Map PY_CODECS_ALIASES = new HashMap<>(); + private static final Map PY_CODECS_ALIASES = new HashMap<>(); static { // ascii PY_CODECS_ALIASES.put("us-ascii", "us-ascii"); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java index ef02595737..154f61e398 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java @@ -341,7 +341,7 @@ public double copySignOO(Object magnitude, Object sign, @GenerateNodeFactory public abstract static class FactorialNode extends PythonUnaryBuiltinNode { - @CompilationFinal(dimensions = 1) protected final static long[] SMALL_FACTORIALS = new long[]{ + @CompilationFinal(dimensions = 1) protected static final long[] SMALL_FACTORIALS = new long[]{ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800L, 87178291200L, 1307674368000L, @@ -795,8 +795,8 @@ public boolean isinf(Object value, @ImportStatic(MathGuards.class) @GenerateNodeFactory public abstract static class IsCloseNode extends PythonBuiltinNode { - private static double DEFAULT_REL = 1e-09; - private static double DEFAULT_ABS = 0.0; + private static final double DEFAULT_REL = 1e-09; + private static final double DEFAULT_ABS = 0.0; @Child private CastToDoubleNode castANode; @Child private CastToDoubleNode castBNode; @@ -1134,8 +1134,9 @@ public double doIt(Object iterable, hi = x + y; yr = hi - x; lo = y - yr; - if (lo != 0.0) + if (lo != 0.0) { break; + } } /* * Make half-even rounding work across multiple partials. Needed so that sum([1e-16, @@ -2105,9 +2106,9 @@ public double count(double x) { return x; } absx = Math.abs(x); - if (absx < ERF_SERIES_CUTOFF) + if (absx < ERF_SERIES_CUTOFF) { return m_erf_series(x); - else { + } else { cf = m_erfc_contfrac(absx); return x > 0.0 ? 1.0 - cf : cf - 1.0; } @@ -2127,9 +2128,9 @@ public double count(double x) { return x; } absx = Math.abs(x); - if (absx < ErfNode.ERF_SERIES_CUTOFF) + if (absx < ErfNode.ERF_SERIES_CUTOFF) { return 1.0 - m_erf_series(x); - else { + } else { cf = m_erfc_contfrac(absx); return x > 0.0 ? cf : 2.0 - cf; } @@ -2144,7 +2145,7 @@ public abstract static class GammaNode extends MathDoubleUnaryBuiltinNode { private static final int LANCZOS_N = 13; protected static final double LANCZOS_G = 6.024680040776729583740234375; private static final double LANZOS_G_MINUS_HALF = 5.524680040776729583740234375; - @CompilationFinal(dimensions = 1) protected final static double[] LANCZOS_NUM_COEFFS = new double[]{ + @CompilationFinal(dimensions = 1) protected static final double[] LANCZOS_NUM_COEFFS = new double[]{ 23531376880.410759688572007674451636754734846804940, 42919803642.649098768957899047001988850926355848959, 35711959237.355668049440185451547166705960488635843, @@ -2160,11 +2161,11 @@ public abstract static class GammaNode extends MathDoubleUnaryBuiltinNode { 2.5066282746310002701649081771338373386264310793408 }; - @CompilationFinal(dimensions = 1) protected final static double[] LANCZOS_DEN_COEFFS = new double[]{ + @CompilationFinal(dimensions = 1) protected static final double[] LANCZOS_DEN_COEFFS = new double[]{ 0.0, 39916800.0, 120543840.0, 150917976.0, 105258076.0, 45995730.0, 13339535.0, 2637558.0, 357423.0, 32670.0, 1925.0, 66.0, 1.0}; - @CompilationFinal(dimensions = 1) protected final static double[] GAMMA_INTEGRAL = new double[]{ + @CompilationFinal(dimensions = 1) protected static final double[] GAMMA_INTEGRAL = new double[]{ 1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0, 479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0, 355687428096000.0, @@ -2239,9 +2240,9 @@ public double count(double x) { /* special cases */ if (!Double.isFinite(x)) { - if (Double.isNaN(x) || x > 0.0) + if (Double.isNaN(x) || x > 0.0) { return x; /* tgamma(nan) = nan, tgamma(inf) = inf */ - else { + } else { checkMathDomainError(false); } } @@ -2250,8 +2251,9 @@ public double count(double x) { /* integer arguments */ if (x == Math.floor(x)) { checkMathDomainError(x < 0.0); - if (x <= NGAMMA_INTEGRAL) + if (x <= NGAMMA_INTEGRAL) { return GAMMA_INTEGRAL[(int) x - 1]; + } } absx = Math.abs(x); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java index 1bea44753e..c8a151068c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java @@ -1653,7 +1653,7 @@ int getAndSetUmask(int umask) { @Builtin(name = "get_terminal_size", maxNumOfPositionalArgs = 1) @GenerateNodeFactory abstract static class GetTerminalSizeNode extends PythonUnaryBuiltinNode { - private final static String ERROR_MESSAGE = "[Errno 9] Bad file descriptor"; + private static final String ERROR_MESSAGE = "[Errno 9] Bad file descriptor"; @Child private CastToIntegerFromIntNode castIntNode; @Child private GetTerminalSizeNode recursiveNode; @@ -1767,7 +1767,7 @@ String readlink(String str, @SuppressWarnings("unused") PNone none) { @GenerateNodeFactory public abstract static class StrErrorNode extends PythonBuiltinNode { - private final static HashMap STR_ERROR_MAP = new HashMap<>(); + private static final HashMap STR_ERROR_MAP = new HashMap<>(); @Specialization String getStrError(int errno) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PyExpatModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PyExpatModuleBuiltins.java index 4646621a5b..6b601764d4 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PyExpatModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PyExpatModuleBuiltins.java @@ -152,7 +152,7 @@ public void initialize(PythonCore core) { @Builtin(name = "ParserCreate", keywordArguments = {"encoding", "namespace_separator", "intern"}, doc = "Return a new XML parser object.") @GenerateNodeFactory - static abstract class ParserCreateNode extends PythonTernaryBuiltinNode { + abstract static class ParserCreateNode extends PythonTernaryBuiltinNode { @SuppressWarnings("unused") @Specialization Object fail(Object encoding, Object namespace_separator, Object intern) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SelectModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SelectModuleBuiltins.java index 3af43d436d..09c0dd732f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SelectModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SelectModuleBuiltins.java @@ -64,7 +64,7 @@ protected List> getNodeFa @Builtin(name = "select", fixedNumOfPositionalArgs = 3, parameterNames = {"rlist", "wlist", "xlist"}, keywordArguments = {"timeout"}) @GenerateNodeFactory - static abstract class SelectNode extends PythonBuiltinNode { + abstract static class SelectNode extends PythonBuiltinNode { @Specialization @TruffleBoundary PTuple select(Object rlist, Object wlist, Object xlist, @SuppressWarnings("unused") Object timeout) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java index d2bc49cdf6..c6bae6f255 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java @@ -42,8 +42,8 @@ import static java.lang.StrictMath.toIntExact; -import java.util.Hashtable; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import com.oracle.graal.python.builtins.Builtin; @@ -73,9 +73,9 @@ @CoreFunctions(defineModule = "_signal") public class SignalModuleBuiltins extends PythonBuiltins { - private static Hashtable signalHandlers = new Hashtable<>(); + private static ConcurrentHashMap signalHandlers = new ConcurrentHashMap<>(); - private final static HiddenKey signalQueueKey = new HiddenKey("signalQueue"); + private static final HiddenKey signalQueueKey = new HiddenKey("signalQueue"); private final ConcurrentLinkedDeque signalQueue = new ConcurrentLinkedDeque<>(); @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysConfigModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysConfigModuleBuiltins.java index af414501c7..79c778463a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysConfigModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysConfigModuleBuiltins.java @@ -62,7 +62,7 @@ */ @CoreFunctions(defineModule = "_sysconfig") public class SysConfigModuleBuiltins extends PythonBuiltins { - private final static Map STATIC_CONFIG_OPTIONS = new HashMap<>(); + private static final Map STATIC_CONFIG_OPTIONS = new HashMap<>(); @Override public void initialize(PythonCore core) { @@ -77,7 +77,7 @@ protected List> getNodeFa @Builtin(name = "get_config_vars", takesVarArgs = true) @GenerateNodeFactory - static abstract class GetConfigVarsNode extends PythonBuiltinNode { + abstract static class GetConfigVarsNode extends PythonBuiltinNode { @Specialization PDict select(@SuppressWarnings("unused") Object[] arguments) { return factory().createDict(STATIC_CONFIG_OPTIONS); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java index fe01ed9054..241af1f2c6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java @@ -265,7 +265,7 @@ static String getPythonOSName() { @Builtin(name = "exc_info", fixedNumOfPositionalArgs = 0) @GenerateNodeFactory - public static abstract class ExcInfoNode extends PythonBuiltinNode { + public abstract static class ExcInfoNode extends PythonBuiltinNode { @Specialization public Object run( @Cached("create()") GetClassNode getClassNode) { @@ -283,7 +283,7 @@ public Object run( @Builtin(name = "_getframe", minNumOfPositionalArgs = 0, maxNumOfPositionalArgs = 1) @GenerateNodeFactory - public static abstract class GetFrameNode extends PythonUnaryBuiltinNode { + public abstract static class GetFrameNode extends PythonUnaryBuiltinNode { public static GetFrameNode create() { return GetFrameNodeFactory.create(); } @@ -377,7 +377,7 @@ private PException raiseCallStackDepth() { @Builtin(name = "getfilesystemencoding", fixedNumOfPositionalArgs = 0) @GenerateNodeFactory - public static abstract class GetFileSystemEncodingNode extends PythonBuiltinNode { + public abstract static class GetFileSystemEncodingNode extends PythonBuiltinNode { @Specialization protected String getFileSystemEncoding() { return System.getProperty("file.encoding"); @@ -386,7 +386,7 @@ protected String getFileSystemEncoding() { @Builtin(name = "getfilesystemencodeerrors", fixedNumOfPositionalArgs = 0) @GenerateNodeFactory - public static abstract class GetFileSystemEncodeErrorsNode extends PythonBuiltinNode { + public abstract static class GetFileSystemEncodeErrorsNode extends PythonBuiltinNode { @Specialization protected String getFileSystemEncoding() { return "surrogateescape"; @@ -412,7 +412,7 @@ PString doBytes(PString ps) { @Builtin(name = "getdefaultencoding", fixedNumOfPositionalArgs = 0) @GenerateNodeFactory - public static abstract class GetDefaultEncodingNode extends PythonBuiltinNode { + public abstract static class GetDefaultEncodingNode extends PythonBuiltinNode { @Specialization @TruffleBoundary protected String getFileSystemEncoding() { @@ -422,7 +422,7 @@ protected String getFileSystemEncoding() { @Builtin(name = "getsizeof", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2) @GenerateNodeFactory - public static abstract class GetsizeofNode extends PythonBinaryBuiltinNode { + public abstract static class GetsizeofNode extends PythonBinaryBuiltinNode { @Child private CastToIntegerFromIntNode castToIntNode = CastToIntegerFromIntNode.create(); @Specialization(guards = "isNoValue(dflt)") diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java index 64c867b45e..da2e267efc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java @@ -469,8 +469,9 @@ private String format(String format, PTuple date) { case 'I': // hour (01-12) j = items[3] % 12; - if (j == 0) + if (j == 0) { j = 12; // midnight or noon + } s = s + twoDigit(j); break; case 'j': @@ -489,10 +490,11 @@ private String format(String format, PTuple date) { // AM/PM j = items[3]; syms = datesyms.getAmPmStrings(); - if (0 <= j && j < 12) + if (0 <= j && j < 12) { s = s + syms[0]; - else if (12 <= j && j < 24) + } else if (12 <= j && j < 24) { s = s + syms[1]; + } break; case 'S': // seconds (00-61) @@ -505,14 +507,16 @@ else if (12 <= j && j < 24) // TODO this is not correct, CPython counts the week of year // from day of year item [8] - if (cal == null) + if (cal == null) { cal = getCalendar(items); + } cal.setFirstDayOfWeek(Calendar.SUNDAY); cal.setMinimalDaysInFirstWeek(7); j = cal.get(Calendar.WEEK_OF_YEAR); - if (cal.get(Calendar.MONTH) == Calendar.JANUARY && j >= 52) + if (cal.get(Calendar.MONTH) == Calendar.JANUARY && j >= 52) { j = 0; + } s = s + twoDigit(j); break; case 'w': @@ -528,14 +532,16 @@ else if (12 <= j && j < 24) // TODO this is not correct, CPython counts the week of year // from day of year item [8] - if (cal == null) + if (cal == null) { cal = getCalendar(items); + } cal.setFirstDayOfWeek(Calendar.MONDAY); cal.setMinimalDaysInFirstWeek(7); j = cal.get(Calendar.WEEK_OF_YEAR); - if (cal.get(Calendar.MONTH) == Calendar.JANUARY && j >= 52) + if (cal.get(Calendar.MONTH) == Calendar.JANUARY && j >= 52) { j = 0; + } s = s + twoDigit(j); break; case 'x': @@ -575,8 +581,9 @@ else if (12 <= j && j < 24) break; case 'Z': // timezone name - if (cal == null) + if (cal == null) { cal = getCalendar(items); + } // If items[8] == 1, we're in daylight savings time. // -1 means the information was not available; treat this as if not in dst. s = s + cal.getTimeZone().getDisplayName(items[8] > 0, 0); @@ -624,7 +631,7 @@ public String formatTime(Object format, @SuppressWarnings("unused") Object time) "time zones; instead the returned value will either be equal to that\n" + "of the timezone or altzone attributes on the time module.") @GenerateNodeFactory - static abstract class MkTimeNode extends PythonUnaryBuiltinNode { + abstract static class MkTimeNode extends PythonUnaryBuiltinNode { private static final int ELEMENT_COUNT = 9; @Child CastToIndexNode castInt = CastToIndexNode.create(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/UnicodeDataModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/UnicodeDataModuleBuiltins.java index 430da81319..5cb78962e5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/UnicodeDataModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/UnicodeDataModuleBuiltins.java @@ -72,65 +72,85 @@ public static String getUnicodeVersion() { // Preliminary Unicode 11 data obtained from // . - if (Character.getType('\u0560') != Character.UNASSIGNED) + if (Character.getType('\u0560') != Character.UNASSIGNED) { return "11.0.0"; // 11.0, June 2018. + } - if (Character.getType('\u0860') != Character.UNASSIGNED) + if (Character.getType('\u0860') != Character.UNASSIGNED) { return "10.0.0"; // 10.0, June 2017. + } - if (Character.getType('\u08b6') != Character.UNASSIGNED) + if (Character.getType('\u08b6') != Character.UNASSIGNED) { return "9.0.0"; // 9.0, June 2016. + } - if (Character.getType('\u08b3') != Character.UNASSIGNED) + if (Character.getType('\u08b3') != Character.UNASSIGNED) { return "8.0.0"; // 8.0, June 2015. + } - if (Character.getType('\u037f') != Character.UNASSIGNED) + if (Character.getType('\u037f') != Character.UNASSIGNED) { return "7.0.0"; // 7.0, June 2014. + } - if (Character.getType('\u061c') != Character.UNASSIGNED) + if (Character.getType('\u061c') != Character.UNASSIGNED) { return "6.3.0"; // 6.3, September 2013. + } - if (Character.getType('\u20ba') != Character.UNASSIGNED) + if (Character.getType('\u20ba') != Character.UNASSIGNED) { return "6.2.0"; // 6.2, September 2012. + } - if (Character.getType('\u058f') != Character.UNASSIGNED) + if (Character.getType('\u058f') != Character.UNASSIGNED) { return "6.1.0"; // 6.1, January 2012. + } - if (Character.getType('\u0526') != Character.UNASSIGNED) + if (Character.getType('\u0526') != Character.UNASSIGNED) { return "6.0.0"; // 6.0, October 2010. + } - if (Character.getType('\u0524') != Character.UNASSIGNED) + if (Character.getType('\u0524') != Character.UNASSIGNED) { return "5.2.0"; // 5.2, October 2009. + } - if (Character.getType('\u0370') != Character.UNASSIGNED) + if (Character.getType('\u0370') != Character.UNASSIGNED) { return "5.1.0"; // 5.1, March 2008. + } - if (Character.getType('\u0242') != Character.UNASSIGNED) + if (Character.getType('\u0242') != Character.UNASSIGNED) { return "5.0.0"; // 5.0, July 2006. + } - if (Character.getType('\u0237') != Character.UNASSIGNED) + if (Character.getType('\u0237') != Character.UNASSIGNED) { return "4.1.0"; // 4.1, March 2005. + } - if (Character.getType('\u0221') != Character.UNASSIGNED) + if (Character.getType('\u0221') != Character.UNASSIGNED) { return "4.0.0"; // 4.0, April 2003. + } - if (Character.getType('\u0220') != Character.UNASSIGNED) + if (Character.getType('\u0220') != Character.UNASSIGNED) { return "3.2.0"; // 3.2, March 2002. + } - if (Character.getType('\u03f4') != Character.UNASSIGNED) + if (Character.getType('\u03f4') != Character.UNASSIGNED) { return "3.1.0"; // 3.1, March 2001. + } - if (Character.getType('\u01f6') != Character.UNASSIGNED) + if (Character.getType('\u01f6') != Character.UNASSIGNED) { return "3.0.0"; // 3.0, September 1999. + } - if (Character.getType('\u20ac') != Character.UNASSIGNED) + if (Character.getType('\u20ac') != Character.UNASSIGNED) { return "2.1.0"; // 2.1, May 1998. + } - if (Character.getType('\u0591') != Character.UNASSIGNED) + if (Character.getType('\u0591') != Character.UNASSIGNED) { return "2.0.0"; // 2.0, July 1996. + } - if (Character.getType('\u0000') != Character.UNASSIGNED) + if (Character.getType('\u0000') != Character.UNASSIGNED) { return "1.1.0"; // 1.1, June 1993. + } return "1.0.0"; // 1.0 } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java index d911060e18..820ae3d139 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java @@ -78,7 +78,7 @@ @CoreFunctions(defineModule = "_weakref") public class WeakRefModuleBuiltins extends PythonBuiltins { - private final static HiddenKey weakRefQueueKey = new HiddenKey("weakRefQueue"); + private static final HiddenKey weakRefQueueKey = new HiddenKey("weakRefQueue"); private final ReferenceQueue weakRefQueue = new ReferenceQueue<>(); @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZLibModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZLibModuleBuiltins.java index 0ca4b9a159..a062f8847c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZLibModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZLibModuleBuiltins.java @@ -159,7 +159,7 @@ public abstract static class Crc32Node extends PythonBinaryBuiltinNode { public abstract long execute(PIBytesLike data, Object value); // we can't use jdk Crc32 class, if there is done init value of crc - private final static int[] CRC32_TABLE = { + private static final int[] CRC32_TABLE = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, @@ -293,7 +293,7 @@ public abstract static class Adler32Node extends PythonBinaryBuiltinNode { public abstract long execute(PIBytesLike data, Object value); - private final static int DEFER = 3850; + private static final int DEFER = 3850; private static final int BASE = 65521; private static int computeAdler32(byte[] bytes, int value) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java index d9f96eb98c..0baf932ca8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java @@ -1431,7 +1431,7 @@ public List> getExecutionSignature() { } @Builtin(fixedNumOfPositionalArgs = 1) - public static abstract class MayRaiseUnaryNode extends PythonUnaryBuiltinNode { + public abstract static class MayRaiseUnaryNode extends PythonUnaryBuiltinNode { @Child private CreateArgumentsNode createArgsNode; @Child private InvokeNode invokeNode; private final Object errorResult; @@ -1457,7 +1457,7 @@ Object doit(Object argument) { } @Builtin(fixedNumOfPositionalArgs = 2) - public static abstract class MayRaiseBinaryNode extends PythonBinaryBuiltinNode { + public abstract static class MayRaiseBinaryNode extends PythonBinaryBuiltinNode { @Child private CreateArgumentsNode createArgsNode; @Child private InvokeNode invokeNode; private final Object errorResult; @@ -1483,7 +1483,7 @@ Object doit(Object arg1, Object arg2) { } @Builtin(fixedNumOfPositionalArgs = 3) - public static abstract class MayRaiseTernaryNode extends PythonTernaryBuiltinNode { + public abstract static class MayRaiseTernaryNode extends PythonTernaryBuiltinNode { @Child private CreateArgumentsNode createArgsNode; @Child private InvokeNode invokeNode; private final Object errorResult; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java index 9d7f4d50b6..3b4d7421eb 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PySequenceArrayWrapperMR.java @@ -192,20 +192,27 @@ long doBytesI64(@SuppressWarnings("unused") VirtualFrame frame, PIBytesLike byte private static long packLong(SequenceStorage store, SequenceStorageNodes.GetItemNode getItemNode, int len, int i) { long result = 0; result |= getItemNode.executeInt(store, i) & 0xFFL; - if (i + 1 < len) + if (i + 1 < len) { result |= ((long) getItemNode.executeInt(store, i + 1) << 8L) & 0xFF00L; - if (i + 2 < len) + } + if (i + 2 < len) { result |= ((long) getItemNode.executeInt(store, i + 2) << 16L) & 0xFF0000L; - if (i + 3 < len) + } + if (i + 3 < len) { result |= ((long) getItemNode.executeInt(store, i + 3) << 24L) & 0xFF000000L; - if (i + 4 < len) + } + if (i + 4 < len) { result |= ((long) getItemNode.executeInt(store, i + 4) << 32L) & 0xFF00000000L; - if (i + 5 < len) + } + if (i + 5 < len) { result |= ((long) getItemNode.executeInt(store, i + 5) << 40L) & 0xFF0000000000L; - if (i + 6 < len) + } + if (i + 6 < len) { result |= ((long) getItemNode.executeInt(store, i + 6) << 48L) & 0xFF000000000000L; - if (i + 7 < len) + } + if (i + 7 < len) { result |= ((long) getItemNode.executeInt(store, i + 7) << 56L) & 0xFF00000000000000L; + } return result; } @@ -553,7 +560,7 @@ public static GetTypeIDNode create() { } } - static abstract class ToNativeStorageNode extends PNodeWithContext { + abstract static class ToNativeStorageNode extends PNodeWithContext { @Child private StorageToNativeNode storageToNativeNode; public abstract NativeSequenceStorage execute(SequenceStorage object); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java index d25ff38520..9595aa76b9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java @@ -94,7 +94,7 @@ protected List> getNodeFa @GenerateNodeFactory @Builtin(name = __ABS__, fixedNumOfPositionalArgs = 1) - static abstract class AbsNode extends PythonBuiltinNode { + abstract static class AbsNode extends PythonBuiltinNode { @Specialization double abs(PComplex c) { double x = c.getReal(); @@ -228,7 +228,7 @@ static int getExponent(final double d) { @Builtin(name = __ADD__, fixedNumOfPositionalArgs = 2) @TypeSystemReference(PythonArithmeticTypes.class) @GenerateNodeFactory - static abstract class AddNode extends PythonBuiltinNode { + abstract static class AddNode extends PythonBuiltinNode { @Specialization PComplex doComplexLong(PComplex left, long right) { return factory().createComplex(left.getReal() + right, left.getImag()); @@ -259,13 +259,13 @@ PNotImplemented doComplex(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __RADD__, fixedNumOfPositionalArgs = 2) - static abstract class RAddNode extends AddNode { + abstract static class RAddNode extends AddNode { } @GenerateNodeFactory @Builtin(name = __TRUEDIV__, fixedNumOfPositionalArgs = 2) @TypeSystemReference(PythonArithmeticTypes.class) - static abstract class DivNode extends PythonBinaryBuiltinNode { + abstract static class DivNode extends PythonBinaryBuiltinNode { @Specialization PComplex doComplexDouble(PComplex left, double right) { double opNormSq = right * right; @@ -292,7 +292,7 @@ PNotImplemented doComplex(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __RTRUEDIV__, fixedNumOfPositionalArgs = 2) @TypeSystemReference(PythonArithmeticTypes.class) - static abstract class RDivNode extends PythonBinaryBuiltinNode { + abstract static class RDivNode extends PythonBinaryBuiltinNode { @Specialization PComplex doComplexDouble(PComplex right, double left) { double opNormSq = left * left; @@ -310,7 +310,7 @@ PNotImplemented doComplex(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __DIVMOD__, fixedNumOfPositionalArgs = 2) - static abstract class DivModNode extends PythonBinaryBuiltinNode { + abstract static class DivModNode extends PythonBinaryBuiltinNode { @Specialization @SuppressWarnings("unused") @@ -322,7 +322,7 @@ PComplex doComplexDouble(Object right, Object left) { @GenerateNodeFactory @Builtin(name = __MUL__, fixedNumOfPositionalArgs = 2) @TypeSystemReference(PythonArithmeticTypes.class) - static abstract class MulNode extends PythonBinaryBuiltinNode { + abstract static class MulNode extends PythonBinaryBuiltinNode { @Specialization PComplex doComplexDouble(PComplex left, double right) { return factory().createComplex(left.getReal() * right, left.getImag() * right); @@ -354,13 +354,13 @@ PNotImplemented doGeneric(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __RMUL__, fixedNumOfPositionalArgs = 2) - static abstract class RMulNode extends MulNode { + abstract static class RMulNode extends MulNode { } @GenerateNodeFactory @Builtin(name = __SUB__, fixedNumOfPositionalArgs = 2) @TypeSystemReference(PythonArithmeticTypes.class) - static abstract class SubNode extends PythonBinaryBuiltinNode { + abstract static class SubNode extends PythonBinaryBuiltinNode { @Specialization PComplex doComplexDouble(PComplex left, double right) { return factory().createComplex(left.getReal() - right, left.getImag()); @@ -381,7 +381,7 @@ PNotImplemented doComplex(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __EQ__, fixedNumOfPositionalArgs = 2) @TypeSystemReference(PythonArithmeticTypes.class) - static abstract class EqNode extends PythonBinaryBuiltinNode { + abstract static class EqNode extends PythonBinaryBuiltinNode { @Specialization boolean doComplex(PComplex left, PComplex right) { return left.equals(right); @@ -424,7 +424,7 @@ PNotImplemented doGeneric(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __GE__, fixedNumOfPositionalArgs = 2) - static abstract class GeNode extends PythonBinaryBuiltinNode { + abstract static class GeNode extends PythonBinaryBuiltinNode { @Specialization boolean doComplex(PComplex left, PComplex right) { return left.greaterEqual(right); @@ -439,7 +439,7 @@ PNotImplemented doGeneric(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __GT__, fixedNumOfPositionalArgs = 2) - static abstract class GtNode extends PythonBinaryBuiltinNode { + abstract static class GtNode extends PythonBinaryBuiltinNode { @Specialization boolean doComplex(PComplex left, PComplex right) { return left.greaterThan(right); @@ -454,7 +454,7 @@ PNotImplemented doGeneric(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __LT__, fixedNumOfPositionalArgs = 2) - static abstract class LtNode extends PythonBinaryBuiltinNode { + abstract static class LtNode extends PythonBinaryBuiltinNode { @Specialization boolean doComplex(PComplex left, PComplex right) { return left.lessThan(right); @@ -469,7 +469,7 @@ PNotImplemented doGeneric(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __LE__, fixedNumOfPositionalArgs = 2) - static abstract class LeNode extends PythonBinaryBuiltinNode { + abstract static class LeNode extends PythonBinaryBuiltinNode { @Specialization boolean doComplex(PComplex left, PComplex right) { return left.lessEqual(right); @@ -484,7 +484,7 @@ PNotImplemented doGeneric(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __NE__, fixedNumOfPositionalArgs = 2) - static abstract class NeNode extends PythonBinaryBuiltinNode { + abstract static class NeNode extends PythonBinaryBuiltinNode { @Specialization boolean doComplex(PComplex left, PComplex right) { return left.notEqual(right); @@ -499,7 +499,7 @@ PNotImplemented doGeneric(Object left, Object right) { @GenerateNodeFactory @Builtin(name = __REPR__, fixedNumOfPositionalArgs = 1) - static abstract class ReprNode extends PythonBuiltinNode { + abstract static class ReprNode extends PythonBuiltinNode { @Specialization @TruffleBoundary String repr(PComplex self) { @@ -509,7 +509,7 @@ String repr(PComplex self) { @GenerateNodeFactory @Builtin(name = __STR__, fixedNumOfPositionalArgs = 1) - static abstract class StrNode extends PythonBuiltinNode { + abstract static class StrNode extends PythonBuiltinNode { @Specialization String repr(PComplex self) { return self.toString(); @@ -518,7 +518,7 @@ String repr(PComplex self) { @GenerateNodeFactory @Builtin(name = __BOOL__, fixedNumOfPositionalArgs = 1) - static abstract class BoolNode extends PythonBuiltinNode { + abstract static class BoolNode extends PythonBuiltinNode { @Specialization boolean bool(PComplex self) { return self.getReal() != 0.0 || self.getImag() != 0.0; @@ -527,7 +527,7 @@ boolean bool(PComplex self) { @GenerateNodeFactory @Builtin(name = __NEG__, fixedNumOfPositionalArgs = 1) - static abstract class NegNode extends PythonBuiltinNode { + abstract static class NegNode extends PythonBuiltinNode { @Specialization PComplex neg(PComplex self) { return factory().createComplex(-self.getReal(), -self.getImag()); @@ -536,7 +536,7 @@ PComplex neg(PComplex self) { @GenerateNodeFactory @Builtin(name = __POS__, fixedNumOfPositionalArgs = 1) - static abstract class PosNode extends PythonBuiltinNode { + abstract static class PosNode extends PythonBuiltinNode { @Specialization PComplex pos(PComplex self) { return factory().createComplex(self.getReal(), self.getImag()); @@ -545,7 +545,7 @@ PComplex pos(PComplex self) { @GenerateNodeFactory @Builtin(name = __GETNEWARGS__, fixedNumOfPositionalArgs = 1) - static abstract class GetNewArgsNode extends PythonBuiltinNode { + abstract static class GetNewArgsNode extends PythonBuiltinNode { @Specialization PTuple get(PComplex self) { return factory().createTuple(new Object[]{self.getReal(), self.getImag()}); @@ -554,7 +554,7 @@ PTuple get(PComplex self) { @GenerateNodeFactory @Builtin(name = "real", fixedNumOfPositionalArgs = 1, isGetter = true, doc = "the real part of a complex number") - static abstract class RealNode extends PythonBuiltinNode { + abstract static class RealNode extends PythonBuiltinNode { @Specialization double get(PComplex self) { return self.getReal(); @@ -563,7 +563,7 @@ static abstract class RealNode extends PythonBuiltinNode { @GenerateNodeFactory @Builtin(name = "imag", fixedNumOfPositionalArgs = 1, isGetter = true, doc = "the imaginary part of a complex number") - static abstract class ImagNode extends PythonBuiltinNode { + abstract static class ImagNode extends PythonBuiltinNode { @Specialization double get(PComplex self) { return self.getImag(); @@ -572,7 +572,7 @@ static abstract class ImagNode extends PythonBuiltinNode { @GenerateNodeFactory @Builtin(name = __HASH__, fixedNumOfPositionalArgs = 1) - static abstract class HashNode extends PythonUnaryBuiltinNode { + abstract static class HashNode extends PythonUnaryBuiltinNode { @Specialization @TruffleBoundary int hash(PComplex self) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/PDictView.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/PDictView.java index 512a689eaf..a82670fa6c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/PDictView.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/PDictView.java @@ -68,13 +68,13 @@ public int size() { // the keys // // ----------------------------------------------------------------------------------------------------------------- - public final static class PDictKeysIterator extends PJavaIteratorIterator { + public static final class PDictKeysIterator extends PJavaIteratorIterator { public PDictKeysIterator(LazyPythonClass clazz, PHashingCollection dict) { super(clazz, dict.keys().iterator()); } } - public final static class PDictKeysView extends PDictView { + public static final class PDictKeysView extends PDictView { public PDictKeysView(LazyPythonClass clazz, PHashingCollection dict) { super(clazz, "dict_keys", dict); @@ -86,13 +86,13 @@ public PDictKeysView(LazyPythonClass clazz, PHashingCollection dict) { // the values // // ----------------------------------------------------------------------------------------------------------------- - public final static class PDictValuesIterator extends PJavaIteratorIterator { + public static final class PDictValuesIterator extends PJavaIteratorIterator { public PDictValuesIterator(LazyPythonClass clazz, PHashingCollection dict) { super(clazz, dict.items().iterator()); } } - public final static class PDictValuesView extends PDictView { + public static final class PDictValuesView extends PDictView { public PDictValuesView(LazyPythonClass clazz, PHashingCollection dict) { super(clazz, "dict_values", dict); @@ -104,7 +104,7 @@ public PDictValuesView(LazyPythonClass clazz, PHashingCollection dict) { // the items // // ----------------------------------------------------------------------------------------------------------------- - public final static class PDictItemsIterator extends PJavaIteratorIterator { + public static final class PDictItemsIterator extends PJavaIteratorIterator { public PDictItemsIterator(LazyPythonClass clazz, PHashingCollection dict) { super(clazz, dict.entries().iterator()); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java index 98bd45c058..82ca0a56ef 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java @@ -1149,7 +1149,7 @@ abstract static class NegNode extends PythonUnaryBuiltinNode { @GenerateNodeFactory @Builtin(name = "real", fixedNumOfPositionalArgs = 1, isGetter = true, doc = "the real part of a complex number") - static abstract class RealNode extends PythonBuiltinNode { + abstract static class RealNode extends PythonBuiltinNode { @Child private GetLazyClassNode getClassNode; @@ -1179,7 +1179,7 @@ PFloat getPFloatOverriden(PFloat self) { @GenerateNodeFactory @Builtin(name = "imag", fixedNumOfPositionalArgs = 1, isGetter = true, doc = "the imaginary part of a complex number") - static abstract class ImagNode extends PythonBuiltinNode { + abstract static class ImagNode extends PythonBuiltinNode { @Specialization double get(@SuppressWarnings("unused") Object self) { @@ -1190,7 +1190,7 @@ static abstract class ImagNode extends PythonBuiltinNode { @GenerateNodeFactory @Builtin(name = "conjugate", fixedNumOfPositionalArgs = 1, doc = "Returns self, the complex conjugate of any float.") - static abstract class ConjugateNode extends RealNode { + abstract static class ConjugateNode extends RealNode { } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/PFloat.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/PFloat.java index c8754595f4..714968978d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/PFloat.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/PFloat.java @@ -79,17 +79,19 @@ public static String doubleToString(double item) { int l = d.length() - 1; if (exp == (l - 2)) { if (d.charAt(exp + 1) == '-') { - if (Integer.valueOf(d.charAt(l) + "") == 4) + if (Integer.valueOf(d.charAt(l) + "") == 4) { /*- Java convert double when 0.000###... while Python does it when 0.0000####... */ d = Double.toString((item * 10)).replace(".", ".0"); - else + } else { d = d.substring(0, l) + "0" + d.substring(l); + } exp = d.indexOf("E"); } } - if (exp != -1 && d.charAt(exp + 1) != '-') + if (exp != -1 && d.charAt(exp + 1) != '-') { d = d.substring(0, exp + 1) + "+" + d.substring(exp + 1, l + 1); + } d = d.toLowerCase(); } return d; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/TruffleObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/TruffleObjectBuiltins.java index 8556a60b18..de9cf4a53f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/TruffleObjectBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/TruffleObjectBuiltins.java @@ -547,7 +547,7 @@ protected boolean isForeignMapping(TruffleObject receiver) { } } - private static abstract class ForeignBinaryDelegate extends UnboxNode { + private abstract static class ForeignBinaryDelegate extends UnboxNode { @Child private LookupAndCallBinaryNode divNode; protected LookupAndCallBinaryNode getDelegate() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/AbstractFunctionBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/AbstractFunctionBuiltins.java index 6ab2088d27..81c178bfce 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/AbstractFunctionBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/AbstractFunctionBuiltins.java @@ -262,7 +262,7 @@ Object builtinCode(PBuiltinFunction self, Object none) { @Builtin(name = __DICT__, fixedNumOfPositionalArgs = 1, isGetter = true) @GenerateNodeFactory - static abstract class DictNode extends PythonUnaryBuiltinNode { + abstract static class DictNode extends PythonUnaryBuiltinNode { @Specialization Object dict(PFunction self) { PHashingCollection dict = self.getDict(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java index 41b5074184..15169ef595 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java @@ -2194,13 +2194,13 @@ int bitLength(PInt argument) { @GenerateNodeFactory @Builtin(name = "real", fixedNumOfPositionalArgs = 1, isGetter = true, doc = "the real part of a complex number") - static abstract class RealNode extends IntNode { + abstract static class RealNode extends IntNode { } @GenerateNodeFactory @Builtin(name = "imag", fixedNumOfPositionalArgs = 1, isGetter = true, doc = "the imaginary part of a complex number") - static abstract class ImagNode extends PythonBuiltinNode { + abstract static class ImagNode extends PythonBuiltinNode { @Specialization int get(@SuppressWarnings("unused") Object self) { return 0; @@ -2209,19 +2209,19 @@ int get(@SuppressWarnings("unused") Object self) { @GenerateNodeFactory @Builtin(name = "numerator", fixedNumOfPositionalArgs = 1, isGetter = true, doc = "the numerator of a rational number in lowest terms") - static abstract class NumeratorNode extends IntNode { + abstract static class NumeratorNode extends IntNode { } @GenerateNodeFactory @Builtin(name = "conjugate", fixedNumOfPositionalArgs = 1, doc = "Returns self, the complex conjugate of any int.") - static abstract class ConjugateNode extends IntNode { + abstract static class ConjugateNode extends IntNode { } @GenerateNodeFactory @Builtin(name = "denominator", fixedNumOfPositionalArgs = 1, isGetter = true, doc = "the denominator of a rational number in lowest terms") - static abstract class DenominatorNode extends PythonBuiltinNode { + abstract static class DenominatorNode extends PythonBuiltinNode { @Specialization int get(@SuppressWarnings("unused") Object self) { return 1; @@ -2230,7 +2230,7 @@ int get(@SuppressWarnings("unused") Object self) { @GenerateNodeFactory @Builtin(name = SpecialMethodNames.__TRUNC__, fixedNumOfPositionalArgs = 1, doc = "Truncating an Integral returns itself.") - static abstract class TruncNode extends IntNode { + abstract static class TruncNode extends IntNode { } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java index f5754395d5..27a672b794 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java @@ -536,7 +536,7 @@ private static NormalizeIndexNode createNormalize() { @ImportStatic(MathGuards.class) @GenerateNodeFactory public abstract static class ListIndexNode extends PythonBuiltinNode { - protected final static String ERROR_TYPE_MESSAGE = "slice indices must be integers or have an __index__ method"; + protected static final String ERROR_TYPE_MESSAGE = "slice indices must be integers or have an __index__ method"; @Child private SequenceStorageNodes.ItemIndexNode itemIndexNode; @Child private SequenceStorageNodes.LenNode lenNode; @@ -637,7 +637,7 @@ int indexO(PTuple self, Object value, Object start, PNone end, return indexNode.execute(self, value, startValue, end); } - @Specialization(guards = {"!isNumber(end)",}) + @Specialization(guards = {"!isNumber(end)"}) int indexLO(PTuple self, Object value, long start, Object end, @Cached("createNumber(ERROR_TYPE_MESSAGE)") IndexNode endNode, @Cached("createIndexNode()") ListIndexNode indexNode) { @@ -645,7 +645,7 @@ int indexLO(PTuple self, Object value, long start, Object end, return indexNode.execute(self, value, start, endValue); } - @Specialization(guards = {"!isNumber(start) || !isNumber(end)",}) + @Specialization(guards = {"!isNumber(start) || !isNumber(end)"}) int indexOO(PTuple self, Object value, Object start, Object end, @Cached("createNumber(ERROR_TYPE_MESSAGE)") IndexNode startNode, @Cached("createNumber(ERROR_TYPE_MESSAGE)") IndexNode endNode, diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/memoryview/MemoryviewBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/memoryview/MemoryviewBuiltins.java index c7ed464acc..8197de525d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/memoryview/MemoryviewBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/memoryview/MemoryviewBuiltins.java @@ -66,7 +66,7 @@ protected List> getNodeFactories() { @Builtin(name = C_MEMORYVIEW, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) @GenerateNodeFactory - static abstract class SetCMemoryviewNode extends PythonBinaryBuiltinNode { + abstract static class SetCMemoryviewNode extends PythonBinaryBuiltinNode { /* * NOTE: DO NOT CHANGE THE NAME OF PROPERTY '__c_memoryview' it is also referenced in native diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java index 6f2ce2418b..842f07b2cc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java @@ -548,7 +548,7 @@ protected PNone doIt(Object object, Object key, @Builtin(name = __DICT__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) @GenerateNodeFactory - public static abstract class DictNode extends PythonBinaryBuiltinNode { + public abstract static class DictNode extends PythonBinaryBuiltinNode { private final IsBuiltinClassProfile exactObjInstanceProfile = IsBuiltinClassProfile.create(); private final IsBuiltinClassProfile exactBuiltinInstanceProfile = IsBuiltinClassProfile.create(); @@ -597,7 +597,7 @@ Object raise(Object self, @SuppressWarnings("unused") Object dict) { @Builtin(name = __FORMAT__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - static abstract class FormatNode extends PythonBinaryBuiltinNode { + abstract static class FormatNode extends PythonBinaryBuiltinNode { @Specialization(guards = "isString(formatString)") Object format(Object self, @SuppressWarnings("unused") Object formatString, @Cached("create(__STR__)") LookupAndCallUnaryNode strCall) { @@ -612,7 +612,7 @@ Object formatFail(@SuppressWarnings("unused") Object self, @SuppressWarnings("un @Builtin(name = RICHCMP, fixedNumOfPositionalArgs = 3) @GenerateNodeFactory - static abstract class RichCompareNode extends PythonTernaryBuiltinNode { + abstract static class RichCompareNode extends PythonTernaryBuiltinNode { protected static final int NO_SLOW_PATH = Integer.MAX_VALUE; protected BinaryComparisonNode createOp(String op) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/socket/PSocket.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/socket/PSocket.java index 70255a2080..f160e889f2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/socket/PSocket.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/socket/PSocket.java @@ -47,14 +47,14 @@ import com.oracle.graal.python.builtins.objects.type.LazyPythonClass; public class PSocket extends PythonBuiltinObject { - public final static int AF_UNSPEC = 0; - public final static int AF_INET = 2; - public final static int AF_INET6 = 23; + public static final int AF_UNSPEC = 0; + public static final int AF_INET = 2; + public static final int AF_INET6 = 23; - public final static int SOCK_DGRAM = 1; - public final static int SOCK_STREAM = 2; + public static final int SOCK_DGRAM = 1; + public static final int SOCK_STREAM = 2; - private final static InetSocketAddress EPHEMERAL_ADDRESS = new InetSocketAddress(0); + private static final InetSocketAddress EPHEMERAL_ADDRESS = new InetSocketAddress(0); private final int family; private final int type; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/AbstractPythonLock.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/AbstractPythonLock.java index 4b093eb796..10e2123d97 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/AbstractPythonLock.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/AbstractPythonLock.java @@ -45,9 +45,9 @@ public abstract class AbstractPythonLock extends PythonBuiltinObject { - public static double TIMEOUT_MAX = 2 ^ 31; - public static boolean DEFAULT_BLOCKING = true; - public static double DEFAULT_TIMEOUT = -1.0; + public static final double TIMEOUT_MAX = 2 ^ 31; + public static final boolean DEFAULT_BLOCKING = true; + public static final double DEFAULT_TIMEOUT = -1.0; AbstractPythonLock(LazyPythonClass cls) { super(cls); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/PThread.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/PThread.java index e44b0bfc8a..3ec60aaab3 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/PThread.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/PThread.java @@ -45,7 +45,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; public class PThread extends PythonBuiltinObject { - public final static String GRAALPYTHON_THREADS = "GRAALPYTHON_THREADS"; + public static final String GRAALPYTHON_THREADS = "GRAALPYTHON_THREADS"; private final Thread thread; public PThread(LazyPythonClass cls, Thread thread) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/TupleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/TupleBuiltins.java index 65bfe8baf9..f141032d68 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/TupleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/tuple/TupleBuiltins.java @@ -98,7 +98,7 @@ protected List> getNodeFa @GenerateNodeFactory public abstract static class IndexNode extends PythonBuiltinNode { - private final static String ERROR_TYPE_MESSAGE = "slice indices must be integers or have an __index__ method"; + private static final String ERROR_TYPE_MESSAGE = "slice indices must be integers or have an __index__ method"; @Child private SequenceStorageNodes.GetItemNode getItemNode; @Child private SequenceStorageNodes.LenNode lenNode; @@ -215,7 +215,7 @@ int indexO(PTuple self, Object value, Object start, PNone end, return indexNode.execute(self, value, startValue, end); } - @Specialization(guards = {"!isNumber(end)",}) + @Specialization(guards = {"!isNumber(end)"}) int indexLO(PTuple self, Object value, long start, Object end, @Cached("create(__INDEX__)") LookupAndCallUnaryNode endNode, @Cached("createIndexNode()") IndexNode indexNode) { @@ -227,7 +227,7 @@ int indexLO(PTuple self, Object value, long start, Object end, return indexNode.execute(self, value, start, endValue); } - @Specialization(guards = {"!isNumber(start) || !isNumber(end)",}) + @Specialization(guards = {"!isNumber(start) || !isNumber(end)"}) int indexOO(PTuple self, Object value, Object start, Object end, @Cached("create(__INDEX__)") LookupAndCallUnaryNode startNode, @Cached("create(__INDEX__)") LookupAndCallUnaryNode endNode, diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index e12d3db217..272501a621 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -444,7 +444,7 @@ private String getTypeName(Object clazz) { @Builtin(name = __PREPARE__, takesVarArgs = true, takesVarKeywordArgs = true) @GenerateNodeFactory - public static abstract class PrepareNode extends PythonBuiltinNode { + public abstract static class PrepareNode extends PythonBuiltinNode { @SuppressWarnings("unused") @Specialization Object doIt(Object args, Object kwargs) { @@ -454,7 +454,7 @@ Object doIt(Object args, Object kwargs) { @Builtin(name = __BASES__, fixedNumOfPositionalArgs = 1, isGetter = true) @GenerateNodeFactory - static abstract class BasesNode extends PythonBuiltinNode { + abstract static class BasesNode extends PythonBuiltinNode { @Specialization Object bases(LazyPythonClass self, @Cached("create()") TypeNodes.GetBaseClassesNode getBaseClassesNode) { @@ -465,7 +465,7 @@ Object bases(LazyPythonClass self, @Builtin(name = __DICT__, fixedNumOfPositionalArgs = 1, isGetter = true) @GenerateNodeFactory @ImportStatic(NativeMemberNames.class) - static abstract class DictNode extends PythonUnaryBuiltinNode { + abstract static class DictNode extends PythonUnaryBuiltinNode { @Specialization Object doManaged(PythonManagedClass self) { PHashingCollection dict = self.getDict(); @@ -489,7 +489,7 @@ Object doNative(PythonNativeClass self, @Builtin(name = __INSTANCECHECK__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - public static abstract class InstanceCheckNode extends PythonBinaryBuiltinNode { + public abstract static class InstanceCheckNode extends PythonBinaryBuiltinNode { @Child private LookupAndCallBinaryNode getAttributeNode = LookupAndCallBinaryNode.create(__GETATTRIBUTE__); @Child private AbstractObjectIsSubclassNode abstractIsSubclassNode = AbstractObjectIsSubclassNode.create(); @Child private AbstractObjectGetBasesNode getBasesNode = AbstractObjectGetBasesNode.create(); @@ -535,7 +535,7 @@ public boolean isInstance(Object cls, Object instance) { @Builtin(name = __SUBCLASSCHECK__, fixedNumOfPositionalArgs = 2) @GenerateNodeFactory - static abstract class SubclassCheckNode extends PythonBinaryBuiltinNode { + abstract static class SubclassCheckNode extends PythonBinaryBuiltinNode { @Child private IsSubtypeNode isSubtypeNode = IsSubtypeNode.create(); @Child private TypeNodes.IsSameTypeNode isSameTypeNode = TypeNodes.IsSameTypeNode.create(); @Child private GetFixedAttributeNode getBasesAttrNode; @@ -597,7 +597,7 @@ protected boolean isSameType(Object a, Object b) { @Builtin(name = __SUBCLASSES__, fixedNumOfPositionalArgs = 1) @GenerateNodeFactory - static abstract class SubclassesNode extends PythonUnaryBuiltinNode { + abstract static class SubclassesNode extends PythonUnaryBuiltinNode { @Specialization PList getSubclasses(LazyPythonClass cls, @@ -615,11 +615,11 @@ private static Object[] toArray(Set subclasses) { @GenerateNodeFactory @ImportStatic(NativeMemberNames.class) @TypeSystemReference(PythonTypes.class) - static abstract class AbstractSlotNode extends PythonBinaryBuiltinNode { + abstract static class AbstractSlotNode extends PythonBinaryBuiltinNode { } @Builtin(name = __NAME__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) - static abstract class NameNode extends AbstractSlotNode { + abstract static class NameNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { return cls.getName(); @@ -667,7 +667,7 @@ private static String getQualName(String fqname) { } @Builtin(name = __MODULE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) - static abstract class ModuleNode extends AbstractSlotNode { + abstract static class ModuleNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") Object getModule(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { @@ -720,7 +720,7 @@ protected String getBuiltinsName() { } @Builtin(name = __QUALNAME__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) - static abstract class QualNameNode extends AbstractSlotNode { + abstract static class QualNameNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") String getName(PythonBuiltinClass cls, @SuppressWarnings("unused") PNone value) { return cls.getName(); @@ -767,7 +767,7 @@ private static String getQualName(String fqname) { } @Builtin(name = __DICTOFFSET__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) - static abstract class DictoffsetNode extends AbstractSlotNode { + abstract static class DictoffsetNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") Object getName(PythonManagedClass cls, @SuppressWarnings("unused") PNone value, @@ -804,7 +804,7 @@ Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @Su } @Builtin(name = __ITEMSIZE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) - static abstract class ItemsizeNode extends AbstractSlotNode { + abstract static class ItemsizeNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") Object getName(PythonManagedClass cls, @SuppressWarnings("unused") PNone value, @@ -841,7 +841,7 @@ Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @Su } @Builtin(name = __BASICSIZE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true) - static abstract class BasicsizeNode extends AbstractSlotNode { + abstract static class BasicsizeNode extends AbstractSlotNode { @Specialization(guards = "isNoValue(value)") Object getName(PythonManagedClass cls, @SuppressWarnings("unused") PNone value, @@ -879,7 +879,7 @@ Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @Su @Builtin(name = "__flags__", fixedNumOfPositionalArgs = 1, isGetter = true) @GenerateNodeFactory - static abstract class FlagsNode extends PythonUnaryBuiltinNode { + abstract static class FlagsNode extends PythonUnaryBuiltinNode { @Child TypeNodes.GetTypeFlagsNode getFlagsNode = TypeNodes.GetTypeFlagsNode.create(); @Specialization diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java index 3cde31448b..ca525bc538 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/LookupAttributeInMRONode.java @@ -141,7 +141,7 @@ protected Object lookupPBCTGeneric(PythonBuiltinClassType klass) { return findAttr(getCore(), klass, key); } - final static class PythonClassAssumptionPair { + static final class PythonClassAssumptionPair { public final Assumption assumption; public final Object value; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/builtins/ListNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/builtins/ListNodes.java index 87b89cbda6..ba99421cd2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/builtins/ListNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/builtins/ListNodes.java @@ -89,7 +89,7 @@ public abstract class ListNodes { - public final static class CreateStorageFromIteratorNode extends PNodeWithContext { + public static final class CreateStorageFromIteratorNode extends PNodeWithContext { private static final int START_SIZE = 2; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java index d555e6912d..4cd58784da 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java @@ -68,7 +68,7 @@ public StatementNode makeWriteNode(ExpressionNode rhs) { return WriteLocalCellNode.create(frameSlot, rhs); } - static abstract class ReadFromCellNode extends PNodeWithContext { + abstract static class ReadFromCellNode extends PNodeWithContext { private final boolean isFreeVar; private final Object identifier; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java index cca6bf9fe5..1006ec42e2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/WriteGeneratorFrameVariableNode.java @@ -52,7 +52,7 @@ public static WriteGeneratorFrameVariableNode create(FrameSlot slot, ExpressionN return WriteGeneratorFrameVariableNodeGen.create(slot, right); } - protected static abstract class WriteGeneraterFrameSlotNode extends FrameSlotNode { + protected abstract static class WriteGeneraterFrameSlotNode extends FrameSlotNode { public WriteGeneraterFrameSlotNode(FrameSlot slot) { super(slot); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToDoubleNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToDoubleNode.java index 0125c7a139..fad0956ff5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToDoubleNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToDoubleNode.java @@ -61,7 +61,7 @@ public abstract class CastToDoubleNode extends PNodeWithContext { @Node.Child private LookupAndCallUnaryNode callFloatNode; - abstract public double execute(Object x); + public abstract double execute(Object x); public static CastToDoubleNode create() { return CastToDoubleNodeGen.create(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/LoopsBookKeeper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/LoopsBookKeeper.java index 22b1330ec5..252cb4d089 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/LoopsBookKeeper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/LoopsBookKeeper.java @@ -25,19 +25,19 @@ */ package com.oracle.graal.python.parser; +import java.util.ArrayDeque; import java.util.HashMap; import java.util.Map; -import java.util.Stack; import org.antlr.v4.runtime.ParserRuleContext; public class LoopsBookKeeper { - private final Stack loops; + private final ArrayDeque loops; private final Map infos; public LoopsBookKeeper() { - loops = new Stack<>(); + loops = new ArrayDeque<>(); infos = new HashMap<>(); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 3384e02136..e27b2fb090 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -90,8 +90,8 @@ public final class PythonContext { private OutputStream err; private InputStream in; @CompilationFinal private Object capiLibrary = null; - private final static Assumption singleNativeContext = Truffle.getRuntime().createAssumption("single native context assumption"); - private final static Assumption singleThreaded = Truffle.getRuntime().createAssumption("single Threaded"); + private static final Assumption singleNativeContext = Truffle.getRuntime().createAssumption("single native context assumption"); + private static final Assumption singleThreaded = Truffle.getRuntime().createAssumption("single Threaded"); @CompilationFinal private HashingStorage.Equivalence slowPathEquivalence; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java index b3ea12acb6..d3a245aa13 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java @@ -104,6 +104,7 @@ int getNumber(LookupAndCallBinaryNode getItemNode) { if (Character.isDigit(c)) { int numStart = index - 1; while (Character.isDigit(c = pop())) { + // empty } index -= 1; Integer i = Integer.valueOf(format.substring(numStart, index)); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/SequenceStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/SequenceStorage.java index 63cb4d06f2..a7794f5dbe 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/SequenceStorage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/SequenceStorage.java @@ -25,8 +25,6 @@ */ package com.oracle.graal.python.runtime.sequence.storage; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; - public abstract class SequenceStorage { public enum ListStorageType { @@ -42,8 +40,6 @@ public enum ListStorageType { Generic } - @CompilationFinal private static boolean LOG_GENERALIZATION = false; - public abstract int length(); public abstract void setNewLength(int length); From b4476a0a3ea5ef33fccb342fd7d62677b3966703 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 20 Feb 2019 09:59:35 +0100 Subject: [PATCH 193/202] spotbugs doesn't understand that call will raise here --- .../graal/python/builtins/modules/SysModuleBuiltins.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java index 241af1f2c6..33c718bb36 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java @@ -329,7 +329,9 @@ Object counted(int num) { } int actual = num + 1; // skip dummy frame try { - call.call(new Object[0]); + @SuppressWarnings("unused") + Object r = call.call(new Object[0]); + // r is just assigned to make spotbugs happy throw raise(PythonErrorType.SystemError, "should not reach here"); } catch (PException e) { PBaseException exception = e.getExceptionObject(); From 10a2a073f6bc34e1adbdf069bca9093a9d9c42ff Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 20 Feb 2019 10:00:10 +0100 Subject: [PATCH 194/202] slightly refactor signal delivery to make spotbugs happy --- .../modules/SignalModuleBuiltins.java | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java index c6bae6f255..21d9bcef42 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SignalModuleBuiltins.java @@ -45,6 +45,7 @@ import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.Semaphore; import com.oracle.graal.python.builtins.Builtin; import com.oracle.graal.python.builtins.CoreFunctions; @@ -77,6 +78,8 @@ public class SignalModuleBuiltins extends PythonBuiltins { private static final HiddenKey signalQueueKey = new HiddenKey("signalQueue"); private final ConcurrentLinkedDeque signalQueue = new ConcurrentLinkedDeque<>(); + private static final HiddenKey signalSemaKey = new HiddenKey("signalQueue"); + private final Semaphore signalSema = new Semaphore(0); @Override protected List> getNodeFactories() { @@ -102,15 +105,18 @@ public void postInitialize(PythonCore core) { PythonModule signalModule = core.lookupBuiltinModule("_signal"); signalModule.setAttribute(signalQueueKey, signalQueue); + signalModule.setAttribute(signalSemaKey, signalSema); core.getContext().registerAsyncAction(() -> { - synchronized (signalQueue) { - try { - signalQueue.wait(); - } catch (InterruptedException e) { + SignalTriggerAction poll = signalQueue.poll(); + try { + while (poll == null) { + signalSema.acquire(); + poll = signalQueue.poll(); } + } catch (InterruptedException e) { } - return signalQueue.poll(); + return poll; }); } @@ -230,17 +236,17 @@ Object signal(@SuppressWarnings("unused") PythonModule self, long signalNumber, @Specialization @TruffleBoundary Object signal(PythonModule self, long signalNumber, Object handler, - @Cached("create()") ReadAttributeFromObjectNode readNode) { + @Cached("create()") ReadAttributeFromObjectNode readQueueNode, + @Cached("create()") ReadAttributeFromObjectNode readSemaNode) { int signum = getSignum(signalNumber); - ConcurrentLinkedDeque queue = getQueue(self, readNode); + ConcurrentLinkedDeque queue = getQueue(self, readQueueNode); + Semaphore semaphore = getSemaphore(self, readSemaNode); Object retval; SignalTriggerAction signalTrigger = new SignalTriggerAction(handler, signum); try { retval = Signals.setSignalHandler(signum, () -> { queue.add(signalTrigger); - synchronized (queue) { - queue.notify(); - } + semaphore.release(); }); } catch (IllegalArgumentException e) { throw raise(PythonErrorType.ValueError, e); @@ -266,6 +272,15 @@ private static ConcurrentLinkedDeque getQueue(PythonModule throw new IllegalStateException("the signal trigger queue was modified!"); } } + + private static Semaphore getSemaphore(PythonModule self, ReadAttributeFromObjectNode readNode) { + Object semaphore = readNode.execute(self, signalSemaKey); + if (semaphore instanceof Semaphore) { + return (Semaphore) semaphore; + } else { + throw new IllegalStateException("the signal trigger semaphore was modified!"); + } + } } } From 807e95c124829b5b822d600a4e13c0ecc98c78e0 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 20 Feb 2019 11:13:46 +0100 Subject: [PATCH 195/202] update copyrights --- .../src/com/oracle/graal/python/shell/GraalPythonLD.java | 2 +- .../src/com/oracle/graal/python/tck/PythonProvider.java | 2 +- .../src/com/oracle/graal/python/PythonFileDetector.java | 2 +- .../graal/python/builtins/modules/CodecsModuleBuiltins.java | 2 +- .../graal/python/builtins/modules/MathModuleBuiltins.java | 2 +- .../graal/python/builtins/modules/PyExpatModuleBuiltins.java | 2 +- .../graal/python/builtins/modules/SelectModuleBuiltins.java | 2 +- .../graal/python/builtins/modules/SysConfigModuleBuiltins.java | 2 +- .../graal/python/builtins/modules/TimeModuleBuiltins.java | 2 +- .../graal/python/builtins/modules/ZLibModuleBuiltins.java | 2 +- .../graal/python/builtins/objects/complex/ComplexBuiltins.java | 2 +- .../oracle/graal/python/builtins/objects/dict/PDictView.java | 2 +- .../com/oracle/graal/python/builtins/objects/floats/PFloat.java | 2 +- .../oracle/graal/python/builtins/objects/list/ListBuiltins.java | 2 +- .../python/builtins/objects/memoryview/MemoryviewBuiltins.java | 2 +- .../oracle/graal/python/builtins/objects/socket/PSocket.java | 2 +- .../python/builtins/objects/thread/AbstractPythonLock.java | 2 +- .../oracle/graal/python/builtins/objects/thread/PThread.java | 2 +- .../src/com/oracle/graal/python/nodes/builtins/ListNodes.java | 2 +- .../com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java | 2 +- .../com/oracle/graal/python/nodes/util/CastToDoubleNode.java | 2 +- .../src/com/oracle/graal/python/parser/LoopsBookKeeper.java | 2 +- .../oracle/graal/python/runtime/formatting/StringFormatter.java | 2 +- .../graal/python/runtime/sequence/storage/SequenceStorage.java | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonLD.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonLD.java index 935f9703e0..55571756a7 100644 --- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonLD.java +++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonLD.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python.tck/src/com/oracle/graal/python/tck/PythonProvider.java b/graalpython/com.oracle.graal.python.tck/src/com/oracle/graal/python/tck/PythonProvider.java index c456fbc49b..0818f0efa7 100644 --- a/graalpython/com.oracle.graal.python.tck/src/com/oracle/graal/python/tck/PythonProvider.java +++ b/graalpython/com.oracle.graal.python.tck/src/com/oracle/graal/python/tck/PythonProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonFileDetector.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonFileDetector.java index 744b76bae8..f99b622b76 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonFileDetector.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonFileDetector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CodecsModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CodecsModuleBuiltins.java index 5c3c6d766b..9de0b2ecaa 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CodecsModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CodecsModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java index 154f61e398..d3e0ba82fa 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PyExpatModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PyExpatModuleBuiltins.java index 6b601764d4..fd3d737e4b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PyExpatModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PyExpatModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SelectModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SelectModuleBuiltins.java index 09c0dd732f..41dfcc14db 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SelectModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SelectModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysConfigModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysConfigModuleBuiltins.java index 79c778463a..9454c5953b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysConfigModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysConfigModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java index da2e267efc..d6f543a412 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZLibModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZLibModuleBuiltins.java index a062f8847c..bf5a4a99e2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZLibModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ZLibModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java index 9595aa76b9..61ee131597 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/PDictView.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/PDictView.java index a82670fa6c..33301ef310 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/PDictView.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/PDictView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/PFloat.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/PFloat.java index 714968978d..a2efa0e055 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/PFloat.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/PFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java index 27a672b794..7ce67d53be 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/memoryview/MemoryviewBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/memoryview/MemoryviewBuiltins.java index 8197de525d..a9c5c3e4f6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/memoryview/MemoryviewBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/memoryview/MemoryviewBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/socket/PSocket.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/socket/PSocket.java index f160e889f2..a9d57dc42f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/socket/PSocket.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/socket/PSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/AbstractPythonLock.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/AbstractPythonLock.java index 10e2123d97..eb58862604 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/AbstractPythonLock.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/AbstractPythonLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/PThread.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/PThread.java index 3ec60aaab3..472c048591 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/PThread.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/PThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/builtins/ListNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/builtins/ListNodes.java index ba99421cd2..81b8daaefd 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/builtins/ListNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/builtins/ListNodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java index 4cd58784da..30ba00c819 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToDoubleNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToDoubleNode.java index fad0956ff5..f7986c3672 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToDoubleNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToDoubleNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/LoopsBookKeeper.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/LoopsBookKeeper.java index 252cb4d089..d669df0a86 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/LoopsBookKeeper.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/LoopsBookKeeper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java index d3a245aa13..81f7666880 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) -2016 Jython Developers * * Licensed under PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/SequenceStorage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/SequenceStorage.java index a7794f5dbe..28deb5e295 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/SequenceStorage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/SequenceStorage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. * Copyright (c) 2013, Regents of the University of California * * All rights reserved. From f49d7ce998ef5db9ffdfd4600f7621aa40d12656 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Wed, 20 Feb 2019 14:01:49 +0100 Subject: [PATCH 196/202] autofix checkstyle issues --- .../modules/MarshalModuleBuiltins.java | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java index 734c52fa79..66a4960155 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java @@ -156,37 +156,37 @@ Object doit(PByteArray bytes, } } - private final static char TYPE_NULL = '0'; - private final static char TYPE_NONE = 'N'; - private final static char TYPE_NOVALUE = 'n'; - private final static char TYPE_FALSE = 'F'; - private final static char TYPE_TRUE = 'T'; - private final static char TYPE_STOPITER = 'S'; - private final static char TYPE_ELLIPSIS = '.'; - private final static char TYPE_INT = 'i'; - private final static char TYPE_INT64 = 'I'; // just for backward compatibility with CPython - private final static char TYPE_FLOAT = 'f'; + private static final char TYPE_NULL = '0'; + private static final char TYPE_NONE = 'N'; + private static final char TYPE_NOVALUE = 'n'; + private static final char TYPE_FALSE = 'F'; + private static final char TYPE_TRUE = 'T'; + private static final char TYPE_STOPITER = 'S'; + private static final char TYPE_ELLIPSIS = '.'; + private static final char TYPE_INT = 'i'; + private static final char TYPE_INT64 = 'I'; // just for backward compatibility with CPython + private static final char TYPE_FLOAT = 'f'; // private final static char TYPE_BINARY_FLOAT = 'g'; - private final static char TYPE_COMPLEX = 'x'; + private static final char TYPE_COMPLEX = 'x'; // private final static char TYPE_BINARY_COMPLEX = 'y'; - private final static char TYPE_LONG = 'l'; - private final static char TYPE_PINT = 'L'; - private final static char TYPE_STRING = 's'; + private static final char TYPE_LONG = 'l'; + private static final char TYPE_PINT = 'L'; + private static final char TYPE_STRING = 's'; // private final static char TYPE_INTERNED = 't'; // private final static char TYPE_STRINGREF = 'R'; - private final static char TYPE_BYTESLIKE = 'b'; - private final static char TYPE_TUPLE = '('; - private final static char TYPE_LIST = '['; - private final static char TYPE_DICT = '{'; - private final static char TYPE_CODE = 'c'; + private static final char TYPE_BYTESLIKE = 'b'; + private static final char TYPE_TUPLE = '('; + private static final char TYPE_LIST = '['; + private static final char TYPE_DICT = '{'; + private static final char TYPE_CODE = 'c'; // private final static char TYPE_UNICODE = 'u'; - private final static char TYPE_UNKNOWN = '?'; - private final static char TYPE_SET = '<'; - private final static char TYPE_FROZENSET = '>'; - private final static int MAX_MARSHAL_STACK_DEPTH = 2000; - private final static int CURRENT_VERSION = 1; + private static final char TYPE_UNKNOWN = '?'; + private static final char TYPE_SET = '<'; + private static final char TYPE_FROZENSET = '>'; + private static final int MAX_MARSHAL_STACK_DEPTH = 2000; + private static final int CURRENT_VERSION = 1; - public static abstract class MarshallerNode extends PNodeWithContext { + public abstract static class MarshallerNode extends PNodeWithContext { public abstract void execute(Object x, int version, DataOutputStream buffer); @@ -456,7 +456,7 @@ public static MarshallerNode create() { } } - public static abstract class UnmarshallerNode extends PNodeWithContext { + public abstract static class UnmarshallerNode extends PNodeWithContext { public abstract Object execute(byte[] dataBytes, int version); @Child private HashingStorageNodes.SetItemNode setItemNode; @@ -559,7 +559,7 @@ private PList readList(int depth) { if (n < 0) { throw raise(ValueError, "bad marshal data"); } - Object items[] = new Object[n]; + Object[] items = new Object[n]; for (int i = 0; i < n; i++) { Object item = readObject(depth + 1); if (item == null) { @@ -646,7 +646,7 @@ private Object readObject(int depth) { if (n < 0) { throw raise(ValueError, "bad marshal data"); } - Object items[] = new Object[n]; + Object[] items = new Object[n]; for (int i = 0; i < n; i++) { items[i] = readObject(depth + 1); } From 563a41456483b85bd0841498a5c7be77aeff4831 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 21 Feb 2019 11:48:21 +0100 Subject: [PATCH 197/202] guard against null python language home --- .../src/com/oracle/graal/python/runtime/PythonCore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java index 8d6dd92c92..2f4c6aced8 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCore.java @@ -130,7 +130,7 @@ public static String getSysBasePrefix(TruffleLanguage.Env env) { String sysPrefix = env.getOptions().get(PythonOptions.SysBasePrefix); if (sysPrefix.isEmpty()) { String homePrefix = PythonLanguage.getCurrent().getHome(); - if (homePrefix.isEmpty()) { + if (homePrefix == null || homePrefix.isEmpty()) { homePrefix = PREFIX; } env.getOptions().set(PythonOptions.SysBasePrefix, homePrefix); From 1d5ae6439ab1d24bfc067f295d2ba70eb1b2027d Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 21 Feb 2019 13:26:05 +0100 Subject: [PATCH 198/202] Fix wrong replace declarations. --- .../python/builtins/modules/TruffleCextBuiltins.java | 6 +++--- .../python/builtins/objects/type/TypeBuiltins.java | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java index cae1c3d4c8..5aa8a67b87 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java @@ -1430,7 +1430,7 @@ Object doUnpackLong(long start, long stop, long step, long length) { } @Specialization(replaces = {"doUnpackLong", "doUnpack"}) - Object doUnpackLongOvf(long start, long stop, long step, long length) { + Object doUnpackLongOvf0(long start, long stop, long step, long length) { try { PSlice tmpSlice = factory().createSlice(PInt.intValueExact(start), PInt.intValueExact(stop), PInt.intValueExact(step)); SliceInfo actualIndices = tmpSlice.computeIndices(length > Integer.MAX_VALUE ? Integer.MAX_VALUE : PInt.intValueExact(length)); @@ -1440,8 +1440,8 @@ Object doUnpackLongOvf(long start, long stop, long step, long length) { } } - @Specialization(replaces = {"doUnpackLongOvf"}) - Object doUnpackLongOvf(Object start, Object stop, Object step, Object lengthObj, + @Specialization(replaces = {"doUnpackLongOvf0"}) + Object doUnpackLongOvf1(Object start, Object stop, Object step, Object lengthObj, @Cached("createOverflow()") CastToIndexNode castToIndexNode, @Cached("create()") IsBuiltinClassProfile profile, @Cached("create()") SliceLiteralNode sliceLiteralNode) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java index 272501a621..825ed05f85 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java @@ -230,24 +230,24 @@ protected Object doItUnboxedIndirect(VirtualFrame frame, @SuppressWarnings("unus } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf"}) - protected Object doIt(VirtualFrame frame, @SuppressWarnings("unused") PythonAbstractClass self, Object[] arguments, PKeyword[] keywords, + protected Object doIt0(VirtualFrame frame, @SuppressWarnings("unused") PythonAbstractClass self, Object[] arguments, PKeyword[] keywords, @Cached("self") PythonAbstractClass cachedSelf) { return op(frame, cachedSelf, arguments, keywords, true); } - @Specialization(replaces = "doIt") - protected Object doItIndirect(VirtualFrame frame, PythonAbstractClass self, Object[] arguments, PKeyword[] keywords) { + @Specialization(replaces = "doIt0") + protected Object doItIndirect0(VirtualFrame frame, PythonAbstractClass self, Object[] arguments, PKeyword[] keywords) { return op(frame, self, arguments, keywords, true); } @Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = {"self == cachedSelf"}) - protected Object doIt(VirtualFrame frame, @SuppressWarnings("unused") PythonNativeObject self, Object[] arguments, PKeyword[] keywords, + protected Object doIt1(VirtualFrame frame, @SuppressWarnings("unused") PythonNativeObject self, Object[] arguments, PKeyword[] keywords, @Cached("self") PythonNativeObject cachedSelf) { return op(frame, PythonNativeClass.cast(cachedSelf), arguments, keywords, true); } - @Specialization(replaces = "doIt") - protected Object doItIndirect(VirtualFrame frame, PythonNativeObject self, Object[] arguments, PKeyword[] keywords) { + @Specialization(replaces = "doIt1") + protected Object doItIndirect1(VirtualFrame frame, PythonNativeObject self, Object[] arguments, PKeyword[] keywords) { return op(frame, PythonNativeClass.cast(self), arguments, keywords, true); } From ecb3cad283660c4ed618c0431eb7a65466167c32 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Thu, 21 Feb 2019 14:07:15 +0100 Subject: [PATCH 199/202] update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 791187c37f..0a0348ee76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ This changelog summarizes major changes between GraalVM versions of the Python language runtime. The main focus is on user-observable behavior of the engine. +## Version 1.0.0 RC13 + +* Support marshal.dumps and marshal.loads for code objects and some other built-in objects +* Fix installation of NumPy in a venv +* Initial support for module mmap +* Support debugging with workspace files in the Chrome debugger +* Support the PEP 553 breakpoint() message +* Support running weak reference callbacks and signals on the main thread + ## Version 1.0.0 RC12 * Support the `__class__` variable in the class scope From df3bdf6eb3c236d4558c0bf9175063b0941a81ad Mon Sep 17 00:00:00 2001 From: Petr Pisl Date: Fri, 22 Feb 2019 14:15:31 +0100 Subject: [PATCH 200/202] [GR-14075] In virtual env the parameters are not given to graalpython correctly --- graalpython/lib-python/3/venv/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graalpython/lib-python/3/venv/__init__.py b/graalpython/lib-python/3/venv/__init__.py index da5c5177fd..f4372f6080 100644 --- a/graalpython/lib-python/3/venv/__init__.py +++ b/graalpython/lib-python/3/venv/__init__.py @@ -135,7 +135,7 @@ def create_if_needed(d): if sys.platform == "win32": f.write(" %*") else: - f.write(" $@") + f.write(" \"$@\"") if sys.platform != "win32": os.chmod(script, 0o777) From 174ad7de9ca7ccedefd78c8af45673688f447c73 Mon Sep 17 00:00:00 2001 From: Petr Pisl Date: Fri, 22 Feb 2019 14:22:04 +0100 Subject: [PATCH 201/202] [GR-14078] Is not possible to create itertools.combinations_with_replacement. --- .../src/tests/test_itertools.py | 26 +++++++++++++++++++ graalpython/lib-graalpython/itertools.py | 4 +-- mx.graalpython/copyrights/overrides | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 graalpython/com.oracle.graal.python.test/src/tests/test_itertools.py diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_itertools.py b/graalpython/com.oracle.graal.python.test/src/tests/test_itertools.py new file mode 100644 index 0000000000..8a2e03dc30 --- /dev/null +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_itertools.py @@ -0,0 +1,26 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# Copyright (C) 1996-2017 Python Software Foundation +# +# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 + +import unittest +from itertools import * + +class CombinationsTests(unittest.TestCase): + + def test_combinations_with_replacement(self): + cwr = combinations_with_replacement + self.assertRaises(TypeError, cwr, 'abc') # missing r argument + self.assertRaises(TypeError, cwr, 'abc', 2, 1) # too many arguments + self.assertRaises(TypeError, cwr, None) # pool is not iterable + self.assertRaises(ValueError, cwr, 'abc', -2) # r is negative + + result = list() + for a in cwr('ABC', 2): + result += a + correct = [('A','A'), ('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')] + compare = list(); + for a in correct: + compare += a; + self.assertEqual(result,compare) + diff --git a/graalpython/lib-graalpython/itertools.py b/graalpython/lib-graalpython/itertools.py index d23a48b610..00360cf37a 100644 --- a/graalpython/lib-graalpython/itertools.py +++ b/graalpython/lib-graalpython/itertools.py @@ -523,7 +523,7 @@ class combinations(): def __init__(self, pool, indices, r): self.pool = pool - self.indices = range(indices) + self.indices = indices if r < 0: raise ValueError("r must be non-negative") self.r = r @@ -593,7 +593,7 @@ def __init__(self, iterable, r): if r < 0: raise ValueError("r must be non-negative") indices = [0] * r - combinations.__init__(pool, indices, r) + super().__init__(pool, indices, r) self.stopped = len(pool) == 0 and r > 0 def get_maximum(self, i): diff --git a/mx.graalpython/copyrights/overrides b/mx.graalpython/copyrights/overrides index 5b28a92167..b5f9e3165d 100644 --- a/mx.graalpython/copyrights/overrides +++ b/mx.graalpython/copyrights/overrides @@ -233,6 +233,7 @@ graalpython/com.oracle.graal.python.test/src/tests/test_getattribute-bimorphic-i graalpython/com.oracle.graal.python.test/src/tests/test_getattribute-bimorphic-inobject.py,zippy.copyright graalpython/com.oracle.graal.python.test/src/tests/test_if-class-none.py,zippy.copyright graalpython/com.oracle.graal.python.test/src/tests/test_if.py,zippy.copyright +graalpython/com.oracle.graal.python.test/src/tests/test_itertools.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_list.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_builtin.py,python.copyright graalpython/com.oracle.graal.python.test/src/tests/test_mandelbrot3.py,benchmarks.copyright From 5849686487b7ea5a2d5abee27398b9028b70066e Mon Sep 17 00:00:00 2001 From: Cosmin Basca Date: Fri, 22 Feb 2019 12:13:56 +0100 Subject: [PATCH 202/202] python-unittests command: add gate mode for regression testing - skip cpython stats gathering - skip html report generation - do not upload results - perform regression testing This reverts commit 2e4ba604587df6e72f6521114aff452ef3cf0a4b. --- ci.jsonnet | 2 +- .../src/python_unittests.py | 88 +++++++++++++++++-- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/ci.jsonnet b/ci.jsonnet index 14d2177914..b00aace087 100644 --- a/ci.jsonnet +++ b/ci.jsonnet @@ -1,5 +1,5 @@ { - overlay: "e08ca6c848943a04c5e46d54272ff927ff3d51f7", + overlay: "d20cc2abdeb3cfb022e1a8035e40e350e5cfe5fc", // ====================================================================================================== // diff --git a/graalpython/com.oracle.graal.python.test/src/python_unittests.py b/graalpython/com.oracle.graal.python.test/src/python_unittests.py index 48f73856a3..cf40a28556 100644 --- a/graalpython/com.oracle.graal.python.test/src/python_unittests.py +++ b/graalpython/com.oracle.graal.python.test/src/python_unittests.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2019, 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 @@ -74,6 +74,9 @@ PTRN_JAVA_EXCEPTION = re.compile(r'^(?Pcom\.oracle\.[^:]*):(?P.*)') PTRN_MODULE_NOT_FOUND = re.compile(r'.*ModuleNotFound: \'(?P.*)\'\..*', re.DOTALL) PTRN_IMPORT_ERROR = re.compile(r".*cannot import name \'(?P.*)\'.*", re.DOTALL) +PTRN_REMOTE_HOST = re.compile(r"(?P\w+)@(?P[\w.]+):(?P.+)") +PTRN_VALID_CSV_NAME = re.compile(r"unittests-\d{4}-\d{2}-\d{2}.csv") + # ---------------------------------------------------------------------------------------------------------------------- # @@ -192,6 +195,27 @@ def _sorter(iterable): return unittests[:limit] if limit else unittests +def get_remote_host(scp_path): + match = re.match(PTRN_REMOTE_HOST, scp_path) + return match.group('user'), match.group('host'), match.group('path') + + +def ssh_ls(scp_path): + user, host, path = get_remote_host(scp_path) + cmd = ['ssh', '{}@{}'.format(user, host), 'ls', '-l', path] + return map(lambda l: l.split()[-1], _run_cmd(cmd)[1].splitlines()) + + +def read_csv(path): + rows = [] + with open(path, "r") as CSV_FILE: + reader = csv.reader(CSV_FILE) + headers = next(reader)[1:] + for row in reader: + rows.append(row) + return rows + + # ---------------------------------------------------------------------------------------------------------------------- # # result (output processing) @@ -597,7 +621,7 @@ def format_val(row, k): elif k == Col.NUM_TESTS: _class = "text-dark" else: - _class = "text-danger" if value < 0 else "text-muted" + _class = "text-danger" if value and value < 0 else "text-muted" return '{}'.format(_class, value) _tbody = '\n'.join([ @@ -694,6 +718,10 @@ def main(prog, args): parser.add_argument("-o", "--only_tests", help="Run only these unittests (comma sep values).", default=None) parser.add_argument("-s", "--skip_tests", help="Run all unittests except (comma sep values)." "the only_tets option takes precedence", default=None) + parser.add_argument("-r", "--regression_running_tests", help="Regression threshold for running tests.", type=float, + default=None) + parser.add_argument("-g", "--gate", help="Run in gate mode (Skip cpython runs; Do not upload results; " + "Detect regressions).", action="store_true") parser.add_argument("path", help="Path to store the csv output and logs to.", nargs='?', default=None) global flags @@ -708,6 +736,12 @@ def main(prog, args): else: log("[INFO] results will not be saved remotely") + if flags.gate: + log("[INFO] running in gate mode") + if not flags.regression_running_tests: + log("[WARNING] --regression_running_tests not set while in gate mode. " + "Regression detection will not be performed") + def _fmt(t): t = t.strip() return os.path.join(flags.tests_path, t if t.endswith(".py") else t + ".py") @@ -720,15 +754,22 @@ def _fmt(t): unittests = get_unittests(flags.tests_path, limit=flags.limit, skip_tests=skip_tests) # get cpython stats - log(HR) - log("[INFO] get cpython stats") - cpy_results = run_unittests(unittests, 60 * 5, with_cpython=True) - cpy_stats = process_output('\n'.join(cpy_results))[-1] + if not flags.gate: + log(HR) + log("[INFO] get cpython stats") + cpy_results = run_unittests(unittests, 60 * 5, with_cpython=True) + cpy_stats = process_output('\n'.join(cpy_results))[-1] + # handle the timeout + timeout = flags.timeout if flags.timeout else None + else: + cpy_stats = None + # handle the timeout + timeout = flags.timeout if flags.timeout else 60 * 5 # 5 minutes if no value specified (in gate mode only) # get graalpython stats log(HR) log("[INFO] get graalpython stats") - results = run_unittests(unittests, flags.timeout, with_cpython=False) + results = run_unittests(unittests, timeout, with_cpython=False) txt_report_path = file_name(TXT_RESULTS_NAME, current_date) output = save_as_txt(txt_report_path, results) @@ -749,15 +790,44 @@ def _fmt(t): log("[JAVA ISSUES] \n{}", pformat(dict(java_issues))) html_report_path = file_name(HTML_RESULTS_NAME, current_date) - save_as_html(html_report_path, rows, totals, missing_modules, cannot_import_modules, java_issues, current_date) + if not flags.gate: + save_as_html(html_report_path, rows, totals, missing_modules, cannot_import_modules, java_issues, current_date) - if flags.path: + if not flags.gate and flags.path: log("[SAVE] saving results to {} ... ", flags.path) scp(txt_report_path, flags.path) scp(csv_report_path, flags.path) scp(html_report_path, flags.path) + gate_failed = False + if flags.gate and flags.regression_running_tests: + log("[REGRESSION] detecting regression, acceptance threshold = {}%".format( + flags.regression_running_tests * 100)) + csv_files = list(filter(lambda entry: True if PTRN_VALID_CSV_NAME.match(entry) else False, ssh_ls(flags.path))) + last_csv = csv_files[-1] + # log('\n'.join(csv_files)) + # read the remote csv and extract stats + log("[REGRESSION] comparing against: {}".format(last_csv)) + scp('{}/{}'.format(flags.path, last_csv), '.', destination_name=last_csv) + rows = read_csv(last_csv) + prev_totals = { + Col.NUM_TESTS: int(rows[-1][1]), + Col.NUM_FAILS: int(rows[-1][2]), + Col.NUM_ERRORS: int(rows[-1][3]), + Col.NUM_SKIPPED: int(rows[-1][4]), + Col.NUM_PASSES: int(rows[-1][5]), + } + print(prev_totals) + if float(totals[Col.NUM_TESTS]) < float(prev_totals[Col.NUM_TESTS]) * (1.0 - flags.regression_running_tests): + log("[REGRESSION] REGRESSION DETECTED, passed {} tests vs {} from {}".format( + totals[Col.NUM_TESTS], prev_totals[Col.NUM_TESTS], last_csv)) + gate_failed = True + else: + log("[REGRESSION] no regression detected") + log("[DONE]") + if flags.gate and gate_failed: + exit(1) if __name__ == "__main__":