[Jython-checkins] jython: Fixed issue 2224 and added a CPython-like Traverseproc-mechanism
stefan.richthofer
jython-checkins at python.org
Wed Feb 11 04:51:58 CET 2015
https://hg.python.org/jython/rev/3536cd7b2657
changeset: 7577:3536cd7b2657
user: Stefan Richthofer <stefan.richthofer at gmx.de>
date: Wed Feb 11 04:49:36 2015 +0100
summary:
Fixed issue 2224 and added a CPython-like Traverseproc-mechanism
along with some enhancements to the gc-module.
For details see doc of org.python.modules.gc.
While it is optional, we recommend for PyObject-subclasses to
implement the Traverseproc-mechanism (all PyObject-subclasses
bundeled with Jython already do).
For instructions see the docs in org.python.core.Traverseproc
and org.python.core.Untraversable.
Note that this commit also simplifies the implementation of
finalizable PyObject-subclasses, i.e. one does not need to
declare a finalizeTrigger-field any more. Doc in
FinalizablePyObject was updated accordingly.
files:
Lib/test/regrtest.py | 1 -
Lib/test/test_finalizers.py | 12 +-
Lib/test/test_gc.py | 760 +++
Lib/test/test_gc_jy.py | 601 ++
Lib/test/test_resurrection_attr_preserve.py | 97 +
Lib/test/test_weakref.py | 4 +-
NEWS | 5 +
src/com/ziclix/python/sql/DBApiType.java | 3 +-
src/com/ziclix/python/sql/Fetch.java | 84 +-
src/com/ziclix/python/sql/PyConnection.java | 41 +-
src/com/ziclix/python/sql/PyCursor.java | 67 +-
src/com/ziclix/python/sql/PyStatement.java | 37 +-
src/com/ziclix/python/sql/connect/Connect.java | 1 +
src/com/ziclix/python/sql/connect/Connectx.java | 8 +-
src/com/ziclix/python/sql/connect/Lookup.java | 2 +
src/com/ziclix/python/sql/util/BCP.java | 23 +-
src/com/ziclix/python/sql/zxJDBC.java | 3 +
src/org/python/antlr/AST.java | 2 +
src/org/python/antlr/PythonTree.java | 16 +-
src/org/python/antlr/ast/AssertDerived.java | 30 +-
src/org/python/antlr/ast/AssignDerived.java | 30 +-
src/org/python/antlr/ast/AttributeDerived.java | 30 +-
src/org/python/antlr/ast/AugAssignDerived.java | 30 +-
src/org/python/antlr/ast/BinOpDerived.java | 30 +-
src/org/python/antlr/ast/BoolOpDerived.java | 30 +-
src/org/python/antlr/ast/BreakDerived.java | 30 +-
src/org/python/antlr/ast/CallDerived.java | 30 +-
src/org/python/antlr/ast/ClassDefDerived.java | 30 +-
src/org/python/antlr/ast/CompareDerived.java | 30 +-
src/org/python/antlr/ast/ContinueDerived.java | 30 +-
src/org/python/antlr/ast/DeleteDerived.java | 30 +-
src/org/python/antlr/ast/DictDerived.java | 30 +-
src/org/python/antlr/ast/EllipsisDerived.java | 30 +-
src/org/python/antlr/ast/ExceptHandlerDerived.java | 30 +-
src/org/python/antlr/ast/ExecDerived.java | 30 +-
src/org/python/antlr/ast/ExprDerived.java | 30 +-
src/org/python/antlr/ast/ExpressionDerived.java | 30 +-
src/org/python/antlr/ast/ExtSliceDerived.java | 30 +-
src/org/python/antlr/ast/ForDerived.java | 30 +-
src/org/python/antlr/ast/FunctionDefDerived.java | 30 +-
src/org/python/antlr/ast/GeneratorExpDerived.java | 30 +-
src/org/python/antlr/ast/GlobalDerived.java | 30 +-
src/org/python/antlr/ast/IfDerived.java | 30 +-
src/org/python/antlr/ast/IfExpDerived.java | 30 +-
src/org/python/antlr/ast/ImportDerived.java | 30 +-
src/org/python/antlr/ast/ImportFromDerived.java | 30 +-
src/org/python/antlr/ast/IndexDerived.java | 30 +-
src/org/python/antlr/ast/InteractiveDerived.java | 30 +-
src/org/python/antlr/ast/LambdaDerived.java | 30 +-
src/org/python/antlr/ast/ListCompDerived.java | 30 +-
src/org/python/antlr/ast/ListDerived.java | 30 +-
src/org/python/antlr/ast/ModuleDerived.java | 30 +-
src/org/python/antlr/ast/NameDerived.java | 30 +-
src/org/python/antlr/ast/NumDerived.java | 30 +-
src/org/python/antlr/ast/PassDerived.java | 30 +-
src/org/python/antlr/ast/PrintDerived.java | 30 +-
src/org/python/antlr/ast/RaiseDerived.java | 30 +-
src/org/python/antlr/ast/ReprDerived.java | 30 +-
src/org/python/antlr/ast/ReturnDerived.java | 30 +-
src/org/python/antlr/ast/SliceDerived.java | 30 +-
src/org/python/antlr/ast/StrDerived.java | 30 +-
src/org/python/antlr/ast/SubscriptDerived.java | 30 +-
src/org/python/antlr/ast/SuiteDerived.java | 30 +-
src/org/python/antlr/ast/TryExceptDerived.java | 30 +-
src/org/python/antlr/ast/TryFinallyDerived.java | 30 +-
src/org/python/antlr/ast/TupleDerived.java | 30 +-
src/org/python/antlr/ast/UnaryOpDerived.java | 30 +-
src/org/python/antlr/ast/WhileDerived.java | 30 +-
src/org/python/antlr/ast/WithDerived.java | 30 +-
src/org/python/antlr/ast/YieldDerived.java | 30 +-
src/org/python/antlr/ast/aliasDerived.java | 30 +-
src/org/python/antlr/ast/arguments.java | 45 +
src/org/python/antlr/ast/argumentsDerived.java | 30 +-
src/org/python/antlr/ast/comprehension.java | 39 +
src/org/python/antlr/ast/comprehensionDerived.java | 30 +-
src/org/python/antlr/ast/keyword.java | 12 +
src/org/python/antlr/ast/keywordDerived.java | 30 +-
src/org/python/antlr/op/AddDerived.java | 30 +-
src/org/python/antlr/op/AndDerived.java | 30 +-
src/org/python/antlr/op/AugLoadDerived.java | 30 +-
src/org/python/antlr/op/AugStoreDerived.java | 30 +-
src/org/python/antlr/op/BitAndDerived.java | 30 +-
src/org/python/antlr/op/BitOrDerived.java | 30 +-
src/org/python/antlr/op/BitXorDerived.java | 30 +-
src/org/python/antlr/op/DelDerived.java | 30 +-
src/org/python/antlr/op/DivDerived.java | 30 +-
src/org/python/antlr/op/EqDerived.java | 30 +-
src/org/python/antlr/op/FloorDivDerived.java | 30 +-
src/org/python/antlr/op/GtDerived.java | 30 +-
src/org/python/antlr/op/GtEDerived.java | 30 +-
src/org/python/antlr/op/InDerived.java | 30 +-
src/org/python/antlr/op/InvertDerived.java | 30 +-
src/org/python/antlr/op/IsDerived.java | 30 +-
src/org/python/antlr/op/IsNotDerived.java | 30 +-
src/org/python/antlr/op/LShiftDerived.java | 30 +-
src/org/python/antlr/op/LoadDerived.java | 30 +-
src/org/python/antlr/op/LtDerived.java | 30 +-
src/org/python/antlr/op/LtEDerived.java | 30 +-
src/org/python/antlr/op/ModDerived.java | 30 +-
src/org/python/antlr/op/MultDerived.java | 30 +-
src/org/python/antlr/op/NotDerived.java | 30 +-
src/org/python/antlr/op/NotEqDerived.java | 30 +-
src/org/python/antlr/op/NotInDerived.java | 30 +-
src/org/python/antlr/op/OrDerived.java | 30 +-
src/org/python/antlr/op/ParamDerived.java | 30 +-
src/org/python/antlr/op/PowDerived.java | 30 +-
src/org/python/antlr/op/RShiftDerived.java | 30 +-
src/org/python/antlr/op/StoreDerived.java | 30 +-
src/org/python/antlr/op/SubDerived.java | 30 +-
src/org/python/antlr/op/UAddDerived.java | 30 +-
src/org/python/antlr/op/USubDerived.java | 30 +-
src/org/python/core/AstList.java | 20 +-
src/org/python/core/BaseBytes.java | 1 +
src/org/python/core/BaseDictionaryView.java | 14 +-
src/org/python/core/BaseSet.java | 77 +-
src/org/python/core/ClasspathPyImporter.java | 1 +
src/org/python/core/ClasspathPyImporterDerived.java | 26 +-
src/org/python/core/ContextGuard.java | 28 +-
src/org/python/core/IdImpl.java | 11 +-
src/org/python/core/JavaImporter.java | 1 +
src/org/python/core/JavaProxyList.java | 5 +-
src/org/python/core/JavaProxyMap.java | 4 +-
src/org/python/core/JavaProxySet.java | 29 +-
src/org/python/core/JyAttribute.java | 308 +
src/org/python/core/Py.java | 23 +-
src/org/python/core/Py2kBuffer.java | 1 +
src/org/python/core/PyArray.java | 23 +-
src/org/python/core/PyArrayDerived.java | 30 +-
src/org/python/core/PyBaseException.java | 27 +-
src/org/python/core/PyBaseExceptionDerived.java | 26 +-
src/org/python/core/PyBeanEvent.java | 1 +
src/org/python/core/PyBeanEventProperty.java | 1 +
src/org/python/core/PyBeanProperty.java | 1 +
src/org/python/core/PyBoolean.java | 1 +
src/org/python/core/PyBuiltinCallable.java | 1 +
src/org/python/core/PyBuiltinFunction.java | 1 +
src/org/python/core/PyBuiltinFunctionNarrow.java | 1 +
src/org/python/core/PyBuiltinFunctionSet.java | 1 +
src/org/python/core/PyBuiltinMethod.java | 14 +-
src/org/python/core/PyBuiltinMethodNarrow.java | 1 -
src/org/python/core/PyBuiltinMethodSet.java | 14 +-
src/org/python/core/PyByteArray.java | 1 +
src/org/python/core/PyByteArrayDerived.java | 30 +-
src/org/python/core/PyBytecode.java | 62 +-
src/org/python/core/PyCallIter.java | 23 +
src/org/python/core/PyCell.java | 14 +-
src/org/python/core/PyClass.java | 66 +-
src/org/python/core/PyClassMethod.java | 14 +-
src/org/python/core/PyClassMethodDerived.java | 30 +-
src/org/python/core/PyClassMethodDescr.java | 1 +
src/org/python/core/PyComplex.java | 1 +
src/org/python/core/PyComplexDerived.java | 30 +-
src/org/python/core/PyCompoundCallable.java | 29 +-
src/org/python/core/PyDataDescr.java | 1 +
src/org/python/core/PyDescriptor.java | 16 +-
src/org/python/core/PyDictProxy.java | 14 +-
src/org/python/core/PyDictionary.java | 70 +-
src/org/python/core/PyDictionaryDerived.java | 32 +-
src/org/python/core/PyEllipsis.java | 1 +
src/org/python/core/PyEnumerate.java | 23 +
src/org/python/core/PyEnumerateDerived.java | 30 +-
src/org/python/core/PyException.java | 30 +-
src/org/python/core/PyFastSequenceIter.java | 17 +
src/org/python/core/PyFile.java | 25 +-
src/org/python/core/PyFileDerived.java | 30 +-
src/org/python/core/PyFileReader.java | 2 +-
src/org/python/core/PyFileWriter.java | 1 +
src/org/python/core/PyFloat.java | 1 +
src/org/python/core/PyFloatDerived.java | 30 +-
src/org/python/core/PyFrame.java | 176 +-
src/org/python/core/PyFrozenSetDerived.java | 30 +-
src/org/python/core/PyFunction.java | 67 +-
src/org/python/core/PyGenerator.java | 33 +-
src/org/python/core/PyInstance.java | 44 +-
src/org/python/core/PyInteger.java | 1 +
src/org/python/core/PyIntegerDerived.java | 30 +-
src/org/python/core/PyIterator.java | 16 +-
src/org/python/core/PyJavaPackage.java | 33 +-
src/org/python/core/PyJavaType.java | 51 +-
src/org/python/core/PyList.java | 23 +
src/org/python/core/PyListDerived.java | 30 +-
src/org/python/core/PyLong.java | 1 +
src/org/python/core/PyLongDerived.java | 30 +-
src/org/python/core/PyMemoryView.java | 46 +-
src/org/python/core/PyMethod.java | 26 +-
src/org/python/core/PyMethodDescr.java | 14 +-
src/org/python/core/PyModule.java | 14 +-
src/org/python/core/PyModuleDerived.java | 26 +-
src/org/python/core/PyNewWrapper.java | 14 +-
src/org/python/core/PyNone.java | 1 +
src/org/python/core/PyNotImplemented.java | 1 +
src/org/python/core/PyObject.java | 88 +-
src/org/python/core/PyObjectDerived.java | 30 +-
src/org/python/core/PyProperty.java | 33 +-
src/org/python/core/PyPropertyDerived.java | 30 +-
src/org/python/core/PyProxy.java | 4 +-
src/org/python/core/PyReflectedConstructor.java | 5 +-
src/org/python/core/PyReflectedField.java | 1 +
src/org/python/core/PyReflectedFunction.java | 14 +-
src/org/python/core/PyReversedIterator.java | 16 +
src/org/python/core/PySequenceIter.java | 16 +
src/org/python/core/PySequenceList.java | 20 +-
src/org/python/core/PySetDerived.java | 32 +-
src/org/python/core/PySingleton.java | 1 +
src/org/python/core/PySlice.java | 24 +-
src/org/python/core/PySlot.java | 1 +
src/org/python/core/PyStaticMethod.java | 14 +-
src/org/python/core/PyString.java | 3 +-
src/org/python/core/PyStringDerived.java | 30 +-
src/org/python/core/PyStringMap.java | 33 +-
src/org/python/core/PySuper.java | 27 +-
src/org/python/core/PySuperDerived.java | 30 +-
src/org/python/core/PySystemState.java | 288 +-
src/org/python/core/PyTableCode.java | 1 +
src/org/python/core/PyTraceback.java | 21 +-
src/org/python/core/PyTuple.java | 46 +
src/org/python/core/PyTupleDerived.java | 30 +-
src/org/python/core/PyType.java | 79 +-
src/org/python/core/PyTypeDerived.java | 26 +-
src/org/python/core/PyUnicode.java | 1 +
src/org/python/core/PyUnicodeDerived.java | 30 +-
src/org/python/core/PyXRange.java | 1 +
src/org/python/core/PythonTraceFunction.java | 14 +-
src/org/python/core/SyspathArchive.java | 1 +
src/org/python/core/Traverseproc.java | 462 +
src/org/python/core/TraverseprocDerived.java | 17 +
src/org/python/core/Untraversable.java | 26 +
src/org/python/core/Visitproc.java | 7 +
src/org/python/core/__builtin__.java | 14 +
src/org/python/core/exceptions.java | 2 +
src/org/python/core/finalization/FinalizableBuiltin.java | 14 +-
src/org/python/core/finalization/FinalizablePyObject.java | 29 +-
src/org/python/core/finalization/FinalizablePyObjectDerived.java | 19 +-
src/org/python/core/finalization/FinalizeTrigger.java | 228 +-
src/org/python/core/finalization/FinalizeTriggerFactory.java | 4 +-
src/org/python/core/finalization/HasFinalizeTrigger.java | 13 -
src/org/python/core/finalization/PyFinalizableObject.java | 17 -
src/org/python/core/stringlib/FieldNameIterator.java | 28 +-
src/org/python/core/stringlib/MarkupIterator.java | 2 +
src/org/python/jsr223/PyScriptEngineScope.java | 19 +
src/org/python/modules/PyIOFileFactory.java | 43 +-
src/org/python/modules/PyStruct.java | 2 +
src/org/python/modules/PyStructDerived.java | 30 +-
src/org/python/modules/_codecs.java | 2 +
src/org/python/modules/_collections/PyDefaultDict.java | 46 +-
src/org/python/modules/_collections/PyDefaultDictDerived.java | 30 +-
src/org/python/modules/_collections/PyDeque.java | 59 +-
src/org/python/modules/_collections/PyDequeDerived.java | 30 +-
src/org/python/modules/_csv/PyDialect.java | 2 +
src/org/python/modules/_csv/PyDialectDerived.java | 26 +-
src/org/python/modules/_csv/PyReader.java | 30 +
src/org/python/modules/_csv/PyWriter.java | 23 +-
src/org/python/modules/_functools/PyPartial.java | 45 +-
src/org/python/modules/_functools/PyPartialDerived.java | 30 +-
src/org/python/modules/_hashlib.java | 2 +
src/org/python/modules/_io/Closer.java | 2 +-
src/org/python/modules/_io/PyFileIO.java | 2 +
src/org/python/modules/_io/PyFileIODerived.java | 26 +-
src/org/python/modules/_io/PyIOBase.java | 29 +-
src/org/python/modules/_io/PyIOBaseDerived.java | 26 +-
src/org/python/modules/_io/PyRawIOBaseDerived.java | 26 +-
src/org/python/modules/_json/Encoder.java | 56 +-
src/org/python/modules/_json/Scanner.java | 43 +-
src/org/python/modules/_jythonlib/dict_builder.java | 15 +-
src/org/python/modules/_marshal.java | 45 +-
src/org/python/modules/_threading/Condition.java | 17 +-
src/org/python/modules/_threading/Lock.java | 2 +
src/org/python/modules/_weakref/AbstractReference.java | 62 +-
src/org/python/modules/_weakref/GlobalRef.java | 140 +-
src/org/python/modules/_weakref/ReferenceType.java | 7 +-
src/org/python/modules/_weakref/ReferenceTypeDerived.java | 30 +-
src/org/python/modules/_weakref/WeakrefModule.java | 5 -
src/org/python/modules/bz2/PyBZ2Compressor.java | 2 +
src/org/python/modules/bz2/PyBZ2CompressorDerived.java | 30 +-
src/org/python/modules/bz2/PyBZ2Decompressor.java | 15 +-
src/org/python/modules/bz2/PyBZ2DecompressorDerived.java | 30 +-
src/org/python/modules/bz2/PyBZ2File.java | 9 +-
src/org/python/modules/bz2/PyBZ2FileDerived.java | 30 +-
src/org/python/modules/gc.java | 2488 +++++++++-
src/org/python/modules/itertools/PyTeeIterator.java | 47 +
src/org/python/modules/itertools/PyTeeIteratorDerived.java | 30 +-
src/org/python/modules/itertools/chain.java | 16 +
src/org/python/modules/itertools/chainDerived.java | 30 +-
src/org/python/modules/itertools/combinations.java | 17 +
src/org/python/modules/itertools/combinationsDerived.java | 30 +-
src/org/python/modules/itertools/combinationsWithReplacement.java | 17 +
src/org/python/modules/itertools/combinationsWithReplacementDerived.java | 30 +-
src/org/python/modules/itertools/compress.java | 16 +
src/org/python/modules/itertools/compressDerived.java | 30 +-
src/org/python/modules/itertools/count.java | 32 +
src/org/python/modules/itertools/countDerived.java | 30 +-
src/org/python/modules/itertools/cycle.java | 16 +
src/org/python/modules/itertools/cycleDerived.java | 30 +-
src/org/python/modules/itertools/dropwhile.java | 17 +
src/org/python/modules/itertools/dropwhileDerived.java | 30 +-
src/org/python/modules/itertools/groupby.java | 17 +
src/org/python/modules/itertools/groupbyDerived.java | 30 +-
src/org/python/modules/itertools/ifilter.java | 17 +
src/org/python/modules/itertools/ifilterDerived.java | 30 +-
src/org/python/modules/itertools/ifilterfalse.java | 17 +
src/org/python/modules/itertools/ifilterfalseDerived.java | 30 +-
src/org/python/modules/itertools/imap.java | 17 +
src/org/python/modules/itertools/islice.java | 17 +
src/org/python/modules/itertools/isliceDerived.java | 30 +-
src/org/python/modules/itertools/itertools.java | 47 +
src/org/python/modules/itertools/izip.java | 17 +
src/org/python/modules/itertools/izipDerived.java | 30 +-
src/org/python/modules/itertools/izipLongest.java | 17 +
src/org/python/modules/itertools/izipLongestDerived.java | 30 +-
src/org/python/modules/itertools/permutations.java | 17 +
src/org/python/modules/itertools/permutationsDerived.java | 30 +-
src/org/python/modules/itertools/product.java | 17 +
src/org/python/modules/itertools/productDerived.java | 30 +-
src/org/python/modules/itertools/repeat.java | 23 +
src/org/python/modules/itertools/repeatDerived.java | 30 +-
src/org/python/modules/itertools/starmap.java | 17 +
src/org/python/modules/itertools/starmapDerived.java | 30 +-
src/org/python/modules/itertools/takewhile.java | 17 +
src/org/python/modules/itertools/takewhileDerived.java | 30 +-
src/org/python/modules/jffi/ArrayCData.java | 16 +
src/org/python/modules/jffi/ByReference.java | 2 +
src/org/python/modules/jffi/CData.java | 16 +-
src/org/python/modules/jffi/DynamicLibrary.java | 2 +
src/org/python/modules/jffi/StructLayout.java | 22 +-
src/org/python/modules/operator.java | 104 +-
src/org/python/modules/posix/PosixModule.java | 6 +
src/org/python/modules/posix/PyStatResult.java | 73 +
src/org/python/modules/random/PyRandom.java | 2 +
src/org/python/modules/random/PyRandomDerived.java | 30 +-
src/org/python/modules/sre/MatchObject.java | 29 +-
src/org/python/modules/sre/PatternObject.java | 27 +-
src/org/python/modules/sre/ScannerObject.java | 24 +-
src/org/python/modules/synchronize.java | 17 +-
src/org/python/modules/thread/PyLocal.java | 57 +-
src/org/python/modules/thread/PyLocalDerived.java | 26 +-
src/org/python/modules/thread/PyLock.java | 8 +-
src/org/python/modules/time/PyTimeTuple.java | 67 +
src/org/python/modules/time/Time.java | 10 +-
src/org/python/modules/zipimport/zipimporterDerived.java | 30 +-
src/templates/dict.derived | 2 +-
src/templates/gderived-defs | 35 +-
src/templates/set.derived | 2 +-
342 files changed, 12121 insertions(+), 1475 deletions(-)
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -1311,7 +1311,6 @@
test_dummy_threading
test_eof
test_frozen # not meaningful for Jython, although it is similar to Clamp singlejar
- test_gc
test_iterlen
test_multibytecodec
test_multibytecodec_support
diff --git a/Lib/test/test_finalizers.py b/Lib/test/test_finalizers.py
--- a/Lib/test/test_finalizers.py
+++ b/Lib/test/test_finalizers.py
@@ -209,7 +209,7 @@
del DummyClass.__del__
def test_classAcquiresFinalizer_afterInstanciation_oldStyleClass(self):
- #okay to fail in Jython without the manual ensureFinalizer call
+ #okay to fail in Jython without the manual __ensure_finalizer__ call
C = DummyClass("C")
DummyClass.__del__ = delClass
try:
@@ -245,7 +245,7 @@
del DummyClassNew.__del__
def test_classAcquiresFinalizer_afterInstanciation_newStyleClass(self):
- #okay to fail in Jython without the manual ensureFinalizer call
+ #okay to fail in Jython without the manual __ensure_finalizer__ call
G = DummyClassNew("G")
DummyClassNew.__del__ = delClass
try:
@@ -270,7 +270,7 @@
def test_instanceAcquiresFinalizer_bound_newStyleClass2(self):
"""
- It seems, CPython prohibits new style instances from acquiring a finalizer.
+ In CPython, new style instances can't acquire a finalizer.
If one calls the instance-acquired __del__ manually, it works, but the gc
will still call the old one.
"""
@@ -327,7 +327,7 @@
def test_objectDoubleResurrectionAndFinalize_oldStyleClass(self):
- #okay to fail in Jython without the manual ensureFinalizer calls
+ #okay to fail in Jython without the manual __ensure_finalizer__ calls
ResurrectableDummyClass.__del__ = delK
K = ResurrectableDummyClass("K")
K = None
@@ -360,7 +360,7 @@
self.assertEqual(str(resurrectedObject_L), "L")
def test_objectDoubleResurrection_newStyleClass(self):
- #okay to fail in Jython without the manual ensureFinalizer calls
+ #okay to fail in Jython without the manual __ensure_finalizer__ calls
ResurrectableDummyClassNew.__del__ = delM
M = ResurrectableDummyClassNew("M")
M = None
@@ -382,7 +382,7 @@
self.assertEqual(str(resurrectedObject_M), "M")
def test_objectDoubleResurrectionAndFinalize_newStyleClass(self):
- #okay to fail in Jython without the manual ensureFinalizer calls
+ #okay to fail in Jython without the manual __ensure_finalizer__ calls
ResurrectableDummyClassNew.__del__ = delN
N = ResurrectableDummyClassNew("N")
N = None
diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/test_gc.py
@@ -0,0 +1,760 @@
+import unittest
+#from test.test_support import verbose, run_unittest
+from test import test_support
+import sys
+import gc
+import weakref
+
+try:
+ import threading
+except ImportError:
+ threading = None
+
+### Support code
+###############################################################################
+
+# Bug 1055820 has several tests of longstanding bugs involving weakrefs and
+# cyclic gc.
+
+# An instance of C1055820 has a self-loop, so becomes cyclic trash when
+# unreachable.
+class C1055820(object):
+ def __init__(self, i):
+ self.i = i
+ self.loop = self
+
+class GC_Detector(object):
+ # Create an instance I. Then gc hasn't happened again so long as
+ # I.gc_happened is false.
+
+ def __init__(self):
+ self.gc_happened = False
+
+ def it_happened(ignored):
+ self.gc_happened = True
+
+ # Create a piece of cyclic trash that triggers it_happened when
+ # gc collects it.
+ self.wr = weakref.ref(C1055820(666), it_happened)
+
+
+### Tests
+###############################################################################
+
+class GCTests(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ #Jython-specific block:
+ try:
+ cls.savedJythonGCFlags = gc.getJythonGCFlags()
+ gc.setMonitorGlobal(True)
+ #since gc module already exists, it would not be caught by monitorGlobal.
+ #so we have to monitor it manually:
+ gc.monitorObject(gc)
+ #the finalizer-related tests need this flag to pass in Jython:
+ gc.addJythonGCFlags(gc.DONT_FINALIZE_CYCLIC_GARBAGE)
+ except Exception:
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ gc.setJythonGCFlags(cls.savedJythonGCFlags)
+ gc.stopMonitoring()
+ except Exception:
+ pass
+
+ def test_list(self):
+ l = []
+ l.append(l)
+ gc.collect()
+ del l
+ self.assertEqual(gc.collect(), 1)
+
+ def test_dict(self):
+ d = {}
+ d[1] = d
+ gc.collect()
+ del d
+ self.assertEqual(gc.collect(), 1)
+
+ def test_tuple(self):
+ # since tuples are immutable we close the loop with a list
+ l = []
+ t = (l,)
+ l.append(t)
+ gc.collect()
+ del t
+ del l
+ self.assertEqual(gc.collect(), 2)
+
+ def test_class(self):
+ class A:
+ pass
+ A.a = A
+ del A
+ self.assertNotEqual(gc.collect(), 0)
+
+ def test_newstyleclass(self):
+ class A(object):
+ pass
+ gc.collect()
+ del A
+ self.assertNotEqual(gc.collect(), 0)
+
+ def test_instance(self):
+ class A:
+ pass
+ a = A()
+ a.a = a
+ gc.collect()
+ del a
+ self.assertNotEqual(gc.collect(), 0)
+
+ def test_newinstance(self):
+ class A(object):
+ pass
+ a = A()
+ a.a = a
+ gc.collect()
+ del a
+ self.assertNotEqual(gc.collect(), 0)
+ class B(list):
+ pass
+ class C(B, A):
+ pass
+ a = C()
+ a.a = a
+ gc.collect()
+ del a
+ self.assertNotEqual(gc.collect(), 0)
+ del B, C
+ self.assertNotEqual(gc.collect(), 0)
+ A.a = A()
+ del A
+ self.assertNotEqual(gc.collect(), 0)
+
+ def test_method(self):
+ # Tricky: self.__init__ is a bound method, it references the instance.
+ class A:
+ def __init__(self):
+ self.init = self.__init__
+ a = A()
+ gc.collect()
+ del a
+ self.assertNotEqual(gc.collect(), 0)
+
+ def test_finalizer(self):
+ # A() is uncollectable if it is part of a cycle, make sure it shows up
+ # in gc.garbage.
+ class A:
+ def __del__(self): pass
+ class B:
+ pass
+ a = A()
+ a.a = a
+ id_a = id(a)
+ b = B()
+ b.b = b
+ gc.collect()
+ del a
+ del b
+ self.assertNotEqual(gc.collect(), 0)
+ for obj in gc.garbage:
+ if id(obj) == id_a:
+ del obj.a
+ break
+ else:
+ self.fail("didn't find obj in garbage (finalizer)")
+ gc.garbage.remove(obj)
+
+ def test_finalizer_newclass(self):
+ # A() is uncollectable if it is part of a cycle, make sure it shows up
+ # in gc.garbage.
+ class A(object):
+ def __del__(self): pass
+ class B(object):
+ pass
+ a = A()
+ a.a = a
+ id_a = id(a)
+ b = B()
+ b.b = b
+ gc.collect()
+ del a
+ del b
+ self.assertNotEqual(gc.collect(), 0)
+ for obj in gc.garbage:
+ if id(obj) == id_a:
+ del obj.a
+ break
+ else:
+ self.fail("didn't find obj in garbage (finalizer)")
+ gc.garbage.remove(obj)
+
+ def test_function(self):
+ # Tricky: f -> d -> f, code should call d.clear() after the exec to
+ # break the cycle.
+ d = {}
+ exec("def f(): pass\n") in d
+ gc.collect()
+ del d
+ self.assertEqual(gc.collect(), 2)
+
+ def test_frame(self):
+ flg = gc.getJythonGCFlags()
+ #gc.addJythonGCFlags(gc.VERBOSE)
+ #sporadically fails in Jython, no idea why.
+ def f():
+ frame = sys._getframe()
+ gc.collect()
+ f()
+ col = gc.collect()
+ gc.setJythonGCFlags(flg)
+ self.assertEqual(col, 1)
+
+
+ def test_saveall(self):
+ # Verify that cyclic garbage like lists show up in gc.garbage if the
+ # SAVEALL option is enabled.
+
+ # First make sure we don't save away other stuff that just happens to
+ # be waiting for collection.
+ gc.collect()
+ # if this fails, someone else created immortal trash
+ self.assertEqual(gc.garbage, [])
+
+ L = []
+ L.append(L)
+ id_L = id(L)
+
+ debug = gc.get_debug()
+ gc.set_debug(debug | gc.DEBUG_SAVEALL)
+ del L
+ gc.collect()
+ gc.set_debug(debug)
+ self.assertEqual(len(gc.garbage), 1)
+ obj = gc.garbage.pop()
+ self.assertEqual(id(obj), id_L)
+
+ @unittest.skipIf(test_support.is_jython,
+ '''
+ Jython neither supports disabling/enabling the gc, nor
+ setting the gc threshold.
+ ''')
+ def test_del(self):
+ # __del__ methods can trigger collection, make this to happen
+ thresholds = gc.get_threshold()
+ gc.enable()
+ gc.set_threshold(1)
+
+ class A:
+ def __del__(self):
+ dir(self)
+ a = A()
+ del a
+
+ gc.disable()
+ gc.set_threshold(*thresholds)
+
+ @unittest.skipIf(test_support.is_jython,
+ '''
+ Jython neither supports disabling/enabling the gc, nor
+ setting the gc threshold.
+ ''')
+ def test_del_newclass(self):
+ # __del__ methods can trigger collection, make this to happen
+ thresholds = gc.get_threshold()
+ gc.enable()
+ gc.set_threshold(1)
+
+ class A(object):
+ def __del__(self):
+ dir(self)
+ a = A()
+ del a
+
+ gc.disable()
+ gc.set_threshold(*thresholds)
+
+ # The following two tests are fragile:
+ # They precisely count the number of allocations,
+ # which is highly implementation-dependent.
+ # For example:
+ # - disposed tuples are not freed, but reused
+ # - the call to assertEqual somehow avoids building its args tuple
+ @unittest.skipIf(test_support.is_jython,
+ '''
+ Jython does not support to interrogate gc-internal
+ generation-wise counters.
+ ''')
+ def test_get_count(self):
+ # Avoid future allocation of method object
+ assertEqual = self._baseAssertEqual
+ gc.collect()
+ assertEqual(gc.get_count(), (0, 0, 0))
+ a = dict()
+ # since gc.collect(), we created two objects:
+ # the dict, and the tuple returned by get_count()
+ assertEqual(gc.get_count(), (2, 0, 0))
+
+ @unittest.skipIf(test_support.is_jython,
+ '''
+ Jython does not support to interrogate gc-internal
+ generation-wise counters.
+ ''')
+ def test_collect_generations(self):
+ # Avoid future allocation of method object
+ assertEqual = self.assertEqual
+ gc.collect()
+ a = dict()
+ gc.collect(0)
+ assertEqual(gc.get_count(), (0, 1, 0))
+ gc.collect(1)
+ assertEqual(gc.get_count(), (0, 0, 1))
+ gc.collect(2)
+ assertEqual(gc.get_count(), (0, 0, 0))
+
+# def test_trashcan(self):
+# class Ouch:
+# n = 0
+# def __del__(self):
+# Ouch.n = Ouch.n + 1
+# if Ouch.n % 17 == 0:
+# gc.collect()
+#
+# # "trashcan" is a hack to prevent stack overflow when deallocating
+# # very deeply nested tuples etc. It works in part by abusing the
+# # type pointer and refcount fields, and that can yield horrible
+# # problems when gc tries to traverse the structures.
+# # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
+# # most likely die via segfault.
+#
+# # Note: In 2.3 the possibility for compiling without cyclic gc was
+# # removed, and that in turn allows the trashcan mechanism to work
+# # via much simpler means (e.g., it never abuses the type pointer or
+# # refcount fields anymore). Since it's much less likely to cause a
+# # problem now, the various constants in this expensive (we force a lot
+# # of full collections) test are cut back from the 2.2 version.
+# gc.enable()
+# N = 150
+# for count in range(2):
+# t = []
+# for i in range(N):
+# t = [t, Ouch()]
+# u = []
+# for i in range(N):
+# u = [u, Ouch()]
+# v = {}
+# for i in range(N):
+# v = {1: v, 2: Ouch()}
+# gc.disable()
+
+# @unittest.skipUnless(threading, "test meaningless on builds without threads")
+# def test_trashcan_threads(self):
+# # Issue #13992: trashcan mechanism should be thread-safe
+# NESTING = 60
+# N_THREADS = 2
+#
+# def sleeper_gen():
+# """A generator that releases the GIL when closed or dealloc'ed."""
+# try:
+# yield
+# finally:
+# time.sleep(0.000001)
+#
+# class C(list):
+# # Appending to a list is atomic, which avoids the use of a lock.
+# inits = []
+# dels = []
+# def __init__(self, alist):
+# self[:] = alist
+# C.inits.append(None)
+# def __del__(self):
+# # This __del__ is called by subtype_dealloc().
+# C.dels.append(None)
+# # `g` will release the GIL when garbage-collected. This
+# # helps assert subtype_dealloc's behaviour when threads
+# # switch in the middle of it.
+# g = sleeper_gen()
+# next(g)
+# # Now that __del__ is finished, subtype_dealloc will proceed
+# # to call list_dealloc, which also uses the trashcan mechanism.
+#
+# def make_nested():
+# """Create a sufficiently nested container object so that the
+# trashcan mechanism is invoked when deallocating it."""
+# x = C([])
+# for i in range(NESTING):
+# x = [C([x])]
+# del x
+#
+# def run_thread():
+# """Exercise make_nested() in a loop."""
+# while not exit:
+# make_nested()
+#
+# old_checkinterval = sys.getcheckinterval()
+# sys.setcheckinterval(3)
+# try:
+# exit = False
+# threads = []
+# for i in range(N_THREADS):
+# t = threading.Thread(target=run_thread)
+# threads.append(t)
+# for t in threads:
+# t.start()
+# time.sleep(1.0)
+# exit = True
+# for t in threads:
+# t.join()
+# finally:
+# pass
+# sys.setcheckinterval(old_checkinterval)
+# gc.collect()
+# self.assertEqual(len(C.inits), len(C.dels))
+
+ def test_boom(self):
+ class Boom:
+ def __getattr__(self, someattribute):
+ del self.attr
+ raise AttributeError
+
+ a = Boom()
+ b = Boom()
+ a.attr = b
+ b.attr = a
+
+ gc.collect()
+ garbagelen = len(gc.garbage)
+ del a, b
+ # a<->b are in a trash cycle now. Collection will invoke
+ # Boom.__getattr__ (to see whether a and b have __del__ methods), and
+ # __getattr__ deletes the internal "attr" attributes as a side effect.
+ # That causes the trash cycle to get reclaimed via refcounts falling to
+ # 0, thus mutating the trash graph as a side effect of merely asking
+ # whether __del__ exists. This used to (before 2.3b1) crash Python.
+ # Now __getattr__ isn't called.
+ self.assertEqual(gc.collect(), 4)
+ self.assertEqual(len(gc.garbage), garbagelen)
+
+ def test_boom2(self):
+ class Boom2:
+ def __init__(self):
+ self.x = 0
+
+ def __getattr__(self, someattribute):
+ self.x += 1
+ if self.x > 1:
+ del self.attr
+ raise AttributeError
+
+ a = Boom2()
+ b = Boom2()
+ a.attr = b
+ b.attr = a
+
+ gc.collect()
+ garbagelen = len(gc.garbage)
+ del a, b
+ # Much like test_boom(), except that __getattr__ doesn't break the
+ # cycle until the second time gc checks for __del__. As of 2.3b1,
+ # there isn't a second time, so this simply cleans up the trash cycle.
+ # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get
+ # reclaimed this way.
+ self.assertEqual(gc.collect(), 4)
+ self.assertEqual(len(gc.garbage), garbagelen)
+
+ def test_boom_new(self):
+ # boom__new and boom2_new are exactly like boom and boom2, except use
+ # new-style classes.
+
+ class Boom_New(object):
+ def __getattr__(self, someattribute):
+ del self.attr
+ raise AttributeError
+
+ a = Boom_New()
+ b = Boom_New()
+ a.attr = b
+ b.attr = a
+
+ gc.collect()
+ garbagelen = len(gc.garbage)
+ del a, b
+ self.assertEqual(gc.collect(), 4)
+ self.assertEqual(len(gc.garbage), garbagelen)
+
+ def test_boom2_new(self):
+ class Boom2_New(object):
+ def __init__(self):
+ self.x = 0
+
+ def __getattr__(self, someattribute):
+ self.x += 1
+ if self.x > 1:
+ del self.attr
+ raise AttributeError
+
+ a = Boom2_New()
+ b = Boom2_New()
+ a.attr = b
+ b.attr = a
+
+ gc.collect()
+ garbagelen = len(gc.garbage)
+ del a, b
+ self.assertEqual(gc.collect(), 4)
+ self.assertEqual(len(gc.garbage), garbagelen)
+
+ def test_get_referents(self):
+ alist = [1, 3, 5]
+ got = gc.get_referents(alist)
+ got.sort()
+ self.assertEqual(got, alist)
+
+ atuple = tuple(alist)
+ got = gc.get_referents(atuple)
+ got.sort()
+ self.assertEqual(got, alist)
+
+ adict = {1: 3, 5: 7}
+ expected = [1, 3, 5, 7]
+ got = gc.get_referents(adict)
+ got.sort()
+ self.assertEqual(got, expected)
+
+ got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0))
+ got.sort()
+ self.assertEqual(got, [0, 0] + range(5))
+
+ self.assertEqual(gc.get_referents(1, 'a', 4j), [])
+
+ def test_is_tracked(self):
+ # Atomic built-in types are not tracked, user-defined objects and
+ # mutable containers are.
+ # NOTE: types with special optimizations (e.g. tuple) have tests
+ # in their own test files instead.
+ self.assertFalse(gc.is_tracked(None))
+ self.assertFalse(gc.is_tracked(1))
+ self.assertFalse(gc.is_tracked(1.0))
+ self.assertFalse(gc.is_tracked(1.0 + 5.0j))
+ self.assertFalse(gc.is_tracked(True))
+ self.assertFalse(gc.is_tracked(False))
+ self.assertFalse(gc.is_tracked("a"))
+ self.assertFalse(gc.is_tracked(u"a"))
+ self.assertFalse(gc.is_tracked(bytearray("a")))
+ self.assertFalse(gc.is_tracked(type))
+ self.assertFalse(gc.is_tracked(int))
+ self.assertFalse(gc.is_tracked(object))
+ self.assertFalse(gc.is_tracked(object()))
+
+ class OldStyle:
+ pass
+ class NewStyle(object):
+ pass
+ self.assertTrue(gc.is_tracked(gc))
+ self.assertTrue(gc.is_tracked(OldStyle))
+ self.assertTrue(gc.is_tracked(OldStyle()))
+ self.assertTrue(gc.is_tracked(NewStyle))
+ self.assertTrue(gc.is_tracked(NewStyle()))
+ self.assertTrue(gc.is_tracked([]))
+ self.assertTrue(gc.is_tracked(set()))
+
+ def test_bug1055820b(self):
+ # Corresponds to temp2b.py in the bug report.
+ ouch = []
+ def callback(ignored):
+ ouch[:] = [wr() for wr in WRs]
+
+ Cs = [C1055820(i) for i in range(2)]
+ WRs = [weakref.ref(c, callback) for c in Cs]
+ c = None
+
+ gc.collect()
+ self.assertEqual(len(ouch), 0)
+ # Make the two instances trash, and collect again. The bug was that
+ # the callback materialized a strong reference to an instance, but gc
+ # cleared the instance's dict anyway.
+ Cs = None
+ gc.collect()
+ self.assertEqual(len(ouch), 2) # else the callbacks didn't run
+ for x in ouch:
+ # If the callback resurrected one of these guys, the instance
+ # would be damaged, with an empty __dict__.
+ self.assertEqual(x, None)
+
+ at unittest.skipIf(test_support.is_jython,
+ '''
+ GCTogglingTests are neither relevant nor applicable for Jython.
+ ''')
+class GCTogglingTests(unittest.TestCase):
+ def setUp(self):
+ gc.enable()
+
+ def tearDown(self):
+ gc.disable()
+
+ def test_bug1055820c(self):
+ # Corresponds to temp2c.py in the bug report. This is pretty
+ # elaborate.
+
+ c0 = C1055820(0)
+ # Move c0 into generation 2.
+ gc.collect()
+
+ c1 = C1055820(1)
+ c1.keep_c0_alive = c0
+ del c0.loop # now only c1 keeps c0 alive
+
+ c2 = C1055820(2)
+ c2wr = weakref.ref(c2) # no callback!
+
+ ouch = []
+ def callback(ignored):
+ ouch[:] = [c2wr()]
+
+ # The callback gets associated with a wr on an object in generation 2.
+ c0wr = weakref.ref(c0, callback)
+
+ c0 = c1 = c2 = None
+
+ # What we've set up: c0, c1, and c2 are all trash now. c0 is in
+ # generation 2. The only thing keeping it alive is that c1 points to
+ # it. c1 and c2 are in generation 0, and are in self-loops. There's a
+ # global weakref to c2 (c2wr), but that weakref has no callback.
+ # There's also a global weakref to c0 (c0wr), and that does have a
+ # callback, and that callback references c2 via c2wr().
+ #
+ # c0 has a wr with callback, which references c2wr
+ # ^
+ # |
+ # | Generation 2 above dots
+ #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
+ # | Generation 0 below dots
+ # |
+ # |
+ # ^->c1 ^->c2 has a wr but no callback
+ # | | | |
+ # <--v <--v
+ #
+ # So this is the nightmare: when generation 0 gets collected, we see
+ # that c2 has a callback-free weakref, and c1 doesn't even have a
+ # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is
+ # the only object that has a weakref with a callback. gc clears c1
+ # and c2. Clearing c1 has the side effect of dropping the refcount on
+ # c0 to 0, so c0 goes away (despite that it's in an older generation)
+ # and c0's wr callback triggers. That in turn materializes a reference
+ # to c2 via c2wr(), but c2 gets cleared anyway by gc.
+
+ # We want to let gc happen "naturally", to preserve the distinction
+ # between generations.
+ junk = []
+ i = 0
+ detector = GC_Detector()
+ while not detector.gc_happened:
+ i += 1
+ if i > 10000:
+ self.fail("gc didn't happen after 10000 iterations")
+ self.assertEqual(len(ouch), 0)
+ junk.append([]) # this will eventually trigger gc
+
+ self.assertEqual(len(ouch), 1) # else the callback wasn't invoked
+ for x in ouch:
+ # If the callback resurrected c2, the instance would be damaged,
+ # with an empty __dict__.
+ self.assertEqual(x, None)
+
+ def test_bug1055820d(self):
+ # Corresponds to temp2d.py in the bug report. This is very much like
+ # test_bug1055820c, but uses a __del__ method instead of a weakref
+ # callback to sneak in a resurrection of cyclic trash.
+
+ ouch = []
+ class D(C1055820):
+ def __del__(self):
+ ouch[:] = [c2wr()]
+
+ d0 = D(0)
+ # Move all the above into generation 2.
+ gc.collect()
+
+ c1 = C1055820(1)
+ c1.keep_d0_alive = d0
+ del d0.loop # now only c1 keeps d0 alive
+
+ c2 = C1055820(2)
+ c2wr = weakref.ref(c2) # no callback!
+
+ d0 = c1 = c2 = None
+
+ # What we've set up: d0, c1, and c2 are all trash now. d0 is in
+ # generation 2. The only thing keeping it alive is that c1 points to
+ # it. c1 and c2 are in generation 0, and are in self-loops. There's
+ # a global weakref to c2 (c2wr), but that weakref has no callback.
+ # There are no other weakrefs.
+ #
+ # d0 has a __del__ method that references c2wr
+ # ^
+ # |
+ # | Generation 2 above dots
+ #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
+ # | Generation 0 below dots
+ # |
+ # |
+ # ^->c1 ^->c2 has a wr but no callback
+ # | | | |
+ # <--v <--v
+ #
+ # So this is the nightmare: when generation 0 gets collected, we see
+ # that c2 has a callback-free weakref, and c1 doesn't even have a
+ # weakref. Collecting generation 0 doesn't see d0 at all. gc clears
+ # c1 and c2. Clearing c1 has the side effect of dropping the refcount
+ # on d0 to 0, so d0 goes away (despite that it's in an older
+ # generation) and d0's __del__ triggers. That in turn materializes
+ # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc.
+
+ # We want to let gc happen "naturally", to preserve the distinction
+ # between generations.
+ detector = GC_Detector()
+ junk = []
+ i = 0
+ while not detector.gc_happened:
+ i += 1
+ if i > 10000:
+ self.fail("gc didn't happen after 10000 iterations")
+ self.assertEqual(len(ouch), 0)
+ junk.append([]) # this will eventually trigger gc
+
+ self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked
+ for x in ouch:
+ # If __del__ resurrected c2, the instance would be damaged, with an
+ # empty __dict__.
+ self.assertEqual(x, None)
+
+# def test_main():
+# unittest.main()
+# enabled = gc.isenabled()
+# gc.disable()
+# assert not gc.isenabled()
+# debug = gc.get_debug()
+# gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
+#
+# try:
+# gc.collect() # Delete 2nd generation garbage
+# run_unittest(GCTests, GCTogglingTests)
+# finally:
+# gc.set_debug(debug)
+# # test gc.enable() even if GC is disabled by default
+# if verbose:
+# print "restoring automatic collection"
+# # make sure to always test gc.enable()
+# gc.enable()
+# assert gc.isenabled()
+# if not enabled:
+# gc.disable()
+
+if __name__ == "__main__":
+ #test_main()
+ unittest.main()
diff --git a/Lib/test/test_gc_jy.py b/Lib/test/test_gc_jy.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/test_gc_jy.py
@@ -0,0 +1,601 @@
+"""
+Tests some Jython-specific gc aspects and debugging
+features.
+"""
+
+import unittest
+#from test.test_support import verbose, run_unittest
+#import sys
+import time
+import gc
+import weakref
+from java.lang import System, Runnable
+
+# class FinalizationDummy:
+# def __del__(self):
+# time.sleep(3.5)
+# print "FinalizationDummy.__del__"
+# time.sleep(3.5)
+#
+# class ResurrectionDummy:
+# def __del__(self):
+# print "ResurrectionDummy.__del__"
+# ResurrectionDummy.resurrected = self.toResurrect
+#
+# class SelfResurrectionDummy:
+# def __del__(self):
+# print "SelfResurrectionDummy.__del__"
+# SelfResurrectionDummy.resurrected = self
+
+class GCTests_Jy_CyclicGarbage(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ #Jython-specific block:
+ try:
+ cls.savedJythonGCFlags = gc.getJythonGCFlags()
+ #the finalizer-related tests need this flag to pass in Jython:
+ gc.addJythonGCFlags(gc.DONT_FINALIZE_CYCLIC_GARBAGE)
+ gc.stopMonitoring()
+ except Exception:
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ gc.setJythonGCFlags(cls.savedJythonGCFlags)
+ except Exception:
+ pass
+
+
+ # In contrast to the tests in test_gc, these finalizer tests shall work
+ # even if gc-monitoring is disabled.
+ def test_finalizer(self):
+ # A() is uncollectable if it is part of a cycle, make sure it shows up
+ # in gc.garbage.
+ class A:
+ def __del__(self): pass
+ class B:
+ pass
+ a = A()
+ a.a = a
+ id_a = id(a)
+ b = B()
+ b.b = b
+ gc.collect()
+ del a
+ del b
+ self.assertNotEqual(gc.collect(), 0)
+ time.sleep(4)
+ for obj in gc.garbage:
+ if id(obj) == id_a:
+ del obj.a
+ break
+ else:
+ self.fail("didn't find obj in garbage (finalizer)")
+ gc.garbage.remove(obj)
+
+
+ def test_finalizer_newclass(self):
+ # A() is uncollectable if it is part of a cycle, make sure it shows up
+ # in gc.garbage.
+ class A(object):
+ def __del__(self): pass
+ class B(object):
+ pass
+ a = A()
+ a.a = a
+ id_a = id(a)
+ b = B()
+ b.b = b
+ gc.collect()
+ del a
+ del b
+ self.assertNotEqual(gc.collect(), 0)
+ time.sleep(1)
+ for obj in gc.garbage:
+ if id(obj) == id_a:
+ del obj.a
+ break
+ else:
+ self.fail("didn't find obj in garbage (finalizer)")
+ gc.garbage.remove(obj)
+
+ def test_manual_monitoring(self):
+ # since tuples are immutable we close the loop with a list
+ l = []
+ t = (l,)
+ l.append(t)
+ gc.monitorObject(l)
+ #gc.monitorObject(t) <- intentionally only monitor one of them
+ gc.collect()
+ del t
+ del l
+ #Note that usually two collected objects would be expected - l and t.
+ #But we intentionally only monitored one of them, so only one should
+ #be counted.
+ self.assertEqual(gc.collect(), 1)
+
+
+class GCTests_Jy_preprocess_and_postprocess(unittest.TestCase):
+
+ def test_finalization_preprocess_and_postprocess(self):
+ #print "test_finalization_preprocess_and_postprocess"
+ #Note that this test is done here again (already was in another class
+ #in this module), to see that everything works as it should also with
+ #a different flag-context.
+ #print "test_finalization_preprocess_and_postprocess"
+ #gc.removeJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
+ comments = []
+ self0 = self
+ class A:
+ def __del__(self):
+ #print "del A"
+ self0.assertIn("run PreProcess", comments)
+ comments.append("A del")
+ #let's simulate a time-consuming finalizer
+ #to ensure that post finalization processing
+ #is sensitive to this
+ time.sleep(0.5)
+ comments.append("A del done")
+
+ class PreProcess(Runnable):
+ def run(self):
+ self0.assertEqual(comments, [])
+ comments.append("run PreProcess")
+
+ class PostProcess(Runnable):
+ def run(self):
+ self0.assertIn("run PreProcess", comments)
+ self0.assertIn("A del", comments)
+ self0.assertIn("A del done", comments)
+ comments.append("run PostProcess")
+
+ a = A()
+ a = None
+ prePr = PreProcess()
+ postPr = PostProcess()
+ time.sleep(1) # <- to avoid that the newly registered processes
+ # become subject to previous run
+ gc.registerPreFinalizationProcess(prePr)
+ gc.registerPostFinalizationProcess(postPr)
+ #Note that order matters here:
+ #If the flag gc.DONT_FINALIZE_RESURRECTED_OBJECTS is used,
+ #gc.registerPostFinalizationProcess(postPr, 0) would lead to failure,
+ #because postPr asserts that a's finalizer already ran. Since
+ #DONT_FINALIZE_RESURRECTED_OBJECTS also inserted a postprocess,
+ #to perform delayed finalization, the 0-index would prepend postPr
+ #before the process that actually runs the finalizers.
+ System.gc()
+ #we wait a bit longer here, since PostProcess runs asynchronous
+ #and must wait for the finalizer of A
+ time.sleep(2)
+ self.assertIn("run PostProcess", comments)
+ comments = []
+ gc.unregisterPreFinalizationProcess(prePr)
+ gc.unregisterPostFinalizationProcess(postPr)
+
+
+class GCTests_Jy_Delayed_Finalization(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ #Jython-specific block:
+ try:
+ cls.savedJythonGCFlags = gc.getJythonGCFlags()
+ #the finalizer-related tests need this flag to pass in Jython:
+ gc.addJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
+ gc.stopMonitoring()
+ except Exception:
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ gc.setJythonGCFlags(cls.savedJythonGCFlags)
+ except Exception:
+ pass
+
+ def test_finalization_preprocess_and_postprocess(self):
+ #print "test_finalization_preprocess_and_postprocess"
+ #Note that this test is done here again (already was in another class
+ #in this module), to see that everything works as it should also with
+ #a different flag-context.
+ #print "test_finalization_preprocess_and_postprocess"
+ #gc.removeJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
+ comments = []
+ self0 = self
+ class A:
+ def __del__(self):
+ #print "del A"
+ self0.assertIn("run PreProcess", comments)
+ comments.append("A del")
+ #let's simulate a time-consuming finalizer
+ #to ensure that post finalization processing
+ #is sensitive to this
+ time.sleep(0.5)
+ comments.append("A del done")
+
+ class PreProcess(Runnable):
+ def run(self):
+ self0.assertEqual(comments, [])
+ comments.append("run PreProcess")
+
+ class PostProcess(Runnable):
+ def run(self):
+ self0.assertIn("run PreProcess", comments)
+ self0.assertIn("A del", comments)
+ self0.assertIn("A del done", comments)
+ comments.append("run PostProcess")
+
+ a = A()
+ a = None
+ prePr = PreProcess()
+ postPr = PostProcess()
+ time.sleep(1) # <- to avoid that the newly registered processes
+ # become subject to previous run
+ gc.registerPreFinalizationProcess(prePr)
+ gc.registerPostFinalizationProcess(postPr)
+ #Note that order matters here:
+ #If the flag gc.DONT_FINALIZE_RESURRECTED_OBJECTS is used,
+ #gc.registerPostFinalizationProcess(postPr, 0) would lead to failure,
+ #because postPr asserts that a's finalizer already ran. Since
+ #DONT_FINALIZE_RESURRECTED_OBJECTS also inserted a postprocess,
+ #to perform delayed finalization, the 0-index would prepend postPr
+ #before the process that actually runs the finalizers.
+ System.gc()
+ #we wait a bit longer here, since PostProcess runs asynchronous
+ #and must wait for the finalizer of A
+ time.sleep(2)
+ self.assertIn("run PostProcess", comments)
+ comments = []
+ gc.unregisterPreFinalizationProcess(prePr)
+ gc.unregisterPostFinalizationProcess(postPr)
+
+
+ def test_delayedFinalization(self):
+ #gc.addJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
+ #gc.addJythonGCFlags(gc.VERBOSE)
+ resurrect = []
+ comments = []
+
+ class Test_Finalizable(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+
+ class Test_Resurrection(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+ if hasattr(self, "toResurrect"):
+ resurrect.append(self.toResurrect)
+
+ a = Test_Finalizable("a")
+ a.b = Test_Finalizable("b")
+ c = Test_Resurrection("c")
+ c.a = a
+ c.toResurrect = Test_Finalizable("d")
+
+ del a
+ del c
+ self.assertNotEqual(gc.collect(), 0)
+ time.sleep(1)
+ #print comments
+ #print resurrect
+ self.assertIn('del c', comments)
+ self.assertEqual(1, len(comments))
+ comments = []
+ self.assertNotEqual(gc.collect(), 0)
+ time.sleep(1)
+ #print comments
+ #print resurrect
+ self.assertIn('del a', comments)
+ self.assertEqual(1, len(comments))
+ comments = []
+ self.assertNotEqual(gc.collect(), 0)
+ time.sleep(1)
+ self.assertIn('del b', comments)
+ self.assertEqual(1, len(comments))
+ #gc.removeJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
+ #gc.removeJythonGCFlags(gc.VERBOSE)
+
+
+class GCTests_Jy_Monitoring(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ #Jython-specific block:
+ try:
+ cls.savedJythonGCFlags = gc.getJythonGCFlags()
+ gc.setMonitorGlobal(True)
+ gc.addJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
+ #since gc module already exists, it would not be caught by monitorGlobal.
+ #so we have to monitor it manually:
+ gc.monitorObject(gc)
+ #the finalizer-related tests need this flag to pass in Jython:
+ #gc.addJythonGCFlags(gc.DONT_FINALIZE_CYCLIC_GARBAGE)
+ except Exception:
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ gc.setJythonGCFlags(cls.savedJythonGCFlags)
+ gc.stopMonitoring()
+ except Exception:
+ pass
+
+ def test_monitor_status_after_delayed_finalization(self):
+ resurrect = []
+ comments = []
+
+ class Test_Finalizable(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+
+ class Test_Resurrection(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+ if hasattr(self, "toResurrect"):
+ resurrect.append(self.toResurrect)
+
+ a = Test_Finalizable("a")
+ a.b = Test_Finalizable("b")
+ c = Test_Resurrection("c")
+ c.toResurrect = a
+ a.b.a = a
+ self.assertTrue(gc.isMonitored(a))
+ self.assertTrue(gc.isMonitored(a.b))
+ self.assertTrue(gc.isMonitored(c))
+ gc.collect()
+ del a
+ del c
+ #gc.set_debug(gc.DEBUG_SAVEALL)
+ #gc.collect()
+ self.assertEqual(gc.collect(), 0) #c is not cyclic and a, b are resurrected,
+ #so nothing to count here
+ #self.asserEqual(len(gc.garbage), 0)
+ #if we called gc.set_debug(gc.DEBUG_SAVEALL) above, it would
+ #be okay for gc.garbage to be empty, because a and b
+ #are not finalized and c is not cyclic.
+ self.assertEqual(comments, ['del c'])
+ self.assertEqual(str(resurrect), "[<a>]")
+ self.assertTrue(gc.isMonitored(resurrect[0]))
+ self.assertTrue(gc.isMonitored(resurrect[0].b))
+
+ def test_notifyRerun_for_delayed_finalization(self):
+ gc.collect()
+ resurrect = []
+ comments = []
+
+ class Test_Finalizable(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+
+ a = Test_Finalizable("a")
+ lst = []
+ lst1 = [lst]
+ lst.append(lst1)
+ a.b = Test_Finalizable("b")
+ a.b.lst = lst
+ del lst
+ del lst1
+ self.assertTrue(gc.isMonitored(a))
+ self.assertTrue(gc.isMonitored(a.b))
+ del a
+ self.assertEqual(gc.collect(), 2) # c is not cyclic and a, b are resurrected,
+ # the cycle of two lists is counted here
+ self.assertEqual(comments, ['del a', 'del b'])
+
+
+class GCTests_Jy_Weakref(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ #Jython-specific block:
+ try:
+ cls.savedJythonGCFlags = gc.getJythonGCFlags()
+ gc.addJythonGCFlags(gc.PRESERVE_WEAKREFS_ON_RESURRECTION)
+ except Exception:
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ gc.setJythonGCFlags(cls.savedJythonGCFlags)
+ gc.stopMonitoring()
+ except Exception:
+ pass
+
+ def test_weakref_after_resurrection(self):
+ resurrect = []
+ comments = []
+ class Test_Finalizable(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+
+ class Test_Resurrection(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+ if hasattr(self, "toResurrect"):
+ resurrect.append(self)
+
+ def clb(ref):
+ comments.append("clb")
+
+ def clb2(ref):
+ comments.append("clb2 "+str(comments))
+
+ a = Test_Finalizable("a")
+ wa = weakref.ref(a, clb)
+ self.assertEqual(wa(), a)
+ c = Test_Resurrection("c")
+ c.toResurrect = a
+ wc = weakref.ref(c, clb2)
+ try:
+ gc.monitorObject(c)
+ except Exception:
+ pass
+ del a
+ del c
+ gc.collect()
+ self.assertIn('clb2 []', comments)
+ self.assertNotIn("clb", comments)
+ self.assertEqual(str(resurrect), "[<c>]")
+ self.assertEqual(str(wa()), "<a>")
+ self.assertEqual(wc(), None)
+
+ def test_weakref_after_resurrection_and_delayed_finalize(self):
+ resurrect = []
+ comments = []
+ class Test_Finalizable(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+
+ class Test_Resurrection(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+ if hasattr(self, "toResurrect"):
+ resurrect.append(self)
+
+ def clb(ref):
+ comments.append("clb")
+
+ def clb2(ref):
+ comments.append("clb2 "+str(comments))
+
+ a = Test_Finalizable("a")
+ wa = weakref.ref(a, clb)
+ self.assertEqual(wa(), a)
+ c = Test_Resurrection("c")
+ c.toResurrect = a
+ wc = weakref.ref(c, clb2)
+ try:
+ gc.monitorObject(c)
+ gc.addJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
+ except Exception:
+ pass
+ del a
+ del c
+ gc.collect()
+ self.assertIn('del c', comments)
+ self.assertNotIn('del a', comments)
+ self.assertIn('clb2 []', comments)
+ self.assertNotIn("clb", comments)
+ self.assertEqual(str(resurrect), "[<c>]")
+ self.assertEqual(str(wa()), "<a>")
+ self.assertEqual(wc(), None)
+ try:
+ gc.removeJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
+ except Exception:
+ pass
+
+ def test_weakref_after_resurrection_threadsafe(self):
+ resurrect = []
+ comments = []
+
+ class Test_Finalizable(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+
+ class Test_Resurrection(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "<"+self.name+">"
+
+ def __del__(self):
+ comments.append("del "+self.name)
+ if hasattr(self, "toResurrect"):
+ resurrect.append(self)
+
+ a = Test_Finalizable("a")
+ wa = weakref.ref(a)
+ c = Test_Resurrection("c")
+ c.toResurrect = a
+ wc = weakref.ref(c)
+ del a
+ del c
+ try:
+ gc.addJythonGCFlags(gc.PRESERVE_WEAKREFS_ON_RESURRECTION)
+ System.gc()
+ # We intentionally don't wait here, but want to observe
+ # the situation with gc unfinnished. Note that wa() preserves
+ # its result right away, due to thread-safe implementation.
+ # Technically, the weak reference breaks and is restored after
+ # gc-run finishes. However wa() blocks until the referent is
+ # restored or the deletion is confirmed.
+ except Exception:
+ pass
+ #self.assertEqual(str(wa()), '<a>')
+ self.assertEqual(comments, [])
+ self.assertEqual(resurrect, [])
+ while comments == [] or resurrect == []:
+ self.assertEqual(str(wa()), '<a>')
+ self.assertEqual(wc(), None)
+ self.assertEqual(str(wa()), '<a>')
+ self.assertEqual(wc(), None)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_resurrection_attr_preserve.py b/Lib/test/test_resurrection_attr_preserve.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/test_resurrection_attr_preserve.py
@@ -0,0 +1,97 @@
+import unittest
+import gc
+import time
+import weakref
+
+class ReferentDummy:
+ def __init__(self, name):
+ self.name = name
+
+ def __str__(self):
+ return self.name
+
+class ResurrectionDummy:
+ def __del__(self):
+ ResurrectionDummy.resurrected = self.toResurrect
+
+class SelfResurrectionDummy:
+ def __del__(self):
+ SelfResurrectionDummy.resurrected = self
+
+class GCDetector():
+ gcIndex = 0
+
+ def __del__(self):
+ GCDetector.gcIndex += 1
+
+maxGCRun = 10
+
+def runGC():
+ """
+ This is needed for Jython, since theoretically Java gc is not guaranteed to
+ run if gc.collect is called; the run is only attempted. This method assures
+ that actually a gc run happens.
+ """
+ currentIndex = GCDetector.gcIndex
+ gcCount = 0
+ detector = GCDetector()
+ del detector
+ gc.collect()
+ time.sleep(0.2)
+ while currentIndex == GCDetector.gcIndex and gcCount < maxGCRun:
+ gc.collect()
+ gcCount += 1
+ time.sleep(0.2)
+
+class GCTests(unittest.TestCase):
+
+ def test_id_after_self_resurrection(self):
+ rd = SelfResurrectionDummy()
+ savedId = id(rd)
+ rd = None
+ runGC() #needed for Jython etc, even though no cyclic trash appears
+ self.assertEqual(id(SelfResurrectionDummy.resurrected), savedId)
+ del SelfResurrectionDummy.resurrected
+
+ def test_id_after_resurrection(self):
+ l = ["ab"]
+ rd = ResurrectionDummy()
+ rd.toResurrect = l
+ savedId = id(l)
+ l = None
+ rd = None
+ runGC() #needed for Jython etc, even though no cyclic trash appears
+ self.assertEqual(id(ResurrectionDummy.resurrected), savedId)
+ del ResurrectionDummy.resurrected
+
+#todo: Check these test regarding to CPython behavior
+# def test_weakref_consistency_after_self_resurrection(self):
+# #fails in CPython
+# rd = SelfResurrectionDummy()
+# wref = weakref.ref(rd)
+# self.assertIn(wref, weakref.getweakrefs(rd))
+# rd = None
+# runGC() #needed for Jython etc, even though no cyclic trash appears
+# self.asserIn(wref, weakref.getweakrefs(SelfResurrectionDummy.resurrected))
+# for wref2 in weakref.getweakrefs(SelfResurrectionDummy.resurrected):
+# self.assertIs(wref2(), SelfResurrectionDummy.resurrected)
+# del SelfResurrectionDummy.resurrected
+#
+# def test_weakref_consistency_after_resurrection(self):
+# l = ReferentDummy("ab")
+# rd = ResurrectionDummy()
+# rd.toResurrect = l
+# wref = weakref.ref(l)
+# self.assertIn(wref, weakref.getweakrefs(l))
+# l = None
+# rd = None
+# runGC() #needed for Jython etc, even though no cyclic trash appears
+# self.asserIn(wref, weakref.getweakrefs(ResurrectionDummy.resurrected))
+# for wref2 in weakref.getweakrefs(ResurrectionDummy.resurrected):
+# self.assertIs(wref2(), ResurrectionDummy.resurrected)
+# del ResurrectionDummy.resurrected
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -1367,7 +1367,7 @@
True
>>> del o, o2
>>> import gc # Addition for Jython
->>> gc.collect()
+>>> gc_count = gc.collect()
>>> print r()
None
@@ -1421,7 +1421,7 @@
True
>>> del a
>>> import gc # addition for Jython
->>> gc.collect()
+>>> gc_count = gc.collect()
>>> try:
... id2obj(a_id)
... except KeyError:
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -41,6 +41,8 @@
- [ 2236 ] Interactive parser does not accept try ... except E as e: syntax
- [ 2237 ] Fully conformant math and cmath support
- [ 2244 ] More robust testing of math and cmath modules
+ - [ 2224 ] id(...) now persists object resurrection and a pattern is provided to solve similar issues
+ (i.e. attributes bound to a PyObject via a WeakHashMap) in an analogue way (See JyAttribute.java).
New features
- Full support of Python buffer protocol, along with Java ByteBuffer support
@@ -55,6 +57,9 @@
- Initial support for ensurepip module
- Callbacks can be registered/unregistered to be notified when
bytecode is loaded, using jythonlib.bytecodetools
+ - Jython now features an optional, but recommended-to-implement traverseproc-mechanism
+ like CPython. This enables some new gc-features to optionally emulate CPython-specific
+ gc-behavior. See doc in gc.java and Traverseproc.java.
Potentially backwards breaking changes, removing silent errors:
diff --git a/src/com/ziclix/python/sql/DBApiType.java b/src/com/ziclix/python/sql/DBApiType.java
--- a/src/com/ziclix/python/sql/DBApiType.java
+++ b/src/com/ziclix/python/sql/DBApiType.java
@@ -7,8 +7,8 @@
*/
package com.ziclix.python.sql;
-import org.python.core.PyClass;
import org.python.core.PyInteger;
+import org.python.core.Untraversable;
/**
* This class wraps the types from java.sql.Type in order for
@@ -17,6 +17,7 @@
*
* @author brian zimmer
*/
+ at Untraversable
public final class DBApiType extends PyInteger {
/**
diff --git a/src/com/ziclix/python/sql/Fetch.java b/src/com/ziclix/python/sql/Fetch.java
--- a/src/com/ziclix/python/sql/Fetch.java
+++ b/src/com/ziclix/python/sql/Fetch.java
@@ -13,6 +13,8 @@
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.core.PyTuple;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import java.sql.CallableStatement;
import java.sql.DatabaseMetaData;
@@ -48,7 +50,7 @@
*
* @author brian zimmer
*/
-abstract public class Fetch {
+abstract public class Fetch implements Traverseproc {
/**
* The total number of rows in the result set.
@@ -464,6 +466,43 @@
public boolean removeWarningListener(WarningListener listener) {
return this.listeners.remove(listener);
}
+
+
+ /* Traverseproc support for Fetch */
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = visit.visit(description, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (listeners != null) {
+ for (WarningListener obj: listeners) {
+ if (obj != null) {
+ if (obj instanceof PyObject) {
+ retVal = visit.visit((PyObject) obj, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ } else if (obj instanceof Traverseproc) {
+ retVal = ((Traverseproc) obj).traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ if (ob == null) {
+ return false;
+ } else if (ob == description) {
+ return true;
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ }
}
/**
@@ -691,6 +730,49 @@
this.rownumber = -1;
this.results.clear();
}
+
+
+ /* Traverseproc support for StaticFetch */
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (results != null) {
+ for (PyObject obj: results) {
+ if (obj != null) {
+ retVal = visit.visit((PyObject) obj, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ if (descriptions != null) {
+ for (PyObject obj: descriptions) {
+ if (obj != null) {
+ retVal = visit.visit((PyObject) obj, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ if (ob == null) {
+ return false;
+ }
+ if (results != null && results.contains(ob)) {
+ return true;
+ }
+ if (descriptions != null && descriptions.contains(ob)) {
+ return true;
+ }
+ return super.refersDirectlyTo(ob);
+ }
}
/**
diff --git a/src/com/ziclix/python/sql/PyConnection.java b/src/com/ziclix/python/sql/PyConnection.java
--- a/src/com/ziclix/python/sql/PyConnection.java
+++ b/src/com/ziclix/python/sql/PyConnection.java
@@ -24,6 +24,8 @@
import org.python.core.PyString;
import org.python.core.PyUnicode;
import org.python.core.ThreadState;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import com.ziclix.python.sql.util.PyArgParser;
@@ -32,7 +34,7 @@
*
* @author brian zimmer
*/
-public class PyConnection extends PyObject implements ClassDictInit, ContextManager {
+public class PyConnection extends PyObject implements ClassDictInit, ContextManager, Traverseproc {
/** True if closed. */
protected boolean closed;
@@ -448,6 +450,43 @@
return false;
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ for (PyObject ob: cursors) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ for (PyObject ob: statements) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null) {
+ return false;
+ }
+ if (cursors != null && cursors.contains(ob)) {
+ return true;
+ } else if (statements != null && statements.contains(ob)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
class ConnectionFunc extends PyBuiltinMethodSet {
diff --git a/src/com/ziclix/python/sql/PyCursor.java b/src/com/ziclix/python/sql/PyCursor.java
--- a/src/com/ziclix/python/sql/PyCursor.java
+++ b/src/com/ziclix/python/sql/PyCursor.java
@@ -23,6 +23,8 @@
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.PyUnicode;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import com.ziclix.python.sql.util.PyArgParser;
import org.python.core.ContextManager;
@@ -35,7 +37,8 @@
*
* @author brian zimmer
*/
-public class PyCursor extends PyObject implements ClassDictInit, WarningListener, ContextManager {
+public class PyCursor extends PyObject implements ClassDictInit, WarningListener,
+ ContextManager, Traverseproc {
/** Field fetch */
protected Fetch fetch;
@@ -900,6 +903,68 @@
close();
return false;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (fetch != null) {
+ retVal = fetch.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (rsType != null) {
+ retVal = visit.visit(rsType, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (rsConcur != null) {
+ retVal = visit.visit(rsConcur, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (warnings != null) {
+ retVal = visit.visit(warnings, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (lastrowid != null) {
+ retVal = visit.visit(lastrowid, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (updatecount != null) {
+ retVal = visit.visit(updatecount, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (connection != null) {
+ retVal = visit.visit(connection, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return statement != null ? visit.visit(statement, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null) {
+ return false;
+ } else if (ob == rsType || ob == rsConcur || ob == warnings || ob == lastrowid
+ || ob == updatecount || ob == connection || ob == statement) {
+ return true;
+ } else {
+ return fetch.refersDirectlyTo(ob);
+ }
+ }
}
class CursorFunc extends PyBuiltinMethodSet {
diff --git a/src/com/ziclix/python/sql/PyStatement.java b/src/com/ziclix/python/sql/PyStatement.java
--- a/src/com/ziclix/python/sql/PyStatement.java
+++ b/src/com/ziclix/python/sql/PyStatement.java
@@ -7,6 +7,7 @@
*/
package com.ziclix.python.sql;
+import org.python.core.Visitproc;
import org.python.core.codecs;
import org.python.core.Py;
import org.python.core.PyException;
@@ -14,6 +15,7 @@
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyUnicode;
+import org.python.core.Traverseproc;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
@@ -25,7 +27,7 @@
*
* @author brian zimmer
*/
-public class PyStatement extends PyObject {
+public class PyStatement extends PyObject implements Traverseproc {
/** Denotes a simple Statement with no parameters. */
public static final int STATEMENT_STATIC = 2;
@@ -278,4 +280,37 @@
closed = true;
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (sql != null) {
+ if (sql instanceof PyObject) {
+ int retVal = visit.visit((PyObject) sql, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ } else if (sql instanceof Traverseproc) {
+ int retVal = ((Traverseproc) sql).traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (sql == null || ob == null) {
+ return false;
+ } else if (sql instanceof PyObject) {
+ return sql == ob;
+ } else if (sql instanceof Traverseproc) {
+ return ((Traverseproc) sql).refersDirectlyTo(ob);
+ } else{
+ return false;
+ }
+ }
}
diff --git a/src/com/ziclix/python/sql/connect/Connect.java b/src/com/ziclix/python/sql/connect/Connect.java
--- a/src/com/ziclix/python/sql/connect/Connect.java
+++ b/src/com/ziclix/python/sql/connect/Connect.java
@@ -19,6 +19,7 @@
*
* @author brian zimmer
*/
+ at Untraversable
public class Connect extends PyObject {
private static final PyString _doc = new PyString("establish a connection through java.sql.DriverManager");
diff --git a/src/com/ziclix/python/sql/connect/Connectx.java b/src/com/ziclix/python/sql/connect/Connectx.java
--- a/src/com/ziclix/python/sql/connect/Connectx.java
+++ b/src/com/ziclix/python/sql/connect/Connectx.java
@@ -19,6 +19,7 @@
import org.python.core.Py;
import org.python.core.PyObject;
import org.python.core.PyString;
+import org.python.core.Untraversable;
import com.ziclix.python.sql.PyConnection;
import com.ziclix.python.sql.zxJDBC;
@@ -29,17 +30,18 @@
*
* @author brian zimmer
*/
+ at Untraversable
public class Connectx extends PyObject {
- private final String SET = "set";
- private final PyString doc =
+ private static final String SET = "set";
+ private static final PyString _doc =
new PyString("establish a connection through a javax.sql.DataSource or "
+ "javax.sql.ConnectionPooledDataSource");
@Override
public PyObject __findattr_ex__(String name) {
if ("__doc__".equals(name)) {
- return doc;
+ return _doc;
}
return super.__findattr_ex__(name);
}
diff --git a/src/com/ziclix/python/sql/connect/Lookup.java b/src/com/ziclix/python/sql/connect/Lookup.java
--- a/src/com/ziclix/python/sql/connect/Lookup.java
+++ b/src/com/ziclix/python/sql/connect/Lookup.java
@@ -22,6 +22,7 @@
import org.python.core.Py;
import org.python.core.PyObject;
import org.python.core.PyString;
+import org.python.core.Untraversable;
import com.ziclix.python.sql.PyConnection;
import com.ziclix.python.sql.zxJDBC;
@@ -36,6 +37,7 @@
*
* @author brian zimmer
*/
+ at Untraversable
public class Lookup extends PyObject {
private static final PyString _doc =
diff --git a/src/com/ziclix/python/sql/util/BCP.java b/src/com/ziclix/python/sql/util/BCP.java
--- a/src/com/ziclix/python/sql/util/BCP.java
+++ b/src/com/ziclix/python/sql/util/BCP.java
@@ -14,6 +14,9 @@
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.core.PyString;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
+
import com.ziclix.python.sql.PyConnection;
import com.ziclix.python.sql.zxJDBC;
import com.ziclix.python.sql.pipe.Pipe;
@@ -23,7 +26,7 @@
/**
* A class to perform efficient Bulk CoPy of database tables.
*/
-public class BCP extends PyObject implements ClassDictInit {
+public class BCP extends PyObject implements ClassDictInit, Traverseproc {
/**
* Field sourceDH, destDH
@@ -182,6 +185,24 @@
return pipe.pipe(source, sink).__sub__(Py.newInteger(1));
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (source != null) {
+ int retVal = visit.visit(source, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return destination != null ? visit.visit(destination, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == source || ob == destination);
+ }
}
/**
diff --git a/src/com/ziclix/python/sql/zxJDBC.java b/src/com/ziclix/python/sql/zxJDBC.java
--- a/src/com/ziclix/python/sql/zxJDBC.java
+++ b/src/com/ziclix/python/sql/zxJDBC.java
@@ -18,6 +18,7 @@
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyStringMap;
+import org.python.core.Untraversable;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
@@ -41,6 +42,7 @@
*
* @author brian zimmer
*/
+ at Untraversable
public class zxJDBC extends PyObject implements ClassDictInit {
/**
@@ -428,6 +430,7 @@
}
}
+ at Untraversable
class zxJDBCFunc extends PyBuiltinFunctionSet {
zxJDBCFunc(String name, int index, int minargs, int maxargs, String doc) {
diff --git a/src/org/python/antlr/AST.java b/src/org/python/antlr/AST.java
--- a/src/org/python/antlr/AST.java
+++ b/src/org/python/antlr/AST.java
@@ -4,8 +4,10 @@
import org.python.core.PyException;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Untraversable;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "_ast.AST", base = PyObject.class)
public class AST extends PyObject {
public static final PyType TYPE = PyType.fromClass(AST.class);
diff --git a/src/org/python/antlr/PythonTree.java b/src/org/python/antlr/PythonTree.java
--- a/src/org/python/antlr/PythonTree.java
+++ b/src/org/python/antlr/PythonTree.java
@@ -4,14 +4,17 @@
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.CommonTree;
+import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.antlr.ast.Name;
import org.python.antlr.ast.VisitorIF;
import java.util.ArrayList;
import java.util.List;
-public class PythonTree extends AST {
+public class PythonTree extends AST implements Traverseproc {
public boolean from_future_checked = false;
private int charStartIndex = -1;
@@ -460,4 +463,15 @@
}
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return parent != null ? visit.visit(parent, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == parent;
+ }
}
diff --git a/src/org/python/antlr/ast/AssertDerived.java b/src/org/python/antlr/ast/AssertDerived.java
--- a/src/org/python/antlr/ast/AssertDerived.java
+++ b/src/org/python/antlr/ast/AssertDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class AssertDerived extends Assert implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class AssertDerived extends Assert implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/AssignDerived.java b/src/org/python/antlr/ast/AssignDerived.java
--- a/src/org/python/antlr/ast/AssignDerived.java
+++ b/src/org/python/antlr/ast/AssignDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class AssignDerived extends Assign implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class AssignDerived extends Assign implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/AttributeDerived.java b/src/org/python/antlr/ast/AttributeDerived.java
--- a/src/org/python/antlr/ast/AttributeDerived.java
+++ b/src/org/python/antlr/ast/AttributeDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class AttributeDerived extends Attribute implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class AttributeDerived extends Attribute implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/AugAssignDerived.java b/src/org/python/antlr/ast/AugAssignDerived.java
--- a/src/org/python/antlr/ast/AugAssignDerived.java
+++ b/src/org/python/antlr/ast/AugAssignDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class AugAssignDerived extends AugAssign implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class AugAssignDerived extends AugAssign implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/BinOpDerived.java b/src/org/python/antlr/ast/BinOpDerived.java
--- a/src/org/python/antlr/ast/BinOpDerived.java
+++ b/src/org/python/antlr/ast/BinOpDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class BinOpDerived extends BinOp implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class BinOpDerived extends BinOp implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/BoolOpDerived.java b/src/org/python/antlr/ast/BoolOpDerived.java
--- a/src/org/python/antlr/ast/BoolOpDerived.java
+++ b/src/org/python/antlr/ast/BoolOpDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class BoolOpDerived extends BoolOp implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class BoolOpDerived extends BoolOp implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/BreakDerived.java b/src/org/python/antlr/ast/BreakDerived.java
--- a/src/org/python/antlr/ast/BreakDerived.java
+++ b/src/org/python/antlr/ast/BreakDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class BreakDerived extends Break implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class BreakDerived extends Break implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/CallDerived.java b/src/org/python/antlr/ast/CallDerived.java
--- a/src/org/python/antlr/ast/CallDerived.java
+++ b/src/org/python/antlr/ast/CallDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class CallDerived extends Call implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class CallDerived extends Call implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ClassDefDerived.java b/src/org/python/antlr/ast/ClassDefDerived.java
--- a/src/org/python/antlr/ast/ClassDefDerived.java
+++ b/src/org/python/antlr/ast/ClassDefDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ClassDefDerived extends ClassDef implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ClassDefDerived extends ClassDef implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/CompareDerived.java b/src/org/python/antlr/ast/CompareDerived.java
--- a/src/org/python/antlr/ast/CompareDerived.java
+++ b/src/org/python/antlr/ast/CompareDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class CompareDerived extends Compare implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class CompareDerived extends Compare implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ContinueDerived.java b/src/org/python/antlr/ast/ContinueDerived.java
--- a/src/org/python/antlr/ast/ContinueDerived.java
+++ b/src/org/python/antlr/ast/ContinueDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ContinueDerived extends Continue implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ContinueDerived extends Continue implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/DeleteDerived.java b/src/org/python/antlr/ast/DeleteDerived.java
--- a/src/org/python/antlr/ast/DeleteDerived.java
+++ b/src/org/python/antlr/ast/DeleteDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class DeleteDerived extends Delete implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class DeleteDerived extends Delete implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/DictDerived.java b/src/org/python/antlr/ast/DictDerived.java
--- a/src/org/python/antlr/ast/DictDerived.java
+++ b/src/org/python/antlr/ast/DictDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class DictDerived extends Dict implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class DictDerived extends Dict implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/EllipsisDerived.java b/src/org/python/antlr/ast/EllipsisDerived.java
--- a/src/org/python/antlr/ast/EllipsisDerived.java
+++ b/src/org/python/antlr/ast/EllipsisDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class EllipsisDerived extends Ellipsis implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class EllipsisDerived extends Ellipsis implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ExceptHandlerDerived.java b/src/org/python/antlr/ast/ExceptHandlerDerived.java
--- a/src/org/python/antlr/ast/ExceptHandlerDerived.java
+++ b/src/org/python/antlr/ast/ExceptHandlerDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ExceptHandlerDerived extends ExceptHandler implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ExceptHandlerDerived extends ExceptHandler implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ExecDerived.java b/src/org/python/antlr/ast/ExecDerived.java
--- a/src/org/python/antlr/ast/ExecDerived.java
+++ b/src/org/python/antlr/ast/ExecDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ExecDerived extends Exec implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ExecDerived extends Exec implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ExprDerived.java b/src/org/python/antlr/ast/ExprDerived.java
--- a/src/org/python/antlr/ast/ExprDerived.java
+++ b/src/org/python/antlr/ast/ExprDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ExprDerived extends Expr implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ExprDerived extends Expr implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ExpressionDerived.java b/src/org/python/antlr/ast/ExpressionDerived.java
--- a/src/org/python/antlr/ast/ExpressionDerived.java
+++ b/src/org/python/antlr/ast/ExpressionDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ExpressionDerived extends Expression implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ExpressionDerived extends Expression implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ExtSliceDerived.java b/src/org/python/antlr/ast/ExtSliceDerived.java
--- a/src/org/python/antlr/ast/ExtSliceDerived.java
+++ b/src/org/python/antlr/ast/ExtSliceDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ExtSliceDerived extends ExtSlice implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ExtSliceDerived extends ExtSlice implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ForDerived.java b/src/org/python/antlr/ast/ForDerived.java
--- a/src/org/python/antlr/ast/ForDerived.java
+++ b/src/org/python/antlr/ast/ForDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ForDerived extends For implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ForDerived extends For implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/FunctionDefDerived.java b/src/org/python/antlr/ast/FunctionDefDerived.java
--- a/src/org/python/antlr/ast/FunctionDefDerived.java
+++ b/src/org/python/antlr/ast/FunctionDefDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class FunctionDefDerived extends FunctionDef implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class FunctionDefDerived extends FunctionDef implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/GeneratorExpDerived.java b/src/org/python/antlr/ast/GeneratorExpDerived.java
--- a/src/org/python/antlr/ast/GeneratorExpDerived.java
+++ b/src/org/python/antlr/ast/GeneratorExpDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class GeneratorExpDerived extends GeneratorExp implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class GeneratorExpDerived extends GeneratorExp implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/GlobalDerived.java b/src/org/python/antlr/ast/GlobalDerived.java
--- a/src/org/python/antlr/ast/GlobalDerived.java
+++ b/src/org/python/antlr/ast/GlobalDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class GlobalDerived extends Global implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class GlobalDerived extends Global implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/IfDerived.java b/src/org/python/antlr/ast/IfDerived.java
--- a/src/org/python/antlr/ast/IfDerived.java
+++ b/src/org/python/antlr/ast/IfDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class IfDerived extends If implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class IfDerived extends If implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/IfExpDerived.java b/src/org/python/antlr/ast/IfExpDerived.java
--- a/src/org/python/antlr/ast/IfExpDerived.java
+++ b/src/org/python/antlr/ast/IfExpDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class IfExpDerived extends IfExp implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class IfExpDerived extends IfExp implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ImportDerived.java b/src/org/python/antlr/ast/ImportDerived.java
--- a/src/org/python/antlr/ast/ImportDerived.java
+++ b/src/org/python/antlr/ast/ImportDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ImportDerived extends Import implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ImportDerived extends Import implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ImportFromDerived.java b/src/org/python/antlr/ast/ImportFromDerived.java
--- a/src/org/python/antlr/ast/ImportFromDerived.java
+++ b/src/org/python/antlr/ast/ImportFromDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ImportFromDerived extends ImportFrom implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ImportFromDerived extends ImportFrom implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/IndexDerived.java b/src/org/python/antlr/ast/IndexDerived.java
--- a/src/org/python/antlr/ast/IndexDerived.java
+++ b/src/org/python/antlr/ast/IndexDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class IndexDerived extends Index implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class IndexDerived extends Index implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/InteractiveDerived.java b/src/org/python/antlr/ast/InteractiveDerived.java
--- a/src/org/python/antlr/ast/InteractiveDerived.java
+++ b/src/org/python/antlr/ast/InteractiveDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class InteractiveDerived extends Interactive implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class InteractiveDerived extends Interactive implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/LambdaDerived.java b/src/org/python/antlr/ast/LambdaDerived.java
--- a/src/org/python/antlr/ast/LambdaDerived.java
+++ b/src/org/python/antlr/ast/LambdaDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class LambdaDerived extends Lambda implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class LambdaDerived extends Lambda implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ListCompDerived.java b/src/org/python/antlr/ast/ListCompDerived.java
--- a/src/org/python/antlr/ast/ListCompDerived.java
+++ b/src/org/python/antlr/ast/ListCompDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ListCompDerived extends ListComp implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ListCompDerived extends ListComp implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ListDerived.java b/src/org/python/antlr/ast/ListDerived.java
--- a/src/org/python/antlr/ast/ListDerived.java
+++ b/src/org/python/antlr/ast/ListDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ListDerived extends List implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ListDerived extends List implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ModuleDerived.java b/src/org/python/antlr/ast/ModuleDerived.java
--- a/src/org/python/antlr/ast/ModuleDerived.java
+++ b/src/org/python/antlr/ast/ModuleDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ModuleDerived extends Module implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ModuleDerived extends Module implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/NameDerived.java b/src/org/python/antlr/ast/NameDerived.java
--- a/src/org/python/antlr/ast/NameDerived.java
+++ b/src/org/python/antlr/ast/NameDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class NameDerived extends Name implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class NameDerived extends Name implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/NumDerived.java b/src/org/python/antlr/ast/NumDerived.java
--- a/src/org/python/antlr/ast/NumDerived.java
+++ b/src/org/python/antlr/ast/NumDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class NumDerived extends Num implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class NumDerived extends Num implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/PassDerived.java b/src/org/python/antlr/ast/PassDerived.java
--- a/src/org/python/antlr/ast/PassDerived.java
+++ b/src/org/python/antlr/ast/PassDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PassDerived extends Pass implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PassDerived extends Pass implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/PrintDerived.java b/src/org/python/antlr/ast/PrintDerived.java
--- a/src/org/python/antlr/ast/PrintDerived.java
+++ b/src/org/python/antlr/ast/PrintDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PrintDerived extends Print implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PrintDerived extends Print implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/RaiseDerived.java b/src/org/python/antlr/ast/RaiseDerived.java
--- a/src/org/python/antlr/ast/RaiseDerived.java
+++ b/src/org/python/antlr/ast/RaiseDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class RaiseDerived extends Raise implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class RaiseDerived extends Raise implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ReprDerived.java b/src/org/python/antlr/ast/ReprDerived.java
--- a/src/org/python/antlr/ast/ReprDerived.java
+++ b/src/org/python/antlr/ast/ReprDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ReprDerived extends Repr implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ReprDerived extends Repr implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/ReturnDerived.java b/src/org/python/antlr/ast/ReturnDerived.java
--- a/src/org/python/antlr/ast/ReturnDerived.java
+++ b/src/org/python/antlr/ast/ReturnDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ReturnDerived extends Return implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ReturnDerived extends Return implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/SliceDerived.java b/src/org/python/antlr/ast/SliceDerived.java
--- a/src/org/python/antlr/ast/SliceDerived.java
+++ b/src/org/python/antlr/ast/SliceDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class SliceDerived extends Slice implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class SliceDerived extends Slice implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/StrDerived.java b/src/org/python/antlr/ast/StrDerived.java
--- a/src/org/python/antlr/ast/StrDerived.java
+++ b/src/org/python/antlr/ast/StrDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class StrDerived extends Str implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class StrDerived extends Str implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/SubscriptDerived.java b/src/org/python/antlr/ast/SubscriptDerived.java
--- a/src/org/python/antlr/ast/SubscriptDerived.java
+++ b/src/org/python/antlr/ast/SubscriptDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class SubscriptDerived extends Subscript implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class SubscriptDerived extends Subscript implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/SuiteDerived.java b/src/org/python/antlr/ast/SuiteDerived.java
--- a/src/org/python/antlr/ast/SuiteDerived.java
+++ b/src/org/python/antlr/ast/SuiteDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class SuiteDerived extends Suite implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class SuiteDerived extends Suite implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/TryExceptDerived.java b/src/org/python/antlr/ast/TryExceptDerived.java
--- a/src/org/python/antlr/ast/TryExceptDerived.java
+++ b/src/org/python/antlr/ast/TryExceptDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class TryExceptDerived extends TryExcept implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class TryExceptDerived extends TryExcept implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/TryFinallyDerived.java b/src/org/python/antlr/ast/TryFinallyDerived.java
--- a/src/org/python/antlr/ast/TryFinallyDerived.java
+++ b/src/org/python/antlr/ast/TryFinallyDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class TryFinallyDerived extends TryFinally implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class TryFinallyDerived extends TryFinally implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/TupleDerived.java b/src/org/python/antlr/ast/TupleDerived.java
--- a/src/org/python/antlr/ast/TupleDerived.java
+++ b/src/org/python/antlr/ast/TupleDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class TupleDerived extends Tuple implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class TupleDerived extends Tuple implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/UnaryOpDerived.java b/src/org/python/antlr/ast/UnaryOpDerived.java
--- a/src/org/python/antlr/ast/UnaryOpDerived.java
+++ b/src/org/python/antlr/ast/UnaryOpDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class UnaryOpDerived extends UnaryOp implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class UnaryOpDerived extends UnaryOp implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/WhileDerived.java b/src/org/python/antlr/ast/WhileDerived.java
--- a/src/org/python/antlr/ast/WhileDerived.java
+++ b/src/org/python/antlr/ast/WhileDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class WhileDerived extends While implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class WhileDerived extends While implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/WithDerived.java b/src/org/python/antlr/ast/WithDerived.java
--- a/src/org/python/antlr/ast/WithDerived.java
+++ b/src/org/python/antlr/ast/WithDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class WithDerived extends With implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class WithDerived extends With implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/YieldDerived.java b/src/org/python/antlr/ast/YieldDerived.java
--- a/src/org/python/antlr/ast/YieldDerived.java
+++ b/src/org/python/antlr/ast/YieldDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class YieldDerived extends Yield implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class YieldDerived extends Yield implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/aliasDerived.java b/src/org/python/antlr/ast/aliasDerived.java
--- a/src/org/python/antlr/ast/aliasDerived.java
+++ b/src/org/python/antlr/ast/aliasDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class aliasDerived extends alias implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class aliasDerived extends alias implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/arguments.java b/src/org/python/antlr/ast/arguments.java
--- a/src/org/python/antlr/ast/arguments.java
+++ b/src/org/python/antlr/ast/arguments.java
@@ -17,6 +17,7 @@
import org.python.core.PyString;
import org.python.core.PyStringMap;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -278,4 +279,48 @@
addChild(t);
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (args != null) {
+ for (PyObject ob: args) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ if (defaults != null) {
+ for (PyObject ob: defaults) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null) {
+ return false;
+ } else if (args != null && args.contains(ob)) {
+ return true;
+ } else if (defaults != null && defaults.contains(ob)) {
+ return true;
+ } else {
+ return super.refersDirectlyTo(ob);
+ }
+ }
}
diff --git a/src/org/python/antlr/ast/argumentsDerived.java b/src/org/python/antlr/ast/argumentsDerived.java
--- a/src/org/python/antlr/ast/argumentsDerived.java
+++ b/src/org/python/antlr/ast/argumentsDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class argumentsDerived extends arguments implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class argumentsDerived extends arguments implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/comprehension.java b/src/org/python/antlr/ast/comprehension.java
--- a/src/org/python/antlr/ast/comprehension.java
+++ b/src/org/python/antlr/ast/comprehension.java
@@ -17,6 +17,7 @@
import org.python.core.PyString;
import org.python.core.PyStringMap;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -203,4 +204,42 @@
}
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (iter != null) {
+ retVal = visit.visit(iter, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (ifs != null) {
+ for (PyObject ob: ifs) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+
+ return target != null ? visit.visit(target, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null) {
+ return false;
+ } else if (ifs != null && ifs.contains(ob)) {
+ return true;
+ } else {
+ return ob == iter || ob == target || super.refersDirectlyTo(ob);
+ }
+ }
}
diff --git a/src/org/python/antlr/ast/comprehensionDerived.java b/src/org/python/antlr/ast/comprehensionDerived.java
--- a/src/org/python/antlr/ast/comprehensionDerived.java
+++ b/src/org/python/antlr/ast/comprehensionDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class comprehensionDerived extends comprehension implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class comprehensionDerived extends comprehension implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/ast/keyword.java b/src/org/python/antlr/ast/keyword.java
--- a/src/org/python/antlr/ast/keyword.java
+++ b/src/org/python/antlr/ast/keyword.java
@@ -17,6 +17,7 @@
import org.python.core.PyString;
import org.python.core.PyStringMap;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -153,4 +154,15 @@
}
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return value != null ? visit.visit(value, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == value || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/antlr/ast/keywordDerived.java b/src/org/python/antlr/ast/keywordDerived.java
--- a/src/org/python/antlr/ast/keywordDerived.java
+++ b/src/org/python/antlr/ast/keywordDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class keywordDerived extends keyword implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class keywordDerived extends keyword implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/AddDerived.java b/src/org/python/antlr/op/AddDerived.java
--- a/src/org/python/antlr/op/AddDerived.java
+++ b/src/org/python/antlr/op/AddDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class AddDerived extends Add implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class AddDerived extends Add implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/AndDerived.java b/src/org/python/antlr/op/AndDerived.java
--- a/src/org/python/antlr/op/AndDerived.java
+++ b/src/org/python/antlr/op/AndDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class AndDerived extends And implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class AndDerived extends And implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/AugLoadDerived.java b/src/org/python/antlr/op/AugLoadDerived.java
--- a/src/org/python/antlr/op/AugLoadDerived.java
+++ b/src/org/python/antlr/op/AugLoadDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class AugLoadDerived extends AugLoad implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class AugLoadDerived extends AugLoad implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/AugStoreDerived.java b/src/org/python/antlr/op/AugStoreDerived.java
--- a/src/org/python/antlr/op/AugStoreDerived.java
+++ b/src/org/python/antlr/op/AugStoreDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class AugStoreDerived extends AugStore implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class AugStoreDerived extends AugStore implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/BitAndDerived.java b/src/org/python/antlr/op/BitAndDerived.java
--- a/src/org/python/antlr/op/BitAndDerived.java
+++ b/src/org/python/antlr/op/BitAndDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class BitAndDerived extends BitAnd implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class BitAndDerived extends BitAnd implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/BitOrDerived.java b/src/org/python/antlr/op/BitOrDerived.java
--- a/src/org/python/antlr/op/BitOrDerived.java
+++ b/src/org/python/antlr/op/BitOrDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class BitOrDerived extends BitOr implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class BitOrDerived extends BitOr implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/BitXorDerived.java b/src/org/python/antlr/op/BitXorDerived.java
--- a/src/org/python/antlr/op/BitXorDerived.java
+++ b/src/org/python/antlr/op/BitXorDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class BitXorDerived extends BitXor implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class BitXorDerived extends BitXor implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/DelDerived.java b/src/org/python/antlr/op/DelDerived.java
--- a/src/org/python/antlr/op/DelDerived.java
+++ b/src/org/python/antlr/op/DelDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class DelDerived extends Del implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class DelDerived extends Del implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/DivDerived.java b/src/org/python/antlr/op/DivDerived.java
--- a/src/org/python/antlr/op/DivDerived.java
+++ b/src/org/python/antlr/op/DivDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class DivDerived extends Div implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class DivDerived extends Div implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/EqDerived.java b/src/org/python/antlr/op/EqDerived.java
--- a/src/org/python/antlr/op/EqDerived.java
+++ b/src/org/python/antlr/op/EqDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class EqDerived extends Eq implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class EqDerived extends Eq implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/FloorDivDerived.java b/src/org/python/antlr/op/FloorDivDerived.java
--- a/src/org/python/antlr/op/FloorDivDerived.java
+++ b/src/org/python/antlr/op/FloorDivDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class FloorDivDerived extends FloorDiv implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class FloorDivDerived extends FloorDiv implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/GtDerived.java b/src/org/python/antlr/op/GtDerived.java
--- a/src/org/python/antlr/op/GtDerived.java
+++ b/src/org/python/antlr/op/GtDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class GtDerived extends Gt implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class GtDerived extends Gt implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/GtEDerived.java b/src/org/python/antlr/op/GtEDerived.java
--- a/src/org/python/antlr/op/GtEDerived.java
+++ b/src/org/python/antlr/op/GtEDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class GtEDerived extends GtE implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class GtEDerived extends GtE implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/InDerived.java b/src/org/python/antlr/op/InDerived.java
--- a/src/org/python/antlr/op/InDerived.java
+++ b/src/org/python/antlr/op/InDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class InDerived extends In implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class InDerived extends In implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/InvertDerived.java b/src/org/python/antlr/op/InvertDerived.java
--- a/src/org/python/antlr/op/InvertDerived.java
+++ b/src/org/python/antlr/op/InvertDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class InvertDerived extends Invert implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class InvertDerived extends Invert implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/IsDerived.java b/src/org/python/antlr/op/IsDerived.java
--- a/src/org/python/antlr/op/IsDerived.java
+++ b/src/org/python/antlr/op/IsDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class IsDerived extends Is implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class IsDerived extends Is implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/IsNotDerived.java b/src/org/python/antlr/op/IsNotDerived.java
--- a/src/org/python/antlr/op/IsNotDerived.java
+++ b/src/org/python/antlr/op/IsNotDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class IsNotDerived extends IsNot implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class IsNotDerived extends IsNot implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/LShiftDerived.java b/src/org/python/antlr/op/LShiftDerived.java
--- a/src/org/python/antlr/op/LShiftDerived.java
+++ b/src/org/python/antlr/op/LShiftDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class LShiftDerived extends LShift implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class LShiftDerived extends LShift implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/LoadDerived.java b/src/org/python/antlr/op/LoadDerived.java
--- a/src/org/python/antlr/op/LoadDerived.java
+++ b/src/org/python/antlr/op/LoadDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class LoadDerived extends Load implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class LoadDerived extends Load implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/LtDerived.java b/src/org/python/antlr/op/LtDerived.java
--- a/src/org/python/antlr/op/LtDerived.java
+++ b/src/org/python/antlr/op/LtDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class LtDerived extends Lt implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class LtDerived extends Lt implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/LtEDerived.java b/src/org/python/antlr/op/LtEDerived.java
--- a/src/org/python/antlr/op/LtEDerived.java
+++ b/src/org/python/antlr/op/LtEDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class LtEDerived extends LtE implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class LtEDerived extends LtE implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/ModDerived.java b/src/org/python/antlr/op/ModDerived.java
--- a/src/org/python/antlr/op/ModDerived.java
+++ b/src/org/python/antlr/op/ModDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ModDerived extends Mod implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ModDerived extends Mod implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/MultDerived.java b/src/org/python/antlr/op/MultDerived.java
--- a/src/org/python/antlr/op/MultDerived.java
+++ b/src/org/python/antlr/op/MultDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class MultDerived extends Mult implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class MultDerived extends Mult implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/NotDerived.java b/src/org/python/antlr/op/NotDerived.java
--- a/src/org/python/antlr/op/NotDerived.java
+++ b/src/org/python/antlr/op/NotDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class NotDerived extends Not implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class NotDerived extends Not implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/NotEqDerived.java b/src/org/python/antlr/op/NotEqDerived.java
--- a/src/org/python/antlr/op/NotEqDerived.java
+++ b/src/org/python/antlr/op/NotEqDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class NotEqDerived extends NotEq implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class NotEqDerived extends NotEq implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/NotInDerived.java b/src/org/python/antlr/op/NotInDerived.java
--- a/src/org/python/antlr/op/NotInDerived.java
+++ b/src/org/python/antlr/op/NotInDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class NotInDerived extends NotIn implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class NotInDerived extends NotIn implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/OrDerived.java b/src/org/python/antlr/op/OrDerived.java
--- a/src/org/python/antlr/op/OrDerived.java
+++ b/src/org/python/antlr/op/OrDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class OrDerived extends Or implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class OrDerived extends Or implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/ParamDerived.java b/src/org/python/antlr/op/ParamDerived.java
--- a/src/org/python/antlr/op/ParamDerived.java
+++ b/src/org/python/antlr/op/ParamDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ParamDerived extends Param implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ParamDerived extends Param implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/PowDerived.java b/src/org/python/antlr/op/PowDerived.java
--- a/src/org/python/antlr/op/PowDerived.java
+++ b/src/org/python/antlr/op/PowDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PowDerived extends Pow implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PowDerived extends Pow implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/RShiftDerived.java b/src/org/python/antlr/op/RShiftDerived.java
--- a/src/org/python/antlr/op/RShiftDerived.java
+++ b/src/org/python/antlr/op/RShiftDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class RShiftDerived extends RShift implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class RShiftDerived extends RShift implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/StoreDerived.java b/src/org/python/antlr/op/StoreDerived.java
--- a/src/org/python/antlr/op/StoreDerived.java
+++ b/src/org/python/antlr/op/StoreDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class StoreDerived extends Store implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class StoreDerived extends Store implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/SubDerived.java b/src/org/python/antlr/op/SubDerived.java
--- a/src/org/python/antlr/op/SubDerived.java
+++ b/src/org/python/antlr/op/SubDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class SubDerived extends Sub implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class SubDerived extends Sub implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/UAddDerived.java b/src/org/python/antlr/op/UAddDerived.java
--- a/src/org/python/antlr/op/UAddDerived.java
+++ b/src/org/python/antlr/op/UAddDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class UAddDerived extends UAdd implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class UAddDerived extends UAdd implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/antlr/op/USubDerived.java b/src/org/python/antlr/op/USubDerived.java
--- a/src/org/python/antlr/op/USubDerived.java
+++ b/src/org/python/antlr/op/USubDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class USubDerived extends USub implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class USubDerived extends USub implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/AstList.java b/src/org/python/core/AstList.java
--- a/src/org/python/core/AstList.java
+++ b/src/org/python/core/AstList.java
@@ -20,7 +20,7 @@
import org.python.expose.MethodType;
@ExposedType(name = "_ast.astlist", base = PyList.class)
-public class AstList extends PySequence implements Cloneable, List {
+public class AstList extends PySequence implements Cloneable, List, Traverseproc {
public static final PyType TYPE = PyType.fromClass(AstList.class);
@@ -635,4 +635,22 @@
return Py.NoConversion;
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ for (Object ob: data) {
+ if (ob instanceof PyObject) {
+ retVal = visit.visit((PyObject) ob, arg);
+ if (retVal != 0) return retVal;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return data.contains(ob);
+ }
}
diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java
--- a/src/org/python/core/BaseBytes.java
+++ b/src/org/python/core/BaseBytes.java
@@ -48,6 +48,7 @@
* {@link #getBuilder(int)} to return instances of its own type. See the documentation of particular
* methods for more information.
*/
+ at Untraversable
public abstract class BaseBytes extends PySequence implements List<PyInteger> {
/**
diff --git a/src/org/python/core/BaseDictionaryView.java b/src/org/python/core/BaseDictionaryView.java
--- a/src/org/python/core/BaseDictionaryView.java
+++ b/src/org/python/core/BaseDictionaryView.java
@@ -9,7 +9,7 @@
import java.util.Iterator;
import org.python.core.PyObject;
-public abstract class BaseDictionaryView extends PyObject {
+public abstract class BaseDictionaryView extends PyObject implements Traverseproc {
protected final PyDictionary dvDict;
public BaseDictionaryView(PyDictionary dvDict) {
@@ -162,4 +162,16 @@
ts.exitRepr(this);
return buf.toString();
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return dvDict != null ? visit.visit(dvDict, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && dvDict == ob;
+ }
}
diff --git a/src/org/python/core/BaseSet.java b/src/org/python/core/BaseSet.java
--- a/src/org/python/core/BaseSet.java
+++ b/src/org/python/core/BaseSet.java
@@ -7,7 +7,7 @@
import java.util.Iterator;
import java.util.Set;
-public abstract class BaseSet extends PyObject implements Set {
+public abstract class BaseSet extends PyObject implements Set, Traverseproc {
/** The underlying Set. */
protected Set<PyObject> _set;
@@ -43,9 +43,9 @@
// Skip the iteration if both are sets
set.addAll(((BaseSet)data)._set);
} else {
- for (PyObject item : data.asIterable()) {
- set.add(item);
- }
+ for (PyObject item : data.asIterable()) {
+ set.add(item);
+ }
}
return set;
}
@@ -126,24 +126,24 @@
}
final PyObject baseset_difference(PyObject other) {
- return baseset_difference(new PyObject[] {other});
+ return baseset_difference(new PyObject[] {other});
}
final PyObject baseset_difference(PyObject [] args) {
- if (args.length == 0) {
- return BaseSet.makeNewSet(getType(), this);
- }
-
- BaseSet o = BaseSet.makeNewSet(getType(), this);
- for (PyObject item: args) {
- BaseSet bs = args[0] instanceof BaseSet ? (BaseSet)item : new PySet(item);
- Set<PyObject> set = bs._set;
+ if (args.length == 0) {
+ return BaseSet.makeNewSet(getType(), this);
+ }
+
+ BaseSet o = BaseSet.makeNewSet(getType(), this);
+ for (PyObject item: args) {
+ BaseSet bs = args[0] instanceof BaseSet ? (BaseSet)item : new PySet(item);
+ Set<PyObject> set = bs._set;
- for (PyObject p : set) {
- if (_set.contains(p)) {
- o._set.remove(p);
- }
- }
+ for (PyObject p : set) {
+ if (_set.contains(p)) {
+ o._set.remove(p);
+ }
+ }
}
return o;
}
@@ -348,7 +348,7 @@
final PyObject baseset_union(PyObject [] args) {
BaseSet result = BaseSet.makeNewSet(getType(), this);
for (PyObject item: args) {
- result._update(item);
+ result._update(item);
}
return result;
}
@@ -372,15 +372,15 @@
}
final PyObject baseset_intersection(PyObject [] args) {
- BaseSet result = BaseSet.makeNewSet(getType(), this);
- if (args.length == 0) {
- return result;
+ BaseSet result = BaseSet.makeNewSet(getType(), this);
+ if (args.length == 0) {
+ return result;
}
-
- for (PyObject other: args) {
- result = (BaseSet)result.baseset_intersection(other);
- }
- return result;
+
+ for (PyObject other: args) {
+ result = (BaseSet)result.baseset_intersection(other);
+ }
+ return result;
}
final PyObject baseset_copy() {
@@ -407,8 +407,8 @@
}
final PyObject baseset_isdisjoint(PyObject other) {
- BaseSet bs = other instanceof BaseSet ? (BaseSet)other : new PySet(other);
- return Collections.disjoint(_set, bs._set) ? Py.True : Py.False;
+ BaseSet bs = other instanceof BaseSet ? (BaseSet)other : new PySet(other);
+ return Collections.disjoint(_set, bs._set) ? Py.True : Py.False;
}
public String toString() {
@@ -599,4 +599,23 @@
}
return a;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retValue;
+ for (PyObject ob: _set) {
+ retValue = visit.visit(ob, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return _set.contains(ob);
+ }
}
diff --git a/src/org/python/core/ClasspathPyImporter.java b/src/org/python/core/ClasspathPyImporter.java
--- a/src/org/python/core/ClasspathPyImporter.java
+++ b/src/org/python/core/ClasspathPyImporter.java
@@ -11,6 +11,7 @@
import org.python.expose.ExposedType;
import org.python.util.Generic;
+ at Untraversable
@ExposedType(name="ClasspathPyImporter")
public class ClasspathPyImporter extends importer<String> {
diff --git a/src/org/python/core/ClasspathPyImporterDerived.java b/src/org/python/core/ClasspathPyImporterDerived.java
--- a/src/org/python/core/ClasspathPyImporterDerived.java
+++ b/src/org/python/core/ClasspathPyImporterDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ClasspathPyImporterDerived extends ClasspathPyImporter implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ClasspathPyImporterDerived extends ClasspathPyImporter implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,17 +26,35 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
public ClasspathPyImporterDerived(PyType subtype) {
super(subtype);
slots=new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return 0;
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/ContextGuard.java b/src/org/python/core/ContextGuard.java
--- a/src/org/python/core/ContextGuard.java
+++ b/src/org/python/core/ContextGuard.java
@@ -72,7 +72,7 @@
throw Py.TypeError("Argument must be a generator function.");
}
- private static class ContextCode extends PyBaseCode {
+ private static class ContextCode extends PyBaseCode implements Traverseproc {
private final PyBaseCode code;
ContextCode(PyBaseCode code) {
this.co_name = code.co_name;
@@ -116,10 +116,22 @@
}
};
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return code != null ? visit.visit(code, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == code;
+ }
}
@SuppressWarnings("serial")
- private static abstract class GeneratorContextManager extends PyObject implements ContextManager {
+ private static abstract class GeneratorContextManager extends PyObject implements ContextManager, Traverseproc {
final PyFrame frame;
public GeneratorContextManager(PyFrame frame) {
@@ -155,5 +167,17 @@
}
abstract PyObject body(ThreadState ts);
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return frame != null ? visit.visit(frame, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == frame;
+ }
}
}
diff --git a/src/org/python/core/IdImpl.java b/src/org/python/core/IdImpl.java
--- a/src/org/python/core/IdImpl.java
+++ b/src/org/python/core/IdImpl.java
@@ -73,12 +73,19 @@
private long sequentialId;
public synchronized long id(PyObject o) {
+ Object id = JyAttribute.getAttr(o, JyAttribute.PY_ID_ATTR);
+ if (id != null) {
+ return ((Long) id).longValue();
+ }
Object javaProxy = o.getJavaProxy();
+ long result;
if (javaProxy != null) {
- return java_obj_id(javaProxy);
+ result = java_obj_id(javaProxy);
} else {
- return java_obj_id(o);
+ result = java_obj_id(o);
}
+ JyAttribute.setAttr(o, JyAttribute.PY_ID_ATTR, result);
+ return result;
}
public String idstr(PyObject o) {
diff --git a/src/org/python/core/JavaImporter.java b/src/org/python/core/JavaImporter.java
--- a/src/org/python/core/JavaImporter.java
+++ b/src/org/python/core/JavaImporter.java
@@ -3,6 +3,7 @@
/**
* Load Java classes.
*/
+ at Untraversable
public class JavaImporter extends PyObject {
public static final String JAVA_IMPORT_PATH_ENTRY = "__classpath__";
diff --git a/src/org/python/core/JavaProxyList.java b/src/org/python/core/JavaProxyList.java
--- a/src/org/python/core/JavaProxyList.java
+++ b/src/org/python/core/JavaProxyList.java
@@ -19,6 +19,7 @@
class JavaProxyList {
+ @Untraversable
private static class ListMethod extends PyBuiltinMethodNarrow {
protected ListMethod(String name, int numArgs) {
super(name, numArgs);
@@ -116,7 +117,7 @@
if (stop < start) {
stop = start;
}
- if (value.javaProxy == this.list) {
+ if (JyAttribute.getAttr(value, JyAttribute.JAVA_PROXY_ATTR) == this.list) {
List xs = Generic.list();
xs.addAll(this.list);
setsliceList(start, stop, step, xs);
@@ -205,7 +206,7 @@
}
}
-
+ @Untraversable
private static class ListMulProxyClass extends ListMethod {
protected ListMulProxyClass(String name, int numArgs) {
super(name, numArgs);
diff --git a/src/org/python/core/JavaProxyMap.java b/src/org/python/core/JavaProxyMap.java
--- a/src/org/python/core/JavaProxyMap.java
+++ b/src/org/python/core/JavaProxyMap.java
@@ -8,10 +8,9 @@
* Proxy Java objects implementing java.util.List with Python methods
* corresponding to the standard list type
*/
-
-
class JavaProxyMap {
+ @Untraversable
private static class MapMethod extends PyBuiltinMethodNarrow {
protected MapMethod(String name, int numArgs) {
super(name, numArgs);
@@ -26,6 +25,7 @@
}
}
+ @Untraversable
private static class MapClassMethod extends PyBuiltinClassMethodNarrow {
protected MapClassMethod(String name, int minArgs, int maxArgs) {
super(name, minArgs, maxArgs);
diff --git a/src/org/python/core/JavaProxySet.java b/src/org/python/core/JavaProxySet.java
--- a/src/org/python/core/JavaProxySet.java
+++ b/src/org/python/core/JavaProxySet.java
@@ -9,10 +9,12 @@
import java.util.NoSuchElementException;
import java.util.Set;
-/** Proxy objects implementing java.util.Set */
-
+/**
+ * Proxy objects implementing java.util.Set
+ */
class JavaProxySet {
+ @Untraversable
private static class SetMethod extends PyBuiltinMethodNarrow {
protected SetMethod(String name, int numArgs) {
@@ -106,6 +108,7 @@
diff.removeAll(other);
return diff;
}
+
protected void differenceUpdate(Collection other) {
asSet().removeAll(other);
}
@@ -118,6 +121,7 @@
}
return intersection;
}
+
protected void intersectUpdate(Collection[] others) {
Set<Object> selfSet = asSet();
for (Collection other : others) {
@@ -131,6 +135,7 @@
u.addAll(other);
return u;
}
+
protected void update(Collection<Object> other) {
asSet().addAll(other);
}
@@ -153,6 +158,7 @@
}
}
+ @Untraversable
private static class SetMethodVarargs extends SetMethod {
protected SetMethodVarargs(String name) {
super(name, 0, -1);
@@ -289,6 +295,8 @@
return Py.newBoolean(!isEqual(other) && isSubset(other));
}
};
+
+ @Untraversable
private static class IsSubsetMethod extends SetMethod {
// __le__, issubset
@@ -301,6 +309,8 @@
return Py.newBoolean(isSubset(other));
}
}
+
+ @Untraversable
private static class IsSupersetMethod extends SetMethod {
// __ge__, issuperset
@@ -313,12 +323,14 @@
return Py.newBoolean(isSuperset(other));
}
}
+
private static final SetMethod gtProxy = new SetMethod("__gt__", 1) {
@Override
public PyObject __call__(PyObject other) {
return Py.newBoolean(!isEqual(other) && isSuperset(other));
}
};
+
private static final SetMethod isDisjointProxy = new SetMethod("isdisjoint", 1) {
@Override
public PyObject __call__(PyObject other) {
@@ -332,6 +344,7 @@
return makePySet(difference(getCombinedJavaCollections(others)));
}
};
+
private static final SetMethod differenceUpdateProxy = new SetMethodVarargs("difference_update") {
@Override
public PyObject __call__(PyObject[] others) {
@@ -339,12 +352,14 @@
return Py.None;
}
};
+
private static final SetMethod subProxy = new SetMethod("__sub__", 1) {
@Override
public PyObject __call__(PyObject other) {
return makePySet(difference(getJavaSet(self, "-", other)));
}
};
+
private static final SetMethod isubProxy = new SetMethod("__isub__", 1) {
@Override
public PyObject __call__(PyObject other) {
@@ -359,6 +374,7 @@
return makePySet(intersect(getJavaCollections(others)));
}
};
+
private static final SetMethod intersectionUpdateProxy = new SetMethodVarargs("intersection_update") {
@Override
public PyObject __call__(PyObject[] others) {
@@ -366,12 +382,14 @@
return Py.None;
}
};
+
private static final SetMethod andProxy = new SetMethod("__and__", 1) {
@Override
public PyObject __call__(PyObject other) {
return makePySet(intersect(new Collection[]{getJavaSet(self, "&", other)}));
}
};
+
private static final SetMethod iandProxy = new SetMethod("__iand__", 1) {
@Override
public PyObject __call__(PyObject other) {
@@ -386,6 +404,7 @@
return makePySet(symDiff(getJavaCollection(other)));
}
};
+
private static final SetMethod symDiffUpdateProxy = new SetMethod("symmetric_difference_update", 1) {
@Override
public PyObject __call__(PyObject other) {
@@ -393,12 +412,14 @@
return Py.None;
}
};
+
private static final SetMethod xorProxy = new SetMethod("__xor__", 1) {
@Override
public PyObject __call__(PyObject other) {
return makePySet(symDiff(getJavaSet(self, "^", other)));
}
};
+
private static final SetMethod ixorProxy = new SetMethod("__ixor__", 1) {
@Override
public PyObject __call__(PyObject other) {
@@ -413,6 +434,7 @@
return makePySet(union(getCombinedJavaCollections(others)));
}
};
+
private static final SetMethod updateProxy = new SetMethodVarargs("update") {
@Override
public PyObject __call__(PyObject[] others) {
@@ -420,12 +442,14 @@
return Py.None;
}
};
+
private static final SetMethod orProxy = new SetMethod("__or__", 1) {
@Override
public PyObject __call__(PyObject other) {
return makePySet(union(getJavaSet(self, "|", other)));
}
};
+
private static final SetMethod iorProxy = new SetMethod("__ior__", 1) {
@Override
public PyObject __call__(PyObject other) {
@@ -434,6 +458,7 @@
}
};
+ @Untraversable
private static class CopyMethod extends SetMethod {
protected CopyMethod(String name) {
super(name, 0);
diff --git a/src/org/python/core/JyAttribute.java b/src/org/python/core/JyAttribute.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/core/JyAttribute.java
@@ -0,0 +1,308 @@
+package org.python.core;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * Manages a linked list of general purpose Object-attributes, which
+ * can be attached to arbitrary {@code PyObject}s. This method replaces
+ * the formerly used method of maintaining weak hash maps for such cases.
+ * These weak hash maps were used to map {@code PyObject}s to such
+ * attributes, for instance to attach
+ * {@link org.python.modules._weakref.GlobalRef}-objects in the
+ * {@link org.python.modules._weakref.WeakrefModule}.
+ * </p>
+ * <p>
+ * Attributes attached via the weak hash map method break, if the
+ * {@code PyObject} is resurrected in its finalizer. The
+ * {@code JyAttribute}-method is resurrection-safe.
+ * </p>
+ * <p>
+ * To reduce memory footprint of {@code PyObject}s, the fields for
+ * {@link org.python.core.finalization.FinalizeTrigger}s and
+ * {@code javaProxy} are included in the list; {@code javaProxy} always
+ * on top so there is no speed-regression,
+ * {@link org.python.core.finalization.FinalizeTrigger} on bottom,
+ * as it is usually never accessed.
+ * </p>
+ */
+public abstract class JyAttribute implements Serializable {
+ /* ordered by priority; indices >= 0 indicate transient attributes.
+ since it is intended for rare use, 128 indices for ordinary and
+ transient attributes each should be enough in foreseeable future.
+ If needed, it would be trivial to change format to short.
+ */
+ public static final byte JAVA_PROXY_ATTR = Byte.MIN_VALUE;
+
+ /**
+ * Stores list of weak references linking to this PyObject.
+ * This list is weakref-based, so it does not keep the
+ * weakrefs alive. This is the only way to find out which
+ * weakrefs (i.e. org.python.modules._weakref.AbstractReference)
+ * linked to the object after a resurrection. A weak
+ * hashmap-based approach for this purpose would break on
+ * resurrection.
+ */
+ public static final byte WEAK_REF_ATTR = 0; //first transient
+
+ /**
+ * Reserved for use by JyNI.
+ */
+ public static final byte JYNI_HANDLE_ATTR = 1;
+
+ /**
+ * Allows the id of a {@link org.python.core.PyObject} to persist
+ * resurrection of that object.
+ */
+ public static final byte PY_ID_ATTR = 2;
+
+ /**
+ * Holds the current thread for an AbstractReference while
+ * referent-retrieval is pending due to a potentially
+ * restored-by-resurrection weak reference. After the
+ * restore has happened or the clear was confirmed, the
+ * thread is interrupted and the attribute is cleared.
+ */
+ public static final byte WEAKREF_PENDING_GET_ATTR = 3;
+
+ /**
+ * Used by gc module to mark cyclic trash. Searching for cyclic
+ * trash is usually not required by Jython. It is only done if
+ * gc features are enabled that mimic CPython behavior.
+ */
+ public static final byte GC_CYCLE_MARK_ATTR = 4;
+
+ /**
+ * Used by gc module to mark monitored objects before they
+ * become unmonitored for deletion. In case of a resurrection
+ * this is the only way for gc to detect that the object was
+ * to be monitored and should be monitored again.
+ */
+ //public static final byte GC_MONITOR_MARK_ATTR = 5;
+
+ /**
+ * Used by gc module to mark finalizable objects that might have
+ * been resurrected during a delayed finalization process.
+ */
+ public static final byte GC_DELAYED_FINALIZE_CRITIC_MARK_ATTR = 6;
+
+ public static final byte FINALIZE_TRIGGER_ATTR = Byte.MAX_VALUE;
+ private static byte nonBuiltinAttrTypeOffset = Byte.MIN_VALUE+1;
+ private static byte nonBuiltinTransientAttrTypeOffset = 7;
+
+ /**
+ * Reserves and returns a new attr type for custom use.
+ *
+ * @return an attr type for custom use
+ */
+ public static byte reserveCustomAttrType() {
+ if (nonBuiltinAttrTypeOffset == 0) {
+ throw new IllegalStateException("No more attr types available.");
+ }
+ return nonBuiltinAttrTypeOffset++;
+ }
+
+ /**
+ * Reserves and returns a new transient attr type for custom use.
+ *
+ * @return a transient attr type for custom use
+ */
+ public static byte reserveTransientCustomAttrType() {
+ if (nonBuiltinTransientAttrTypeOffset == Byte.MAX_VALUE) {
+ throw new IllegalStateException("No more transient attr types available.");
+ }
+ return nonBuiltinTransientAttrTypeOffset++;
+ }
+
+ byte attr_type;
+
+ static class AttributeLink extends JyAttribute {
+ JyAttribute next;
+ Object value;
+
+ protected AttributeLink(byte attr_type, Object value) {
+ super(attr_type);
+ this.value = value;
+ }
+
+ protected JyAttribute getNext() {
+ return next;
+ }
+
+ protected void setNext(JyAttribute next) {
+ this.next = next;
+ }
+
+ protected Object getValue() {
+ return value;
+ }
+
+ protected void setValue(Object value) {
+ this.value = value;
+ }
+ }
+
+ static class TransientAttributeLink extends JyAttribute {
+ transient JyAttribute next;
+ transient Object value;
+
+ protected TransientAttributeLink(byte attr_type, Object value) {
+ super(attr_type);
+ this.value = value;
+ }
+
+ protected JyAttribute getNext() {
+ return next;
+ }
+
+ protected void setNext(JyAttribute next) {
+ this.next = next;
+ }
+
+ protected Object getValue() {
+ return value;
+ }
+
+ protected void setValue(Object value) {
+ this.value = value;
+ }
+ }
+
+ protected JyAttribute(byte attr_type) {
+ this.attr_type = attr_type;
+ }
+
+ protected abstract JyAttribute getNext();
+ protected abstract void setNext(JyAttribute next);
+ protected abstract Object getValue();
+ protected abstract void setValue(Object value);
+
+ /**
+ * Checks whether the given {@code PyObject} has an attribute
+ * of the given type attached.
+ */
+ public static synchronized boolean hasAttr(PyObject ob, byte attr_type) {
+ if (ob.attributes == null) {
+ return false;
+ }
+ if (!(ob.attributes instanceof JyAttribute)) {
+ return attr_type == JAVA_PROXY_ATTR;
+ }
+ JyAttribute att = (JyAttribute) ob.attributes;
+ while (att != null && att.attr_type < attr_type) {
+ att = att.getNext();
+ }
+ return att != null && att.attr_type == attr_type;
+ }
+
+ /**
+ * Retrieves the attribute of the given type from the given
+ * {@code PyObject}.
+ * If no attribute of the given type is attached, null is returned.
+ */
+ public static synchronized Object getAttr(PyObject ob, byte attr_type) {
+ if (ob.attributes == null) {
+ return null;
+ }
+ if (!(ob.attributes instanceof JyAttribute)) {
+ return attr_type == JAVA_PROXY_ATTR ? ob.attributes : null;
+ }
+ JyAttribute att = (JyAttribute) ob.attributes;
+ while (att != null && att.attr_type < attr_type) {
+ att = att.getNext();
+ }
+ return att != null && att.attr_type == attr_type ? att.getValue() : null;
+ }
+
+ public static synchronized void debugPrintAttributes(PyObject o, java.io.PrintStream out) {
+ out.println("debugPrintAttributes of "+System.identityHashCode(o)+":");
+ if (o.attributes == null) {
+ out.println("null");
+ } else if (!(o.attributes instanceof JyAttribute)) {
+ out.println("only javaProxy");
+ } else {
+ JyAttribute att = (JyAttribute) o.attributes;
+ while (att != null) {
+ out.println("att type: "+att.attr_type+" value: "+att.getValue());
+ att = att.getNext();
+ }
+ }
+ out.println("debugPrintAttributes done");
+ }
+
+ public static synchronized void setAttr(PyObject ob, byte attr_type, Object value) {
+ if (value == null) {
+ delAttr(ob, attr_type);
+ } else {
+ if (ob.attributes == null) {
+ if (attr_type == JyAttribute.JAVA_PROXY_ATTR) {
+ ob.attributes = value;
+ } else {
+ ob.attributes = attr_type < 0 ?
+ new AttributeLink(attr_type, value) :
+ new TransientAttributeLink(attr_type, value);
+ }
+ } else if (!(ob.attributes instanceof JyAttribute)) {
+ if (attr_type == JyAttribute.JAVA_PROXY_ATTR) {
+ ob.attributes = value;
+ } else {
+ ob.attributes = new AttributeLink(JyAttribute.JAVA_PROXY_ATTR, ob.attributes);
+ ((JyAttribute) ob.attributes).setNext(attr_type < 0 ?
+ new AttributeLink(attr_type, value) :
+ new TransientAttributeLink(attr_type, value));
+ }
+ } else {
+ JyAttribute att = (JyAttribute) ob.attributes;
+ if (att.attr_type > attr_type) {
+ JyAttribute newAtt = attr_type < 0 ?
+ new AttributeLink(attr_type, value) :
+ new TransientAttributeLink(attr_type, value);
+ newAtt.setNext(att);
+ ob.attributes = newAtt;
+ } else {
+ while (att.getNext() != null && att.getNext().attr_type <= attr_type) {
+ att = att.getNext();
+ }
+ if (att.attr_type == attr_type) {
+ att.setValue(value);
+ } else if (att.getNext() == null) {
+ att.setNext(attr_type < 0 ?
+ new AttributeLink(attr_type, value) :
+ new TransientAttributeLink(attr_type, value));
+ } else {
+ JyAttribute newAtt = attr_type < 0 ?
+ new AttributeLink(attr_type, value) :
+ new TransientAttributeLink(attr_type, value);
+ newAtt.setNext(att.getNext());
+ att.setNext(newAtt);
+ }
+ }
+ }
+ }
+ }
+
+ public static synchronized void delAttr(PyObject ob, byte attr_type) {
+ if (ob.attributes == null) {
+ return;
+ } else if (attr_type == JAVA_PROXY_ATTR && !(ob.attributes instanceof JyAttribute)) {
+ ob.attributes = null;
+ }
+ JyAttribute att = (JyAttribute) ob.attributes;
+ if (att.attr_type == attr_type) {
+ ob.attributes = att.getNext();
+ } else {
+ while (att.getNext() != null && att.getNext().attr_type < attr_type) {
+ att = att.getNext();
+ }
+ if (att.getNext() != null && att.getNext().attr_type == attr_type) {
+ att.setNext(att.getNext().getNext());
+ }
+ }
+ if (ob.attributes != null) {
+ att = (JyAttribute) ob.attributes;
+ if (att.getNext() == null && att.attr_type == JyAttribute.JAVA_PROXY_ATTR) {
+ ob.attributes = att.getValue();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/python/core/Py.java b/src/org/python/core/Py.java
--- a/src/org/python/core/Py.java
+++ b/src/org/python/core/Py.java
@@ -34,6 +34,8 @@
import org.python.antlr.base.mod;
import org.python.core.adapter.ClassicPyObjectAdapter;
import org.python.core.adapter.ExtensiblePyObjectAdapter;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.modules.posix.PosixModule;
import org.python.util.Generic;
@@ -988,10 +990,10 @@
PyObject instance = (PyObject)(ThreadContext.initializingProxy.get()[0]);
ThreadState ts = Py.getThreadState();
if (instance != null) {
- if (instance.javaProxy != null) {
+ if (JyAttribute.hasAttr(instance, JyAttribute.JAVA_PROXY_ATTR)) {
throw Py.TypeError("Proxy instance reused");
}
- instance.javaProxy = proxy;
+ JyAttribute.setAttr(instance, JyAttribute.JAVA_PROXY_ATTR, proxy);
proxy._setPyInstance(instance);
proxy._setPySystemState(ts.systemState);
return;
@@ -1014,7 +1016,7 @@
pargs = Py.javas2pys(args);
}
instance = pyc.__call__(pargs);
- instance.javaProxy = proxy;
+ JyAttribute.setAttr(instance, JyAttribute.JAVA_PROXY_ATTR, proxy);
proxy._setPyInstance(instance);
proxy._setPySystemState(ts.systemState);
}
@@ -2273,7 +2275,7 @@
/**
* A code object wrapper for a python function.
*/
-class JavaCode extends PyCode {
+class JavaCode extends PyCode implements Traverseproc {
private PyObject func;
@@ -2337,12 +2339,25 @@
PyObject[] defaults, PyObject closure) {
return func.__call__(arg1, arg2, arg3, arg4);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return func != null ? visit.visit(func, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == func;
+ }
}
/**
* A function object wrapper for a java method which comply with the
* PyArgsKeywordsCall standard.
*/
+ at Untraversable
class JavaFunc extends PyObject {
Method method;
diff --git a/src/org/python/core/Py2kBuffer.java b/src/org/python/core/Py2kBuffer.java
--- a/src/org/python/core/Py2kBuffer.java
+++ b/src/org/python/core/Py2kBuffer.java
@@ -21,6 +21,7 @@
* arguments the same (one-dimensional byte-array) types. Their behaviour differs as detailed in the
* documentation.
*/
+ at Untraversable
@ExposedType(name = "buffer", doc = BuiltinDocs.buffer_doc, base = PyObject.class,
isBaseType = false)
public class Py2kBuffer extends PySequence implements BufferProtocol {
diff --git a/src/org/python/core/PyArray.java b/src/org/python/core/PyArray.java
--- a/src/org/python/core/PyArray.java
+++ b/src/org/python/core/PyArray.java
@@ -22,6 +22,7 @@
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
import org.python.expose.MethodType;
+import org.python.modules.gc;
/**
* A wrapper class around native java arrays.
@@ -30,8 +31,9 @@
* <p>
* See also the jarray module.
*/
+
@ExposedType(name = "array.array", base = PyObject.class)
-public class PyArray extends PySequence implements Cloneable, BufferProtocol {
+public class PyArray extends PySequence implements Cloneable, BufferProtocol, Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyArray.class);
@@ -2150,4 +2152,23 @@
}
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (data == null || !gc.canLinkToPyObject(data.getClass(), true)) {
+ return 0;
+ }
+ return gc.traverseByReflection(data, visit, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob)
+ throws UnsupportedOperationException {
+ if (data == null || !gc.canLinkToPyObject(data.getClass(), true)) {
+ return false;
+ }
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/src/org/python/core/PyArrayDerived.java b/src/org/python/core/PyArrayDerived.java
--- a/src/org/python/core/PyArrayDerived.java
+++ b/src/org/python/core/PyArrayDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyArrayDerived extends PyArray implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyArrayDerived extends PyArray implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyBaseException.java b/src/org/python/core/PyBaseException.java
--- a/src/org/python/core/PyBaseException.java
+++ b/src/org/python/core/PyBaseException.java
@@ -13,7 +13,7 @@
*
*/
@ExposedType(name = "exceptions.BaseException", doc = BuiltinDocs.BaseException_doc)
-public class PyBaseException extends PyObject {
+public class PyBaseException extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyBaseException.class);
@@ -257,4 +257,29 @@
}
message = null;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retValue;
+ if (message != null) {
+ retValue = visit.visit(message, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ if (args != null) {
+ retValue = visit.visit(args, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ return __dict__ != null ? visit.visit(__dict__, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == message || ob == args || ob == __dict__);
+ }
}
diff --git a/src/org/python/core/PyBaseExceptionDerived.java b/src/org/python/core/PyBaseExceptionDerived.java
--- a/src/org/python/core/PyBaseExceptionDerived.java
+++ b/src/org/python/core/PyBaseExceptionDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyBaseExceptionDerived extends PyBaseException implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyBaseExceptionDerived extends PyBaseException implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,17 +26,35 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
public PyBaseExceptionDerived(PyType subtype) {
super(subtype);
slots=new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return 0;
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyBeanEvent.java b/src/org/python/core/PyBeanEvent.java
--- a/src/org/python/core/PyBeanEvent.java
+++ b/src/org/python/core/PyBeanEvent.java
@@ -3,6 +3,7 @@
import java.lang.reflect.Method;
+ at Untraversable
public class PyBeanEvent<T> extends PyObject {
public Method addMethod;
diff --git a/src/org/python/core/PyBeanEventProperty.java b/src/org/python/core/PyBeanEventProperty.java
--- a/src/org/python/core/PyBeanEventProperty.java
+++ b/src/org/python/core/PyBeanEventProperty.java
@@ -9,6 +9,7 @@
import org.python.util.Generic;
+ at Untraversable
public class PyBeanEventProperty extends PyObject {
private static Map<String, Class<?>> adapterClasses = Generic.map();
diff --git a/src/org/python/core/PyBeanProperty.java b/src/org/python/core/PyBeanProperty.java
--- a/src/org/python/core/PyBeanProperty.java
+++ b/src/org/python/core/PyBeanProperty.java
@@ -2,6 +2,7 @@
package org.python.core;
import java.lang.reflect.*;
+ at Untraversable
public class PyBeanProperty extends PyReflectedField {
public Method getMethod, setMethod;
public Class<?> myType;
diff --git a/src/org/python/core/PyBoolean.java b/src/org/python/core/PyBoolean.java
--- a/src/org/python/core/PyBoolean.java
+++ b/src/org/python/core/PyBoolean.java
@@ -10,6 +10,7 @@
* The builtin python bool. It would be nice if it didn't extend PyInteger,
* but too hard to avoid pre-Python 2.2 semantics here.
*/
+ at Untraversable
@ExposedType(name = "bool", isBaseType = false, doc = BuiltinDocs.bool_doc)
public class PyBoolean extends PyInteger {
diff --git a/src/org/python/core/PyBuiltinCallable.java b/src/org/python/core/PyBuiltinCallable.java
--- a/src/org/python/core/PyBuiltinCallable.java
+++ b/src/org/python/core/PyBuiltinCallable.java
@@ -6,6 +6,7 @@
import org.python.expose.ExposedGet;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "builtin_function_or_method", isBaseType = false)
public abstract class PyBuiltinCallable extends PyObject {
diff --git a/src/org/python/core/PyBuiltinFunction.java b/src/org/python/core/PyBuiltinFunction.java
--- a/src/org/python/core/PyBuiltinFunction.java
+++ b/src/org/python/core/PyBuiltinFunction.java
@@ -2,6 +2,7 @@
import org.python.expose.ExposeAsSuperclass;
+ at Untraversable
public class PyBuiltinFunction extends PyBuiltinCallable implements ExposeAsSuperclass {
protected PyBuiltinFunction(String name, String doc) {
diff --git a/src/org/python/core/PyBuiltinFunctionNarrow.java b/src/org/python/core/PyBuiltinFunctionNarrow.java
--- a/src/org/python/core/PyBuiltinFunctionNarrow.java
+++ b/src/org/python/core/PyBuiltinFunctionNarrow.java
@@ -1,5 +1,6 @@
package org.python.core;
+ at Untraversable
public class PyBuiltinFunctionNarrow extends PyBuiltinFunction {
protected PyBuiltinFunctionNarrow(String name, int minargs, int maxargs, String doc) {
diff --git a/src/org/python/core/PyBuiltinFunctionSet.java b/src/org/python/core/PyBuiltinFunctionSet.java
--- a/src/org/python/core/PyBuiltinFunctionSet.java
+++ b/src/org/python/core/PyBuiltinFunctionSet.java
@@ -8,6 +8,7 @@
* method with a switch on the index number.
*
*/
+ at Untraversable
public class PyBuiltinFunctionSet extends PyBuiltinFunctionNarrow {
// used as an index into a big switch statement in the various derived
diff --git a/src/org/python/core/PyBuiltinMethod.java b/src/org/python/core/PyBuiltinMethod.java
--- a/src/org/python/core/PyBuiltinMethod.java
+++ b/src/org/python/core/PyBuiltinMethod.java
@@ -3,7 +3,7 @@
import org.python.expose.ExposeAsSuperclass;
public abstract class PyBuiltinMethod extends PyBuiltinCallable implements ExposeAsSuperclass,
- Cloneable {
+ Cloneable, Traverseproc {
protected PyObject self;
@@ -71,4 +71,16 @@
int compareTo = info.getName().compareTo(otherMethod.info.getName());
return compareTo < 0 ? -1 : compareTo > 0 ? 1 : 0;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return self != null ? visit.visit(self, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == self;
+ }
}
diff --git a/src/org/python/core/PyBuiltinMethodNarrow.java b/src/org/python/core/PyBuiltinMethodNarrow.java
--- a/src/org/python/core/PyBuiltinMethodNarrow.java
+++ b/src/org/python/core/PyBuiltinMethodNarrow.java
@@ -15,7 +15,6 @@
this(name, numArgs, numArgs);
}
-
/**
* Creates a method for the given name that takes at least <code>minArgs</code> and at most
* <code>maxArgs</code> arguments.
diff --git a/src/org/python/core/PyBuiltinMethodSet.java b/src/org/python/core/PyBuiltinMethodSet.java
--- a/src/org/python/core/PyBuiltinMethodSet.java
+++ b/src/org/python/core/PyBuiltinMethodSet.java
@@ -1,7 +1,7 @@
/* Copyright (c) Jython Developers */
package org.python.core;
-public class PyBuiltinMethodSet extends PyBuiltinFunctionSet implements Cloneable {
+public class PyBuiltinMethodSet extends PyBuiltinFunctionSet implements Cloneable, Traverseproc {
private Class<?> type;
@@ -57,4 +57,16 @@
public String toString() {
return String.format("<built-in method %s>", info.getName());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return visit.visit(__self__, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob == __self__;
+ }
}
diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java
--- a/src/org/python/core/PyByteArray.java
+++ b/src/org/python/core/PyByteArray.java
@@ -22,6 +22,7 @@
* This may relate to parameters, or to the target object itself (in text that applies equally to
* base or sibling classes).
*/
+ at Untraversable
@ExposedType(name = "bytearray", base = PyObject.class, doc = BuiltinDocs.bytearray_doc)
public class PyByteArray extends BaseBytes implements BufferProtocol {
diff --git a/src/org/python/core/PyByteArrayDerived.java b/src/org/python/core/PyByteArrayDerived.java
--- a/src/org/python/core/PyByteArrayDerived.java
+++ b/src/org/python/core/PyByteArrayDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyByteArrayDerived extends PyByteArray implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyByteArrayDerived extends PyByteArray implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyBytecode.java b/src/org/python/core/PyBytecode.java
--- a/src/org/python/core/PyBytecode.java
+++ b/src/org/python/core/PyBytecode.java
@@ -4,7 +4,7 @@
import java.util.Arrays;
import java.util.List;
-public class PyBytecode extends PyBaseCode {
+public class PyBytecode extends PyBaseCode implements Traverseproc {
// for debugging
private int count = 0; // total number of opcodes run so far in this code obj
@@ -170,11 +170,12 @@
RETURN, /* 'return' statement */
BREAK, /* 'break' statement */
CONTINUE, /* 'continue' statement */
- YIELD /* 'yield' operator */
+ YIELD /* 'yield' operator */
};
// to enable why's to be stored on a PyStack
+ @Untraversable
private static class PyStackWhy extends PyObject {
Why why;
@@ -189,7 +190,7 @@
}
}
- private static class PyStackException extends PyObject {
+ private static class PyStackException extends PyObject implements Traverseproc {
PyException exception;
@@ -201,6 +202,18 @@
public String toString() {
return String.format("PyStackException<%s,%s,%.100s>", exception.type, exception.value, exception.traceback);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return exception != null ? exception.traverse(visit, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && exception.refersDirectlyTo(ob);
+ }
}
private static String stringify_blocks(PyFrame f) {
@@ -257,7 +270,7 @@
protected PyObject interpret(PyFrame f, ThreadState ts) {
final PyStack stack = new PyStack(co_stacksize);
int next_instr = -1;
- int opcode; /* Current opcode */
+ int opcode; /* Current opcode */
int oparg = 0; /* Current opcode argument, if any */
Why why = Why.NOT;
PyObject retval = null;
@@ -1479,13 +1492,14 @@
}
}
+ @Untraversable
private static class PyTryBlock extends PyObject { // purely to sit on top of the existing PyFrame in f_exits!!!
- int b_type; /* what kind of block this is */
+ int b_type; /* what kind of block this is */
- int b_handler; /* where to jump to find handler */
+ int b_handler; /* where to jump to find handler */
- int b_level; /* value stack level to pop to */
+ int b_level; /* value stack level to pop to */
PyTryBlock(int type, int handler, int level) {
@@ -1609,6 +1623,36 @@
}
return x;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retValue;
+ if (co_consts != null) {
+ for (PyObject ob: co_consts) {
+ if (ob != null) {
+ retValue = visit.visit(ob, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null || co_consts == null) {
+ return false;
+ } else {
+ for (PyObject obj: co_consts) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
}
-
-
diff --git a/src/org/python/core/PyCallIter.java b/src/org/python/core/PyCallIter.java
--- a/src/org/python/core/PyCallIter.java
+++ b/src/org/python/core/PyCallIter.java
@@ -1,6 +1,7 @@
package org.python.core;
public class PyCallIter extends PyIterator {
+ //note: Already implements Traverseproc, inheriting it from PyIterator
private PyObject callable;
@@ -36,4 +37,26 @@
}
return result;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retValue = super.traverse(visit, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ if (callable != null) {
+ retValue = visit.visit(callable, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ return sentinel != null ? visit.visit(sentinel, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == callable || ob == sentinel || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/core/PyCell.java b/src/org/python/core/PyCell.java
--- a/src/org/python/core/PyCell.java
+++ b/src/org/python/core/PyCell.java
@@ -10,7 +10,7 @@
* Cells are used to implement variables referenced by multiple scopes.
*/
@ExposedType(name = "cell", isBaseType = false)
-public class PyCell extends PyObject {
+public class PyCell extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyCell.class);
@@ -37,4 +37,16 @@
return String.format("<cell at %s: %.80s object at %s>", Py.idstr(this),
ob_ref.getType().getName(), Py.idstr(ob_ref));
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return ob_ref != null ? visit.visit(ob_ref, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob_ref == ob;
+ }
}
diff --git a/src/org/python/core/PyClass.java b/src/org/python/core/PyClass.java
--- a/src/org/python/core/PyClass.java
+++ b/src/org/python/core/PyClass.java
@@ -9,7 +9,7 @@
* The classic Python class.
*/
@ExposedType(name = "classobj", isBaseType = false)
-public class PyClass extends PyObject {
+public class PyClass extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyClass.class);
@@ -188,7 +188,7 @@
PyInstance inst;
inst = new PyInstance(this);
if (__del__ != null) {
- inst.finalizeTrigger = FinalizeTrigger.makeTrigger(inst);
+ FinalizeTrigger.ensureFinalizer(inst);
}
inst.__init__(args, keywords);
return inst;
@@ -281,4 +281,66 @@
}
__name__ = name;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (__bases__ != null) {
+ retVal = visit.visit(__bases__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__dict__ != null) {
+ retVal = visit.visit(__dict__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ //CPython also traverses the name, which is not stored
+ //as a PyObject in Jython.
+ //Py_VISIT(o->cl_name);
+ if (__getattr__ != null) {
+ retVal = visit.visit(__getattr__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__setattr__ != null) {
+ retVal = visit.visit(__setattr__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__delattr__ != null) {
+ retVal = visit.visit(__delattr__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+
+ /* Jython-only */
+ if (__tojava__ != null) {
+ retVal = visit.visit(__tojava__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__del__ != null) {
+ retVal = visit.visit(__del__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return __contains__ != null ? visit.visit(__contains__, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (__dict__ == ob || __bases__ == ob
+ || __getattr__ == ob || __setattr__ == ob || __delattr__ == ob
+ || __tojava__ == ob || __del__ == ob || __contains__ == ob);
+ }
}
diff --git a/src/org/python/core/PyClassMethod.java b/src/org/python/core/PyClassMethod.java
--- a/src/org/python/core/PyClassMethod.java
+++ b/src/org/python/core/PyClassMethod.java
@@ -9,7 +9,7 @@
* The classmethod descriptor.
*/
@ExposedType(name = "classmethod", doc = BuiltinDocs.classmethod_doc)
-public class PyClassMethod extends PyObject {
+public class PyClassMethod extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyClassMethod.class);
@@ -50,4 +50,16 @@
}
return new PyMethod(callable, type, type.getType());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return callable != null ? visit.visit(callable, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == callable;
+ }
}
diff --git a/src/org/python/core/PyClassMethodDerived.java b/src/org/python/core/PyClassMethodDerived.java
--- a/src/org/python/core/PyClassMethodDerived.java
+++ b/src/org/python/core/PyClassMethodDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyClassMethodDerived extends PyClassMethod implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyClassMethodDerived extends PyClassMethod implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyClassMethodDescr.java b/src/org/python/core/PyClassMethodDescr.java
--- a/src/org/python/core/PyClassMethodDescr.java
+++ b/src/org/python/core/PyClassMethodDescr.java
@@ -5,6 +5,7 @@
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "classmethod_descriptor", isBaseType = false)
public class PyClassMethodDescr extends PyMethodDescr {
diff --git a/src/org/python/core/PyComplex.java b/src/org/python/core/PyComplex.java
--- a/src/org/python/core/PyComplex.java
+++ b/src/org/python/core/PyComplex.java
@@ -15,6 +15,7 @@
/**
* A builtin python complex number
*/
+ at Untraversable
@ExposedType(name = "complex", doc = BuiltinDocs.complex_doc)
public class PyComplex extends PyObject {
diff --git a/src/org/python/core/PyComplexDerived.java b/src/org/python/core/PyComplexDerived.java
--- a/src/org/python/core/PyComplexDerived.java
+++ b/src/org/python/core/PyComplexDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyComplexDerived extends PyComplex implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyComplexDerived extends PyComplex implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyCompoundCallable.java b/src/org/python/core/PyCompoundCallable.java
--- a/src/org/python/core/PyCompoundCallable.java
+++ b/src/org/python/core/PyCompoundCallable.java
@@ -5,7 +5,7 @@
import org.python.util.Generic;
-public class PyCompoundCallable extends PyObject {
+public class PyCompoundCallable extends PyObject implements Traverseproc {
private List<PyObject> callables = Generic.list();
@@ -31,4 +31,31 @@
public String toString() {
return "<CompoundCallable with " + callables.size() + " callables>";
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retValue;
+ if (systemState != null) {
+ retValue = visit.visit(systemState, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ if (callables != null) {
+ for (PyObject ob: callables) {
+ retValue = visit.visit(ob, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == systemState || callables.contains(ob));
+ }
}
diff --git a/src/org/python/core/PyDataDescr.java b/src/org/python/core/PyDataDescr.java
--- a/src/org/python/core/PyDataDescr.java
+++ b/src/org/python/core/PyDataDescr.java
@@ -12,6 +12,7 @@
* those methods, their respective implementsDescr* methods should be overriden
* as well.
*/
+ at Untraversable
@ExposedType(name = "getset_descriptor", base = PyObject.class, isBaseType = false)
public abstract class PyDataDescr extends PyDescriptor {
diff --git a/src/org/python/core/PyDescriptor.java b/src/org/python/core/PyDescriptor.java
--- a/src/org/python/core/PyDescriptor.java
+++ b/src/org/python/core/PyDescriptor.java
@@ -1,6 +1,6 @@
package org.python.core;
-public abstract class PyDescriptor extends PyObject {
+public abstract class PyDescriptor extends PyObject implements Traverseproc {
protected PyType dtype;
@@ -22,5 +22,17 @@
String msg = String.format("descriptor '%s' for '%s' objects doesn't apply to '%s' object",
name, dtype.fastGetName(), type.fastGetName());
throw Py.TypeError(msg);
- }
+ }
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return dtype != null ? visit.visit(dtype, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob == dtype;
+ }
}
diff --git a/src/org/python/core/PyDictProxy.java b/src/org/python/core/PyDictProxy.java
--- a/src/org/python/core/PyDictProxy.java
+++ b/src/org/python/core/PyDictProxy.java
@@ -10,7 +10,7 @@
*
*/
@ExposedType(name = "dictproxy", isBaseType = false)
-public class PyDictProxy extends PyObject {
+public class PyDictProxy extends PyObject implements Traverseproc {
/** The dict proxied to. */
PyObject dict;
@@ -145,4 +145,16 @@
public boolean isSequenceType() {
return false;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return dict == null ? 0 : visit.visit(dict, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == dict;
+ }
}
diff --git a/src/org/python/core/PyDictionary.java b/src/org/python/core/PyDictionary.java
--- a/src/org/python/core/PyDictionary.java
+++ b/src/org/python/core/PyDictionary.java
@@ -29,7 +29,7 @@
* A builtin python dictionary.
*/
@ExposedType(name = "dict", doc = BuiltinDocs.dict_doc)
-public class PyDictionary extends PyObject implements ConcurrentMap {
+public class PyDictionary extends PyObject implements ConcurrentMap, Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyDictionary.class);
{
@@ -300,38 +300,38 @@
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.dict___lt___doc)
final PyObject dict___lt__(PyObject otherObj) {
- int result = __cmp__(otherObj);
- if (result == -2) {
- return null;
- }
- return result < 0 ? Py.True : Py.False;
+ int result = __cmp__(otherObj);
+ if (result == -2) {
+ return null;
+ }
+ return result < 0 ? Py.True : Py.False;
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.dict___gt___doc)
final PyObject dict___gt__(PyObject otherObj) {
- int result = __cmp__(otherObj);
- if (result == -2) {
- return null;
- }
- return result > 0 ? Py.True : Py.False;
+ int result = __cmp__(otherObj);
+ if (result == -2) {
+ return null;
+ }
+ return result > 0 ? Py.True : Py.False;
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.dict___le___doc)
final PyObject dict___le__(PyObject otherObj) {
- int result = __cmp__(otherObj);
- if (result == -2) {
- return null;
- }
- return result <= 0 ? Py.True : Py.False;
+ int result = __cmp__(otherObj);
+ if (result == -2) {
+ return null;
+ }
+ return result <= 0 ? Py.True : Py.False;
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.dict___ge___doc)
final PyObject dict___ge__(PyObject otherObj) {
- int result = __cmp__(otherObj);
- if (result == -2) {
- return null;
- }
- return result >= 0 ? Py.True : Py.False;
+ int result = __cmp__(otherObj);
+ if (result == -2) {
+ return null;
+ }
+ return result >= 0 ? Py.True : Py.False;
}
@Override
@@ -716,7 +716,7 @@
*/
@ExposedMethod(doc = BuiltinDocs.dict_viewkeys_doc)
public PyObject viewkeys() {
- return new PyDictionaryViewKeys(this);
+ return new PyDictionaryViewKeys(this);
}
/**
@@ -732,7 +732,7 @@
*/
@ExposedMethod(doc = BuiltinDocs.dict_viewvalues_doc)
public PyObject viewvalues() {
- return new PyDictionaryViewValues(this);
+ return new PyDictionaryViewValues(this);
}
@ExposedMethod(doc = BuiltinDocs.dict_itervalues_doc)
@@ -1165,6 +1165,30 @@
return tojava(getMap().replace(Py.java2py(key), Py.java2py(value)));
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ for (Map.Entry<PyObject, PyObject> ent: internalMap.entrySet()) {
+ retVal = visit.visit(ent.getKey(), arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (ent.getValue() != null) {
+ retVal = visit.visit(ent.getValue(), arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (internalMap.containsKey(ob) || internalMap.containsValue(ob));
+ }
}
/** Basic implementation of Entry that just holds onto a key and value and returns them. */
diff --git a/src/org/python/core/PyDictionaryDerived.java b/src/org/python/core/PyDictionaryDerived.java
--- a/src/org/python/core/PyDictionaryDerived.java
+++ b/src/org/python/core/PyDictionaryDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyDictionaryDerived extends PyDictionary implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyDictionaryDerived extends PyDictionary implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,16 +75,20 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyDictionaryDerived(PyType subtype,ConcurrentMap backingMap,boolean useBackingMap) {
super(subtype,backingMap,useBackingMap);
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
diff --git a/src/org/python/core/PyEllipsis.java b/src/org/python/core/PyEllipsis.java
--- a/src/org/python/core/PyEllipsis.java
+++ b/src/org/python/core/PyEllipsis.java
@@ -8,6 +8,7 @@
/**
* A class representing the singleton Ellipsis <code>...</code> object.
*/
+ at Untraversable
@ExposedType(name = "ellipsis", base = PyObject.class, isBaseType = false)
public class PyEllipsis extends PySingleton implements Serializable {
diff --git a/src/org/python/core/PyEnumerate.java b/src/org/python/core/PyEnumerate.java
--- a/src/org/python/core/PyEnumerate.java
+++ b/src/org/python/core/PyEnumerate.java
@@ -10,6 +10,7 @@
*/
@ExposedType(name = "enumerate", base = PyObject.class, doc = BuiltinDocs.enumerate_doc)
public class PyEnumerate extends PyIterator {
+ //note: Already implements Traverseproc, inheriting it from PyIterator
public static final PyType TYPE = PyType.fromClass(PyEnumerate.class);
@@ -88,4 +89,26 @@
return next;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retValue = super.traverse(visit, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ if (index != null) {
+ retValue = visit.visit(index, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ return sit == null ? 0 : visit.visit(sit, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == index || ob == sit || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/core/PyEnumerateDerived.java b/src/org/python/core/PyEnumerateDerived.java
--- a/src/org/python/core/PyEnumerateDerived.java
+++ b/src/org/python/core/PyEnumerateDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyEnumerateDerived extends PyEnumerate implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyEnumerateDerived extends PyEnumerate implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyException.java b/src/org/python/core/PyException.java
--- a/src/org/python/core/PyException.java
+++ b/src/org/python/core/PyException.java
@@ -7,7 +7,7 @@
* subclasses of PyException. Instead the python exception class is stored in the <code>type</code>
* field and value or class instance is stored in the <code>value</code> field.
*/
-public class PyException extends RuntimeException
+public class PyException extends RuntimeException implements Traverseproc
{
/**
@@ -332,4 +332,32 @@
public static String exceptionClassName(PyObject obj) {
return obj instanceof PyClass ? ((PyClass)obj).__name__ : ((PyType)obj).fastGetName();
}
+
+
+ /* Traverseproc support */
+
+ public int traverse(Visitproc visit, Object arg) {
+ int retValue;
+ if (type != null) {
+ retValue = visit.visit(type, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ } if (value != null) {
+ retValue = visit.visit(value, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ } if (traceback != null) {
+ retValue = visit.visit(traceback, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ return 0;
+ }
+
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (type == ob || value == ob || traceback == ob);
+ }
}
diff --git a/src/org/python/core/PyFastSequenceIter.java b/src/org/python/core/PyFastSequenceIter.java
--- a/src/org/python/core/PyFastSequenceIter.java
+++ b/src/org/python/core/PyFastSequenceIter.java
@@ -9,6 +9,7 @@
*/
@ExposedType(name = "fastsequenceiterator", base = PyObject.class, isBaseType = false)
public class PyFastSequenceIter extends PyIterator {
+ //note: Already implements Traverseproc, inheriting it from PyIterator
public static final PyType TYPE = PyType.fromClass(PyFastSequenceIter.class);
@@ -48,4 +49,20 @@
}
return result;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retValue = super.traverse(visit, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ return seq == null ? 0 : visit.visit(seq, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == seq || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/core/PyFile.java b/src/org/python/core/PyFile.java
--- a/src/org/python/core/PyFile.java
+++ b/src/org/python/core/PyFile.java
@@ -35,7 +35,7 @@
* The Python file type. Wraps an {@link TextIOBase} object.
*/
@ExposedType(name = "file", doc = BuiltinDocs.file_doc)
-public class PyFile extends PyObject implements FinalizableBuiltin {
+public class PyFile extends PyObject implements FinalizableBuiltin, Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyFile.class);
@@ -82,26 +82,24 @@
/** The file's closer object; ensures the file is closed at
* shutdown */
private Closer closer;
-
- public FinalizeTrigger finalizeTrigger;
- public PyFile() {finalizeTrigger = FinalizeTrigger.makeTrigger(this);}
+ public PyFile() {FinalizeTrigger.ensureFinalizer(this);}
public PyFile(PyType subType) {
super(subType);
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
public PyFile(RawIOBase raw, String name, String mode, int bufsize) {
parseMode(mode);
file___init__(raw, name, mode, bufsize);
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
public PyFile(InputStream istream, String name, String mode, int bufsize, boolean closefd) {
parseMode(mode);
file___init__(new StreamIO(istream, closefd), name, mode, bufsize);
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
/**
@@ -133,7 +131,7 @@
public PyFile(OutputStream ostream, String name, String mode, int bufsize, boolean closefd) {
parseMode(mode);
file___init__(new StreamIO(ostream, closefd), name, mode, bufsize);
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
/**
@@ -161,7 +159,7 @@
public PyFile(String name, String mode, int bufsize) {
file___init__(new FileIO(name, parseMode(mode)), name, mode, bufsize);
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
@ExposedNew
@@ -733,5 +731,14 @@
}
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return name == null ? 0 : visit.visit(name, arg);
+ }
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == name;
+ }
}
diff --git a/src/org/python/core/PyFileDerived.java b/src/org/python/core/PyFileDerived.java
--- a/src/org/python/core/PyFileDerived.java
+++ b/src/org/python/core/PyFileDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyFileDerived extends PyFile implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyFileDerived extends PyFile implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyFileReader.java b/src/org/python/core/PyFileReader.java
--- a/src/org/python/core/PyFileReader.java
+++ b/src/org/python/core/PyFileReader.java
@@ -8,7 +8,7 @@
import java.io.IOException;
import java.io.BufferedReader;
-
+ at Untraversable
public class PyFileReader extends PyObject
{
static final int DEFAULT_BUF_SIZE = 1024;
diff --git a/src/org/python/core/PyFileWriter.java b/src/org/python/core/PyFileWriter.java
--- a/src/org/python/core/PyFileWriter.java
+++ b/src/org/python/core/PyFileWriter.java
@@ -10,6 +10,7 @@
import java.io.Writer;
import java.io.IOException;
+ at Untraversable
public class PyFileWriter extends PyObject {
private final Writer writer;
diff --git a/src/org/python/core/PyFloat.java b/src/org/python/core/PyFloat.java
--- a/src/org/python/core/PyFloat.java
+++ b/src/org/python/core/PyFloat.java
@@ -20,6 +20,7 @@
/**
* A builtin python float.
*/
+ at Untraversable
@ExposedType(name = "float", doc = BuiltinDocs.float_doc)
public class PyFloat extends PyObject {
diff --git a/src/org/python/core/PyFloatDerived.java b/src/org/python/core/PyFloatDerived.java
--- a/src/org/python/core/PyFloatDerived.java
+++ b/src/org/python/core/PyFloatDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyFloatDerived extends PyFloat implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyFloatDerived extends PyFloat implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyFrame.java b/src/org/python/core/PyFrame.java
--- a/src/org/python/core/PyFrame.java
+++ b/src/org/python/core/PyFrame.java
@@ -13,7 +13,7 @@
* A Python frame object.
*/
@ExposedType(name = "frame", isBaseType = false)
-public class PyFrame extends PyObject {
+public class PyFrame extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyFrame.class);
@@ -363,4 +363,178 @@
public void to_cell(int parm_index, int env_index) {
f_env[env_index].ob_ref = f_fastlocals[parm_index];
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (f_back != null) {
+ retVal = visit.visit(f_back, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (f_code != null) {
+ retVal = visit.visit(f_code, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (f_builtins != null) {
+ retVal = visit.visit(f_builtins, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (f_globals != null) {
+ retVal = visit.visit(f_globals, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (f_locals != null) {
+ retVal = visit.visit(f_locals, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (tracefunc != null && tracefunc instanceof Traverseproc) {
+ retVal = ((Traverseproc) tracefunc).traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+
+// CPython also features fields for an exception.
+// These are not present in PyFrame in Jython:
+// Py_VISIT(f->f_exc_type);
+// Py_VISIT(f->f_exc_value);
+// Py_VISIT(f->f_exc_traceback);
+
+ /* locals */
+ if (f_fastlocals != null) {
+ for (PyObject ob: f_fastlocals) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+
+ if (f_savedlocals != null) {
+ for (Object ob: f_savedlocals) {
+ if (ob != null) {
+ if (ob instanceof PyObject) {
+ retVal = visit.visit((PyObject) ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ } else if (ob instanceof Traverseproc) {
+ retVal = ((Traverseproc) ob).traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ }
+
+ /* Jython-only miscellaneous */
+ if (f_env != null) {
+ for (PyCell ob: f_env) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+
+ if (generatorInput != null) {
+ if (generatorInput instanceof PyObject) {
+ retVal = visit.visit((PyObject) generatorInput, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ } else if (generatorInput instanceof Traverseproc) {
+ retVal = ((Traverseproc) generatorInput).traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+
+ if (f_exits != null) {
+ for (PyObject ob: f_exits) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+
+// CPython also traverses the stack. This seems to be not necessary
+// in Jython since there is no stack-equivalent in PyFrame:
+//
+// /* stack */
+// if (f->f_stacktop != NULL) {
+// for (p = f->f_valuestack; p < f->f_stacktop; p++)
+// Py_VISIT(*p);
+// }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ if (ob == null) {
+ return false;
+ } else if (ob == f_back || ob == f_code || ob == f_builtins
+ || ob == f_globals || ob == f_locals || ob == generatorInput) {
+ return true;
+ }
+
+ if (f_fastlocals != null) {
+ for (PyObject obj: f_fastlocals) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ }
+ if (f_env != null) {
+ for (PyObject obj: f_env) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ }
+ if (f_exits != null) {
+ for (PyObject obj: f_exits) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ }
+ if (f_savedlocals != null) {
+ for (Object obj: f_savedlocals) {
+ if (obj == ob) {
+ return true;
+ } else if (obj != null && obj instanceof Traverseproc
+ &&((Traverseproc) obj).refersDirectlyTo(ob)) {
+ return true;
+ }
+ }
+ }
+ if (tracefunc != null && tracefunc instanceof Traverseproc
+ &&((Traverseproc) tracefunc).refersDirectlyTo(ob)) {
+ return true;
+ }
+ return generatorInput instanceof Traverseproc ?
+ ((Traverseproc) generatorInput).refersDirectlyTo(ob) : false;
+ }
}
diff --git a/src/org/python/core/PyFrozenSetDerived.java b/src/org/python/core/PyFrozenSetDerived.java
--- a/src/org/python/core/PyFrozenSetDerived.java
+++ b/src/org/python/core/PyFrozenSetDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyFrozenSetDerived extends PyFrozenSet implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyFrozenSetDerived extends PyFrozenSet implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyFunction.java b/src/org/python/core/PyFunction.java
--- a/src/org/python/core/PyFunction.java
+++ b/src/org/python/core/PyFunction.java
@@ -16,7 +16,7 @@
* A Python function.
*/
@ExposedType(name = "function", isBaseType = false, doc = BuiltinDocs.function_doc)
-public class PyFunction extends PyObject implements InvocationHandler {
+public class PyFunction extends PyObject implements InvocationHandler, Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyFunction.class);
@@ -544,4 +544,69 @@
@Override
public boolean isSequenceType() { return false; }
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ //globals cannot be null
+ int retVal = visit.visit(__globals__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (__code__ != null) {
+ retVal = visit.visit(__code__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ //__module__ cannot be null
+ retVal = visit.visit(__module__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (__defaults__ != null) {
+ for (PyObject ob: __defaults__) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ //__doc__ cannot be null
+ retVal = visit.visit(__doc__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+
+// CPython also traverses the name, which is not stored
+// as a PyObject in Jython:
+// Py_VISIT(f->func_name);
+
+ if (__dict__ != null) {
+ retVal = visit.visit(__dict__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return __closure__ != null ? visit.visit(__closure__, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null) {
+ return false;
+ }
+ if (__defaults__ != null) {
+ for (PyObject obj: __defaults__) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ }
+ return ob == __doc__ || ob == __globals__ || ob == __code__
+ || ob == __dict__ || ob == __closure__ || ob == __module__;
+ }
}
diff --git a/src/org/python/core/PyGenerator.java b/src/org/python/core/PyGenerator.java
--- a/src/org/python/core/PyGenerator.java
+++ b/src/org/python/core/PyGenerator.java
@@ -22,8 +22,6 @@
protected boolean gi_running;
private PyObject closure;
-
- public FinalizeTrigger finalizeTrigger;
public PyGenerator(PyFrame frame, PyObject closure) {
super(TYPE);
@@ -32,7 +30,7 @@
gi_code = gi_frame.f_code;
}
this.closure = closure;
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
public PyObject send(PyObject value) {
@@ -173,4 +171,33 @@
}
return result;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retValue = super.traverse(visit, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ if (gi_frame != null) {
+ retValue = visit.visit(gi_frame, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ if (gi_code != null) {
+ retValue = visit.visit(gi_code, arg);
+ if (retValue != 0) {
+ return retValue;
+ }
+ }
+ return closure == null ? 0 : visit.visit(closure, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == gi_frame || ob == gi_code
+ || ob == closure || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/core/PyInstance.java b/src/org/python/core/PyInstance.java
--- a/src/org/python/core/PyInstance.java
+++ b/src/org/python/core/PyInstance.java
@@ -13,11 +13,10 @@
* An instance of a classic Python class.
*/
@ExposedType(name = "instance", isBaseType = false)
-public class PyInstance extends PyObject implements FinalizablePyObject {
+public class PyInstance extends PyObject implements FinalizablePyObject, Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyInstance.class);
- public FinalizeTrigger finalizeTrigger;
private static JavaFunc __ensure_finalizer__Function;
// xxx doc, final name
@@ -81,7 +80,6 @@
private void writeObject(java.io.ObjectOutputStream out)
throws java.io.IOException {
- //System.out.println("writing: "+getClass().getName());
out.defaultWriteObject();
PyObject name = instclass.__findattr__("__module__");
if (!(name instanceof PyString) || name == Py.None) {
@@ -154,8 +152,7 @@
}
public static void ensureFinalizer(PyObject[] args, String[] kws) {
- ((PyInstance) args[0]).finalizeTrigger = FinalizeTrigger.makeTrigger(
- (PyInstance) args[0]);
+ FinalizeTrigger.ensureFinalizer((PyInstance) args[0]);
}
private static JavaFunc makeFunction__ensure_finalizer__() {
@@ -171,9 +168,9 @@
if (name == "__class__") return instclass;
if (name == "__ensure_finalizer__") {
if (__ensure_finalizer__Function == null) {
- __ensure_finalizer__Function = makeFunction__ensure_finalizer__();
+ __ensure_finalizer__Function = makeFunction__ensure_finalizer__();
}
- return new PyMethod(__ensure_finalizer__Function, this, instclass);
+ return new PyMethod(__ensure_finalizer__Function, this, instclass);
}
if (__dict__ == null) return null;
@@ -288,8 +285,9 @@
if (name == "__class__") {
if (value instanceof PyClass) {
instclass = (PyClass) value;
- if (instclass.__del__ != null && finalizeTrigger == null) {
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ if (instclass.__del__ != null &&
+ !JyAttribute.hasAttr(this, JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__class__ must be set to a class");
@@ -306,8 +304,8 @@
} else {
__dict__.__setitem__(name, value);
}
- if (name == "__del__" && finalizeTrigger == null) {
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ if (name == "__del__" && !JyAttribute.hasAttr(this, JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
}
@@ -1942,7 +1940,7 @@
@Override
public void __del__() {
- try {
+ try {
PyObject method = __findattr__("__del__");
if (method != null) {
method.__call__();
@@ -1960,4 +1958,26 @@
Py.writeUnraisable(exc, method);
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+// Potential PyObject refs in PyInstance:
+// public transient PyClass instclass;
+// public PyObject __dict__;
+ if (instclass != null) {
+ int retVal = visit.visit(instclass, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ //__dict__ cannot be null
+ return visit.visit(__dict__, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == instclass || ob == __dict__);
+ }
}
diff --git a/src/org/python/core/PyInteger.java b/src/org/python/core/PyInteger.java
--- a/src/org/python/core/PyInteger.java
+++ b/src/org/python/core/PyInteger.java
@@ -19,6 +19,7 @@
/**
* A builtin python int.
*/
+ at Untraversable
@ExposedType(name = "int", doc = BuiltinDocs.int_doc)
public class PyInteger extends PyObject {
diff --git a/src/org/python/core/PyIntegerDerived.java b/src/org/python/core/PyIntegerDerived.java
--- a/src/org/python/core/PyIntegerDerived.java
+++ b/src/org/python/core/PyIntegerDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyIntegerDerived extends PyInteger implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyIntegerDerived extends PyInteger implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyIterator.java b/src/org/python/core/PyIterator.java
--- a/src/org/python/core/PyIterator.java
+++ b/src/org/python/core/PyIterator.java
@@ -14,7 +14,7 @@
* If the implementation raises a StopIteration exception, it should be stored in stopException so
* the correct exception can be thrown to preserve the line numbers in the traceback.
*/
-public abstract class PyIterator extends PyObject implements Iterable<Object> {
+public abstract class PyIterator extends PyObject implements Iterable<Object>, Traverseproc {
protected PyException stopException;
@@ -75,7 +75,7 @@
return iterator();
}
if (c.isAssignableFrom(Collection.class)) {
- List<Object> list = new ArrayList();
+ List<Object> list = new ArrayList<>();
for (Object obj : this) {
list.add(obj);
}
@@ -83,4 +83,16 @@
}
return super.__tojava__(c);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return stopException != null ? stopException.traverse(visit, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && stopException != null && stopException.refersDirectlyTo(ob);
+ }
}
diff --git a/src/org/python/core/PyJavaPackage.java b/src/org/python/core/PyJavaPackage.java
--- a/src/org/python/core/PyJavaPackage.java
+++ b/src/org/python/core/PyJavaPackage.java
@@ -4,25 +4,22 @@
package org.python.core;
import org.python.core.packagecache.PackageManager;
-
import java.util.StringTokenizer;
/**
* A representation of java package.
*/
-
-public class PyJavaPackage extends PyObject {
+public class PyJavaPackage extends PyObject implements Traverseproc {
public String __name__;
public PyStringMap __dict__;
- //public String _unparsedAll;
+
/** Its keys are the names of statically known classes.
* E.g. from jars pre-scan.
*/
public PyStringMap clsSet;
public String __file__;
- //public PyList __all__;
/** (Control) package manager whose hierarchy contains this java pkg.
*/
@@ -134,7 +131,7 @@
return addPackage(name);
}
- Class c = __mgr__.findClass(__name__,name);
+ Class<?> c = __mgr__.findClass(__name__,name);
if (c != null) return addClass(name,c);
if (name == "__name__") return new PyString(__name__);
@@ -170,4 +167,28 @@
public String toString() {
return "<java package "+__name__+" "+Py.idstr(this)+">";
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ //__dict__ cannot be null
+ int retVal = visit.visit(__dict__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+
+ //clsSet cannot be null
+ retVal = visit.visit(clsSet, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ //__mgr__ and __mgr__.topLevelPackage cannot be null
+ return visit.visit(__mgr__.topLevelPackage, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == __dict__ || ob == clsSet || ob == __mgr__.topLevelPackage);
+ }
}
diff --git a/src/org/python/core/PyJavaType.java b/src/org/python/core/PyJavaType.java
--- a/src/org/python/core/PyJavaType.java
+++ b/src/org/python/core/PyJavaType.java
@@ -84,7 +84,7 @@
public static PyObject wrapJavaObject(Object o) {
PyObject obj = new PyObjectDerived(PyType.fromClass(o.getClass(), false));
- obj.javaProxy = o;
+ JyAttribute.setAttr(obj, JyAttribute.JAVA_PROXY_ATTR, o);
return obj;
}
@@ -233,7 +233,7 @@
computeLinearMro(baseClass);
} else {
needsInners.add(this);
- javaProxy = forClass;
+ JyAttribute.setAttr(this, JyAttribute.JAVA_PROXY_ATTR, forClass);
objtype = PyType.fromClassSkippingInners(Class.class, needsInners);
// Wrapped Java types fill in their mro first using all of their interfaces then their
// super class.
@@ -253,11 +253,11 @@
}
visibleBases.add(PyType.fromClassSkippingInners(iface, needsInners));
}
- if (javaProxy == Object.class) {
+ if (JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR) == Object.class) {
base = PyType.fromClassSkippingInners(PyObject.class, needsInners);
} else if(baseClass == null) {
base = PyType.fromClassSkippingInners(Object.class, needsInners);
- }else if (javaProxy == Class.class) {
+ }else if (JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR) == Class.class) {
base = PyType.fromClassSkippingInners(PyType.class, needsInners);
} else {
base = PyType.fromClassSkippingInners(baseClass, needsInners);
@@ -893,6 +893,9 @@
protected abstract boolean getResult(int comparison);
}
+ // Traverseproc-note: Usually we would have to traverse this class, but we can
+ // leave this out, since CollectionProxies is only used locally in private
+ // static fields.
private static class CollectionProxies {
final Map<Class<?>, PyBuiltinMethod[]> proxies;
final Map<Class<?>, PyBuiltinMethod[]> postProxies;
@@ -923,7 +926,7 @@
* injected methods.
*/
private static Map<Class<?>, PyBuiltinMethod[]> buildCollectionProxies() {
- final Map<Class<?>, PyBuiltinMethod[]> proxies = new HashMap();
+ final Map<Class<?>, PyBuiltinMethod[]> proxies = new HashMap<>();
PyBuiltinMethodNarrow iterableProxy = new PyBuiltinMethodNarrow("__iter__") {
@Override
@@ -983,10 +986,46 @@
}
private static Map<Class<?>, PyBuiltinMethod[]> buildPostCollectionProxies() {
- final Map<Class<?>, PyBuiltinMethod[]> postProxies = new HashMap();
+ final Map<Class<?>, PyBuiltinMethod[]> postProxies = new HashMap<>();
postProxies.put(List.class, JavaProxyList.getPostProxyMethods());
postProxies.put(Map.class, JavaProxyMap.getPostProxyMethods());
postProxies.put(Set.class, JavaProxySet.getPostProxyMethods());
return Collections.unmodifiableMap(postProxies);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (conflicted != null) {
+ for (PyObject ob: conflicted) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ if (ob == null) {
+ return false;
+ }
+ if (conflicted != null) {
+ for (PyObject obj: conflicted) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ }
+ return super.refersDirectlyTo(ob);
+ }
}
diff --git a/src/org/python/core/PyList.java b/src/org/python/core/PyList.java
--- a/src/org/python/core/PyList.java
+++ b/src/org/python/core/PyList.java
@@ -1224,4 +1224,27 @@
public synchronized boolean remove(Object o) {
return list.remove(Py.java2py(o));
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (list != null) {
+ int retVal;
+ for (PyObject ob: list) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return list == null ? false : list.contains(ob);
+ }
}
diff --git a/src/org/python/core/PyListDerived.java b/src/org/python/core/PyListDerived.java
--- a/src/org/python/core/PyListDerived.java
+++ b/src/org/python/core/PyListDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyListDerived extends PyList implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyListDerived extends PyList implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyLong.java b/src/org/python/core/PyLong.java
--- a/src/org/python/core/PyLong.java
+++ b/src/org/python/core/PyLong.java
@@ -21,6 +21,7 @@
/**
* A builtin python long. This is implemented as a java.math.BigInteger.
*/
+ at Untraversable
@ExposedType(name = "long", doc = BuiltinDocs.long_doc)
public class PyLong extends PyObject {
diff --git a/src/org/python/core/PyLongDerived.java b/src/org/python/core/PyLongDerived.java
--- a/src/org/python/core/PyLongDerived.java
+++ b/src/org/python/core/PyLongDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyLongDerived extends PyLong implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyLongDerived extends PyLong implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyMemoryView.java b/src/org/python/core/PyMemoryView.java
--- a/src/org/python/core/PyMemoryView.java
+++ b/src/org/python/core/PyMemoryView.java
@@ -15,7 +15,7 @@
*/
@ExposedType(name = "memoryview", doc = BuiltinDocs.memoryview_doc, base = PyObject.class,
isBaseType = false)
-public class PyMemoryView extends PySequence implements BufferProtocol {
+public class PyMemoryView extends PySequence implements BufferProtocol, Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyMemoryView.class);
@@ -843,4 +843,48 @@
}
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (backing != null) {
+ if (backing instanceof PyObject) {
+ retVal = visit.visit((PyObject) backing, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ } else if (backing instanceof Traverseproc) {
+ retVal = ((Traverseproc) backing).traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ if (shape != null) {
+ retVal = visit.visit(shape, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (strides != null) {
+ retVal = visit.visit(strides, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return suboffsets == null ? 0 : visit.visit(suboffsets, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob != null && (ob == backing || ob == shape || ob == strides
+ || ob == suboffsets)) {
+ return true;
+ } else if (suboffsets instanceof Traverseproc) {
+ return ((Traverseproc) suboffsets).refersDirectlyTo(ob);
+ } else {
+ return false;
+ }
+ }
}
diff --git a/src/org/python/core/PyMethod.java b/src/org/python/core/PyMethod.java
--- a/src/org/python/core/PyMethod.java
+++ b/src/org/python/core/PyMethod.java
@@ -16,7 +16,7 @@
* A Python method.
*/
@ExposedType(name = "instancemethod", isBaseType = false, doc = BuiltinDocs.instancemethod_doc)
-public class PyMethod extends PyObject implements InvocationHandler {
+public class PyMethod extends PyObject implements InvocationHandler, Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyMethod.class);
@@ -413,4 +413,28 @@
}
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (im_class != null) {
+ retVal = visit.visit(im_class, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__func__ != null) {
+ retVal = visit.visit(__func__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return __self__ == null ? 0 : visit.visit(__self__, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == im_class || ob == __func__ || ob == __self__);
+ }
}
diff --git a/src/org/python/core/PyMethodDescr.java b/src/org/python/core/PyMethodDescr.java
--- a/src/org/python/core/PyMethodDescr.java
+++ b/src/org/python/core/PyMethodDescr.java
@@ -5,7 +5,7 @@
import org.python.expose.ExposedType;
@ExposedType(name = "method_descriptor", base = PyObject.class, isBaseType = false)
-public class PyMethodDescr extends PyDescriptor implements PyBuiltinCallable.Info {
+public class PyMethodDescr extends PyDescriptor implements PyBuiltinCallable.Info, Traverseproc {
protected int minargs, maxargs;
@@ -92,4 +92,16 @@
public PyObject getObjClass() {
return dtype;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return meth == null ? 0 : visit.visit(meth, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == meth;
+ }
}
diff --git a/src/org/python/core/PyModule.java b/src/org/python/core/PyModule.java
--- a/src/org/python/core/PyModule.java
+++ b/src/org/python/core/PyModule.java
@@ -13,7 +13,7 @@
*
*/
@ExposedType(name = "module")
-public class PyModule extends PyObject {
+public class PyModule extends PyObject implements Traverseproc {
private final PyObject moduleDoc = new PyString(
"module(name[, doc])\n" +
"\n" +
@@ -193,4 +193,16 @@
__dict__ = new PyStringMap();
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return __dict__ == null ? 0 : visit.visit(__dict__, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == __dict__;
+ }
}
diff --git a/src/org/python/core/PyModuleDerived.java b/src/org/python/core/PyModuleDerived.java
--- a/src/org/python/core/PyModuleDerived.java
+++ b/src/org/python/core/PyModuleDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyModuleDerived extends PyModule implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyModuleDerived extends PyModule implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,17 +26,35 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
public PyModuleDerived(PyType subtype) {
super(subtype);
slots=new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return 0;
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyNewWrapper.java b/src/org/python/core/PyNewWrapper.java
--- a/src/org/python/core/PyNewWrapper.java
+++ b/src/org/python/core/PyNewWrapper.java
@@ -1,6 +1,6 @@
package org.python.core;
-public abstract class PyNewWrapper extends PyBuiltinMethod {
+public abstract class PyNewWrapper extends PyBuiltinMethod implements Traverseproc {
public PyType for_type;
@@ -70,4 +70,16 @@
System.arraycopy(args, 1, rest, 0, nargs - 1);
return new_impl(false, subtype, rest, keywords);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return for_type == null ? 0 : visit.visit(for_type, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == for_type;
+ }
}
diff --git a/src/org/python/core/PyNone.java b/src/org/python/core/PyNone.java
--- a/src/org/python/core/PyNone.java
+++ b/src/org/python/core/PyNone.java
@@ -12,6 +12,7 @@
/**
* The singleton None object.
*/
+ at Untraversable
@ExposedType(name = "NoneType", isBaseType = false)
public class PyNone extends PyObject implements Serializable {
diff --git a/src/org/python/core/PyNotImplemented.java b/src/org/python/core/PyNotImplemented.java
--- a/src/org/python/core/PyNotImplemented.java
+++ b/src/org/python/core/PyNotImplemented.java
@@ -3,6 +3,7 @@
import java.io.Serializable;
// XXX: isBaseType = false
+ at Untraversable
public class PyNotImplemented extends PySingleton implements Serializable
{
PyNotImplemented() {
diff --git a/src/org/python/core/PyObject.java b/src/org/python/core/PyObject.java
--- a/src/org/python/core/PyObject.java
+++ b/src/org/python/core/PyObject.java
@@ -8,7 +8,6 @@
import java.util.List;
import java.util.Map;
-import org.python.core.finalization.FinalizeTrigger;
import org.python.expose.ExposedClassMethod;
import org.python.expose.ExposedDelete;
import org.python.expose.ExposedGet;
@@ -17,6 +16,7 @@
import org.python.expose.ExposedSet;
import org.python.expose.ExposedType;
import org.python.util.Generic;
+import org.python.modules.gc;
/**
* All objects known to the Jython runtime system are represented by an instance
@@ -27,15 +27,31 @@
public static final PyType TYPE = PyType.fromClass(PyObject.class);
- /** The type of this object. */
+ /**
+ * This should have been suited at org.python.modules.gc, but that would cause
+ * a dependency cycle in the init-phases of gc.class and PyObject.class.
+ * Now this boolean mirrors the presence of the MONITOR_GLOBAL-flag of
+ * Jython's gc module.
+ */
+ public static boolean gcMonitorGlobal = false;
+
+ /** The type of this object.
+ */
protected PyType objtype;
/**
- * An underlying Java instance that this object is wrapping or is a subclass
- * of. Anything attempting to use the proxy should go through {@link #getJavaProxy()}
- * which ensures that it's initialized.
+ * {@code attributes} is a general purpose linked list of arbitrary
+ * Java objects that should be kept alive by this PyObject. These
+ * objects can be accessed by the methods and keys in
+ * {@link org.python.core.JyAttribute}.
+ * A notable attribute is the javaProxy (accessible via
+ * {@code JyAttribute.getAttr(this, JAVA_PROXY_ATTR)}),
+ * an underlying Java instance that this object is wrapping or is a
+ * subclass of. Anything attempting to use the proxy should go through
+ * {@link #getJavaProxy()} which ensures that it's initialized.
*/
- protected Object javaProxy;
+ //protected Object javaProxy;
+ protected Object attributes;
/** Primitives classes their wrapper classes. */
private static final Map<Class<?>, Class<?>> primitiveMap = Generic.map();
@@ -58,6 +74,8 @@
public PyObject(PyType objtype) {
this.objtype = objtype;
+ if (gcMonitorGlobal)
+ gc.monitorObject(this);
}
/**
@@ -66,6 +84,8 @@
**/
public PyObject() {
objtype = PyType.fromClass(getClass(), false);
+ if (gcMonitorGlobal)
+ gc.monitorObject(this);
}
/**
@@ -74,6 +94,8 @@
*/
PyObject(boolean ignored) {
objtype = (PyType)this;
+ if (gcMonitorGlobal)
+ gc.monitorObject(this);
}
@ExposedNew
@@ -156,6 +178,7 @@
*/
void proxyInit() {
Class<?> c = getType().getProxyType();
+ Object javaProxy = JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR);
if (javaProxy != null || c == null) {
return;
}
@@ -183,6 +206,7 @@
} finally {
ThreadContext.initializingProxy.set(previous);
}
+ javaProxy = JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR);
if (javaProxy != null && javaProxy != proxy) {
throw Py.TypeError("Proxy instance already initialized");
}
@@ -190,7 +214,7 @@
if (proxyInstance != null && proxyInstance != this) {
throw Py.TypeError("Proxy initialized with another instance");
}
- javaProxy = proxy;
+ JyAttribute.setAttr(this, JyAttribute.JAVA_PROXY_ATTR, proxy);
}
/**
@@ -306,7 +330,7 @@
**/
public Object __tojava__(Class<?> c) {
if ((c == Object.class || c == Serializable.class) && getJavaProxy() != null) {
- return javaProxy;
+ return JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR);
}
if (c.isInstance(this)) {
return this;
@@ -318,7 +342,7 @@
}
}
if (c.isInstance(getJavaProxy())) {
- return javaProxy;
+ return JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR);
}
// convert faux floats
@@ -338,10 +362,10 @@
}
protected synchronized Object getJavaProxy() {
- if (javaProxy == null) {
+ if (!JyAttribute.hasAttr(this, JyAttribute.JAVA_PROXY_ATTR)) {
proxyInit();
}
- return javaProxy;
+ return JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR);
}
/**
@@ -1684,7 +1708,10 @@
public PyObject _is(PyObject o) {
// Access javaProxy directly here as is is for object identity, and at best getJavaProxy
// will initialize a new object with a different identity
- return this == o || (javaProxy != null && javaProxy == o.javaProxy) ? Py.True : Py.False;
+ //return this == o || (javaProxy != null && javaProxy == o.javaProxy) ? Py.True : Py.False;
+ return this == o || (JyAttribute.hasAttr(this, JyAttribute.JAVA_PROXY_ATTR) &&
+ JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR) ==
+ JyAttribute.getAttr(o, JyAttribute.JAVA_PROXY_ATTR)) ? Py.True : Py.False;
}
/**
@@ -1696,7 +1723,10 @@
public PyObject _isnot(PyObject o) {
// Access javaProxy directly here as is is for object identity, and at best getJavaProxy
// will initialize a new object with a different identity
- return this != o && (javaProxy == null || javaProxy != o.javaProxy) ? Py.True : Py.False;
+ //return this != o && (javaProxy == null || javaProxy != o.javaProxy) ? Py.True : Py.False;
+ return this != o && (!JyAttribute.hasAttr(this, JyAttribute.JAVA_PROXY_ATTR) ||
+ JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR) !=
+ JyAttribute.getAttr(o, JyAttribute.JAVA_PROXY_ATTR)) ? Py.True : Py.False;
}
/**
@@ -4205,7 +4235,7 @@
* by hashing and comparing its elements by identity.
*/
-class PyIdentityTuple extends PyObject {
+class PyIdentityTuple extends PyObject implements Traverseproc {
PyObject[] list;
@@ -4241,4 +4271,34 @@
return true;
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (list != null) {
+ int retVal;
+ for (PyObject ob: list) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null || list == null) {
+ return false;
+ }
+ for (PyObject obj: list) {
+ if (ob == obj) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/src/org/python/core/PyObjectDerived.java b/src/org/python/core/PyObjectDerived.java
--- a/src/org/python/core/PyObjectDerived.java
+++ b/src/org/python/core/PyObjectDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyObjectDerived extends PyObject implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyObjectDerived extends PyObject implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyProperty.java b/src/org/python/core/PyProperty.java
--- a/src/org/python/core/PyProperty.java
+++ b/src/org/python/core/PyProperty.java
@@ -7,7 +7,7 @@
import org.python.expose.ExposedType;
@ExposedType(name = "property", doc = BuiltinDocs.property_doc)
-public class PyProperty extends PyObject {
+public class PyProperty extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyProperty.class);
@@ -160,4 +160,35 @@
return getType().__call__(get, set, del, doc);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (fget != null) {
+ retVal = visit.visit(fget, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (fset != null) {
+ retVal = visit.visit(fset, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (fdel != null) {
+ retVal = visit.visit(fdel, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return doc == null ? 0 : visit.visit(doc, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == fget || ob == fset || ob == fdel || ob == doc);
+ }
}
diff --git a/src/org/python/core/PyPropertyDerived.java b/src/org/python/core/PyPropertyDerived.java
--- a/src/org/python/core/PyPropertyDerived.java
+++ b/src/org/python/core/PyPropertyDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyPropertyDerived extends PyProperty implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyPropertyDerived extends PyProperty implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyProxy.java b/src/org/python/core/PyProxy.java
--- a/src/org/python/core/PyProxy.java
+++ b/src/org/python/core/PyProxy.java
@@ -9,8 +9,8 @@
* <ul>
* <li>An instance of the proxy class. The _getPyInstance() will return a reference to the
* PyInstance.
- * <li>An instance of PyInstance. The PyInstance.javaProxy contains a reference to the proxy class
- * instance.
+ * <li>An instance of PyInstance. The PyInstance's java proxy attribute contains a reference to the
+ * proxy class instance.
* </ul>
*
* All proxy classes implement this interface.
diff --git a/src/org/python/core/PyReflectedConstructor.java b/src/org/python/core/PyReflectedConstructor.java
--- a/src/org/python/core/PyReflectedConstructor.java
+++ b/src/org/python/core/PyReflectedConstructor.java
@@ -6,6 +6,7 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.InstantiationException;
+ at Untraversable
public class PyReflectedConstructor extends PyReflectedFunction {
public PyReflectedConstructor(String name) {
@@ -106,7 +107,7 @@
} else if (Modifier.isAbstract(mods)) {
throw Py.TypeError("can't instantiate abstract class (" + declaringClass.getName() + ")");
}
- if (self.javaProxy != null) {
+ if (JyAttribute.hasAttr(self, JyAttribute.JAVA_PROXY_ATTR)) {
Class<?> sup = javaClass;
if (PyProxy.class.isAssignableFrom(sup)) {
sup = sup.getSuperclass();
@@ -224,7 +225,7 @@
} finally {
ThreadContext.initializingProxy.set(previous);
}
- obj.javaProxy = jself;
+ JyAttribute.setAttr(obj, JyAttribute.JAVA_PROXY_ATTR, jself);
}
@Override
diff --git a/src/org/python/core/PyReflectedField.java b/src/org/python/core/PyReflectedField.java
--- a/src/org/python/core/PyReflectedField.java
+++ b/src/org/python/core/PyReflectedField.java
@@ -7,6 +7,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+ at Untraversable
public class PyReflectedField extends PyObject {
public Field field;
diff --git a/src/org/python/core/PyReflectedFunction.java b/src/org/python/core/PyReflectedFunction.java
--- a/src/org/python/core/PyReflectedFunction.java
+++ b/src/org/python/core/PyReflectedFunction.java
@@ -7,7 +7,7 @@
import org.python.util.Generic;
-public class PyReflectedFunction extends PyObject {
+public class PyReflectedFunction extends PyObject implements Traverseproc {
public String __name__;
@@ -335,4 +335,16 @@
public String toString() {
return "<java function " + __name__ + " " + Py.idstr(this) + ">";
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return __doc__ != null ? visit.visit(__doc__, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == __doc__;
+ }
}
diff --git a/src/org/python/core/PyReversedIterator.java b/src/org/python/core/PyReversedIterator.java
--- a/src/org/python/core/PyReversedIterator.java
+++ b/src/org/python/core/PyReversedIterator.java
@@ -31,4 +31,20 @@
private PyObject seq;
private int idx;
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return seq == null ? 0 : visit.visit(seq, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == seq || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/core/PySequenceIter.java b/src/org/python/core/PySequenceIter.java
--- a/src/org/python/core/PySequenceIter.java
+++ b/src/org/python/core/PySequenceIter.java
@@ -34,4 +34,20 @@
}
return result;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return seq == null ? 0 : visit.visit(seq, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == seq || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/core/PySequenceList.java b/src/org/python/core/PySequenceList.java
--- a/src/org/python/core/PySequenceList.java
+++ b/src/org/python/core/PySequenceList.java
@@ -5,7 +5,7 @@
import java.util.List;
import java.util.ListIterator;
-public abstract class PySequenceList extends PySequence {
+public abstract class PySequenceList extends PySequence implements Traverseproc {
protected PySequenceList(PyType type) {
super(type);
@@ -79,4 +79,22 @@
public abstract String toString();
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ for (int i = 0; i < size(); ++i) {
+ retVal = visit.visit(pyget(i), arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/src/org/python/core/PySetDerived.java b/src/org/python/core/PySetDerived.java
--- a/src/org/python/core/PySetDerived.java
+++ b/src/org/python/core/PySetDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PySetDerived extends PySet implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PySetDerived extends PySet implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
@@ -1143,7 +1159,7 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
diff --git a/src/org/python/core/PySingleton.java b/src/org/python/core/PySingleton.java
--- a/src/org/python/core/PySingleton.java
+++ b/src/org/python/core/PySingleton.java
@@ -1,6 +1,7 @@
// Copyright (c) Corporation for National Research Initiatives
package org.python.core;
+ at Untraversable
public class PySingleton extends PyObject
{
private String name;
diff --git a/src/org/python/core/PySlice.java b/src/org/python/core/PySlice.java
--- a/src/org/python/core/PySlice.java
+++ b/src/org/python/core/PySlice.java
@@ -10,7 +10,7 @@
* The Python slice object.
*/
@ExposedType(name = "slice", isBaseType = false, doc = BuiltinDocs.slice_doc)
-public class PySlice extends PyObject {
+public class PySlice extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PySlice.class);
@@ -242,4 +242,26 @@
final PyObject slice___reduce_ex__(PyObject protocol) {
return new PyTuple(getType(), new PyTuple(start, stop, step));
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ //start, stop, step cannot be null
+ int retVal = visit.visit(start, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ retVal = visit.visit(stop, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return visit.visit(step, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ //start, stop, step cannot be null
+ return ob == start || ob == stop || ob == step;
+ }
}
diff --git a/src/org/python/core/PySlot.java b/src/org/python/core/PySlot.java
--- a/src/org/python/core/PySlot.java
+++ b/src/org/python/core/PySlot.java
@@ -4,6 +4,7 @@
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "member_descriptor", base = PyObject.class, isBaseType = false)
public class PySlot extends PyDescriptor {
diff --git a/src/org/python/core/PyStaticMethod.java b/src/org/python/core/PyStaticMethod.java
--- a/src/org/python/core/PyStaticMethod.java
+++ b/src/org/python/core/PyStaticMethod.java
@@ -9,7 +9,7 @@
* The staticmethod descriptor.
*/
@ExposedType(name = "staticmethod", doc = BuiltinDocs.staticmethod_doc)
-public class PyStaticMethod extends PyObject {
+public class PyStaticMethod extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyStaticMethod.class);
@@ -41,4 +41,16 @@
final PyObject staticmethod___get__(PyObject obj, PyObject type) {
return callable;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return callable != null ? visit.visit(callable, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == callable;
+ }
}
diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java
--- a/src/org/python/core/PyString.java
+++ b/src/org/python/core/PyString.java
@@ -30,7 +30,8 @@
/**
* A builtin python string.
*/
- at ExposedType(name = "str", doc = BuiltinDocs.str_doc)
+ at Untraversable
+ at ExposedType(name = "str", base = PyBaseString.class, doc = BuiltinDocs.str_doc)
public class PyString extends PyBaseString implements BufferProtocol {
public static final PyType TYPE = PyType.fromClass(PyString.class);
diff --git a/src/org/python/core/PyStringDerived.java b/src/org/python/core/PyStringDerived.java
--- a/src/org/python/core/PyStringDerived.java
+++ b/src/org/python/core/PyStringDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyStringDerived extends PyString implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyStringDerived extends PyString implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyStringMap.java b/src/org/python/core/PyStringMap.java
--- a/src/org/python/core/PyStringMap.java
+++ b/src/org/python/core/PyStringMap.java
@@ -24,7 +24,7 @@
* to PyObject unlike PyDictionary.
*/
@ExposedType(name = "stringmap", isBaseType = false)
-public class PyStringMap extends PyObject {
+public class PyStringMap extends PyObject implements Traverseproc {
/**
* TYPE computed lazily, PyStringMap is used early in the bootstrap process and
@@ -658,8 +658,8 @@
super(c);
}
- @Override
- public PyObject stringMapNext() {
+ @Override
+ public PyObject stringMapNext() {
return iterator.next();
}
}
@@ -703,4 +703,31 @@
return pyKey;
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ Object key;
+ PyObject value;
+ for (Map.Entry<Object, PyObject> ent: table.entrySet()) {
+ key = ent.getKey();
+ value = ent.getValue();
+ if (key instanceof PyObject) {
+ retVal = visit.visit((PyObject) key, arg);
+ if (retVal != 0) return retVal;
+ }
+ if (value != null) {
+ retVal = visit.visit(value, arg);
+ if (retVal != 0) return retVal;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (table.containsKey(ob) || table.containsValue(ob));
+ }
}
diff --git a/src/org/python/core/PySuper.java b/src/org/python/core/PySuper.java
--- a/src/org/python/core/PySuper.java
+++ b/src/org/python/core/PySuper.java
@@ -10,7 +10,7 @@
* The Python super type.
*/
@ExposedType(name = "super", doc = BuiltinDocs.super_doc)
-public class PySuper extends PyObject {
+public class PySuper extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PySuper.class);
@@ -163,4 +163,29 @@
public PyType getObjType() {
return objType;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (superType != null) {
+ retVal = visit.visit(superType, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (obj != null) {
+ retVal = visit.visit(obj, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return objType == null ? 0 : visit.visit(objType, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == superType || ob == obj || ob == objType);
+ }
}
diff --git a/src/org/python/core/PySuperDerived.java b/src/org/python/core/PySuperDerived.java
--- a/src/org/python/core/PySuperDerived.java
+++ b/src/org/python/core/PySuperDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PySuperDerived extends PySuper implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PySuperDerived extends PySuper implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PySystemState.java b/src/org/python/core/PySystemState.java
--- a/src/org/python/core/PySystemState.java
+++ b/src/org/python/core/PySystemState.java
@@ -51,7 +51,8 @@
*/
// xxx Many have lamented, this should really be a module!
// but it will require some refactoring to see this wish come true.
-public class PySystemState extends PyObject implements AutoCloseable, ClassDictInit, Closeable {
+public class PySystemState extends PyObject implements AutoCloseable,
+ ClassDictInit, Closeable, Traverseproc {
public static final String PYTHON_CACHEDIR = "python.cachedir";
public static final String PYTHON_CACHEDIR_SKIP = "python.cachedir.skip";
@@ -1637,7 +1638,7 @@
private class ShutdownCloser implements Runnable {
- @Override
+ @Override
public synchronized void run() {
runClosers();
resourceClosers.clear();
@@ -1646,6 +1647,192 @@
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+// Potential PyObject refs in PySystemState:
+// public PyList argv = new PyList();
+// public PyObject modules;
+// public PyList path;
+// public PyList warnoptions = new PyList();
+// public PyObject builtins;
+// public PyObject platform = defaultPlatform;
+// public PyList meta_path;
+// public PyList path_hooks;
+// public PyObject path_importer_cache;
+// public PyObject ps1 = new PyString(">>> ");
+// public PyObject ps2 = new PyString("... ");
+// public PyObject executable;
+// public PyObject stdout, stderr, stdin;
+// public PyObject __stdout__, __stderr__, __stdin__;
+// public PyObject __displayhook__, __excepthook__;
+// public PyObject last_value = Py.None;
+// public PyObject last_type = Py.None;
+// public PyObject last_traceback = Py.None;
+// public PyObject __name__ = new PyString("sys");
+// public PyObject __dict__;
+ int retVal;
+ if (argv != null) {
+ retVal = visit.visit(argv, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (modules != null) {
+ retVal = visit.visit(modules, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (path != null) {
+ retVal = visit.visit(path, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (warnoptions != null) {
+ retVal = visit.visit(warnoptions, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (builtins != null) {
+ retVal = visit.visit(builtins, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (platform != null) {
+ retVal = visit.visit(platform, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (meta_path != null) {
+ retVal = visit.visit(meta_path, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (path_hooks != null) {
+ retVal = visit.visit(path_hooks, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (path_importer_cache != null) {
+ retVal = visit.visit(path_importer_cache, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (ps1 != null) {
+ retVal = visit.visit(ps1, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (ps2 != null) {
+ retVal = visit.visit(ps2, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (executable != null) {
+ retVal = visit.visit(executable, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (stdout != null) {
+ retVal = visit.visit(stdout, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (stderr != null) {
+ retVal = visit.visit(stderr, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (stdin != null) {
+ retVal = visit.visit(stdin, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__stdout__ != null) {
+ retVal = visit.visit(__stdout__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__stderr__ != null) {
+ retVal = visit.visit(__stderr__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__stdin__ != null) {
+ retVal = visit.visit(__stdin__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__displayhook__ != null) {
+ retVal = visit.visit(__displayhook__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__excepthook__ != null) {
+ retVal = visit.visit(__excepthook__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (last_value != null) {
+ retVal = visit.visit(last_value, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (last_type != null) {
+ retVal = visit.visit(last_type, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (last_traceback != null) {
+ retVal = visit.visit(last_traceback, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (__name__ != null) {
+ retVal = visit.visit(__name__, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return __dict__ == null ? 0 : visit.visit(__dict__, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == argv || ob == modules || ob == path
+ || ob == warnoptions || ob == builtins || ob == platform
+ || ob == meta_path || ob == path_hooks || ob == path_importer_cache
+ || ob == ps1 || ob == ps2 || ob == executable || ob == stdout
+ || ob == stderr || ob == stdin || ob == __stdout__ || ob == __stderr__
+ || ob == __stdin__ || ob == __displayhook__ || ob == __excepthook__
+ || ob == last_value || ob == last_type || ob == last_traceback
+ || ob ==__name__ || ob == __dict__);
+ }
+
+
/**
* Helper abstracting common code from {@link ShutdownCloser#run()} and
* {@link PySystemStateCloser#cleanup()} to close resources (such as still-open files). The
@@ -1654,10 +1841,10 @@
*
* @param resourceClosers to be called in turn
*/
-
}
+ at Untraversable
class PySystemStateFunctions extends PyBuiltinFunctionSet {
PySystemStateFunctions(String name, int index, int minargs, int maxargs) {
@@ -1692,6 +1879,7 @@
* Value of a class or instance variable when the corresponding attribute is deleted. Used only in
* PySystemState for now.
*/
+ at Untraversable
class PyAttributeDeleted extends PyObject {
final static PyAttributeDeleted INSTANCE = new PyAttributeDeleted();
@@ -1760,6 +1948,81 @@
Py.newLong(1) // FLT_ROUNDS
);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (max != null) {
+ retVal = visit.visit(max, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (max_exp != null) {
+ retVal = visit.visit(max_exp, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (max_10_exp != null) {
+ retVal = visit.visit(max_10_exp, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (min != null) {
+ retVal = visit.visit(min, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (min_exp != null) {
+ retVal = visit.visit(min_exp, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (min_10_exp != null) {
+ retVal = visit.visit(min_10_exp, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (dig != null) {
+ retVal = visit.visit(dig, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (mant_dig != null) {
+ retVal = visit.visit(mant_dig, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (epsilon != null) {
+ retVal = visit.visit(epsilon, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (radix != null) {
+ retVal = visit.visit(radix, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return rounds == null ? 0 : visit.visit(rounds, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == max || ob == max_exp || ob == max_10_exp || ob == min
+ || ob == min_exp || ob == min_10_exp || ob == dig
+ || ob == mant_dig || ob == epsilon || ob == radix || ob == rounds);
+ }
}
@@ -1783,4 +2046,23 @@
static public LongInfo getInfo() {
return new LongInfo(Py.newLong(30), Py.newLong(4));
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (bits_per_digit != null) {
+ retVal = visit.visit(bits_per_digit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return sizeof_digit == null ? 0 : visit.visit(sizeof_digit, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == bits_per_digit || ob == sizeof_digit);
+ }
}
diff --git a/src/org/python/core/PyTableCode.java b/src/org/python/core/PyTableCode.java
--- a/src/org/python/core/PyTableCode.java
+++ b/src/org/python/core/PyTableCode.java
@@ -8,6 +8,7 @@
import org.python.modules._systemrestart;
+ at Untraversable
public class PyTableCode extends PyBaseCode
{
diff --git a/src/org/python/core/PyTraceback.java b/src/org/python/core/PyTraceback.java
--- a/src/org/python/core/PyTraceback.java
+++ b/src/org/python/core/PyTraceback.java
@@ -9,7 +9,7 @@
* A python traceback object.
*/
@ExposedType(name = "traceback", isBaseType = false)
-public class PyTraceback extends PyObject {
+public class PyTraceback extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyTraceback.class);
@@ -120,4 +120,23 @@
dumpStack(buf);
return buf.toString();
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (tb_next != null) {
+ int retVal = visit.visit(tb_next, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ //__dict__ cannot be null
+ return tb_frame == null ? 0 : visit.visit(tb_frame, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == tb_next || ob == tb_frame);
+ }
}
diff --git a/src/org/python/core/PyTuple.java b/src/org/python/core/PyTuple.java
--- a/src/org/python/core/PyTuple.java
+++ b/src/org/python/core/PyTuple.java
@@ -606,4 +606,50 @@
}
return converted;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ for (PyObject ob: array) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ if (cachedList != null) {
+ for (PyObject ob: cachedList) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null) {
+ return false;
+ }
+ for (PyObject obj: array) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ if (cachedList != null) {
+ for (PyObject obj: cachedList) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/src/org/python/core/PyTupleDerived.java b/src/org/python/core/PyTupleDerived.java
--- a/src/org/python/core/PyTupleDerived.java
+++ b/src/org/python/core/PyTupleDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyTupleDerived extends PyTuple implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyTupleDerived extends PyTuple implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyType.java b/src/org/python/core/PyType.java
--- a/src/org/python/core/PyType.java
+++ b/src/org/python/core/PyType.java
@@ -30,7 +30,7 @@
* The Python Type object implementation.
*/
@ExposedType(name = "type", doc = BuiltinDocs.type_doc)
-public class PyType extends PyObject implements Serializable {
+public class PyType extends PyObject implements Serializable, Traverseproc {
public static final PyType TYPE = fromClass(PyType.class);
@@ -668,7 +668,7 @@
}
Class<?> proxyClass = MakeProxies.makeProxy(baseProxyClass, interfaces, name, proxyName,
dict);
- javaProxy = proxyClass;
+ JyAttribute.setAttr(this, JyAttribute.JAVA_PROXY_ATTR, proxyClass);
PyType proxyType = PyType.fromClass(proxyClass, false);
List<PyObject> cleanedBases = Generic.list();
@@ -932,7 +932,7 @@
* Returns the Java Class that this type inherits from, or null if this type is Python-only.
*/
public Class<?> getProxyType() {
- return (Class<?>)javaProxy;
+ return (Class<?>) JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR);
}
private synchronized void attachSubclass(PyType subtype) {
@@ -1022,7 +1022,8 @@
PyObject[] computeMro(MROMergeState[] toMerge, List<PyObject> mro) {
boolean addedProxy = false;
- PyType proxyAsType = javaProxy == null ? null : PyType.fromClass(((Class<?>)javaProxy), false);
+ PyType proxyAsType = !JyAttribute.hasAttr(this, JyAttribute.JAVA_PROXY_ATTR) ?
+ null : PyType.fromClass(((Class<?>)JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR)), false);
scan : for (int i = 0; i < toMerge.length; i++) {
if (toMerge[i].isMerged()) {
continue scan;
@@ -1035,9 +1036,11 @@
}
}
if (!addedProxy && !(this instanceof PyJavaType) && candidate instanceof PyJavaType
- && candidate.javaProxy != null
- && PyProxy.class.isAssignableFrom(((Class<?>)candidate.javaProxy))
- && candidate.javaProxy != javaProxy) {
+ && JyAttribute.hasAttr(candidate, JyAttribute.JAVA_PROXY_ATTR)
+ && PyProxy.class.isAssignableFrom(
+ ((Class<?>)JyAttribute.getAttr(candidate, JyAttribute.JAVA_PROXY_ATTR)))
+ && JyAttribute.getAttr(candidate, JyAttribute.JAVA_PROXY_ATTR) !=
+ JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR)) {
// If this is a subclass of a Python class that subclasses a Java class, slip the
// proxy for this class in before the proxy class in the superclass' mro.
// This exposes the methods from the proxy generated for this class in addition to
@@ -1235,6 +1238,7 @@
* @return found object or null
*/
public PyObject lookup_where(String name, PyObject[] where) {
+ if (methodCache == null) System.out.println("method cache is null");
return methodCache.lookup_where(this, name, where);
}
@@ -2094,4 +2098,65 @@
}
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (base != null) {
+ retVal = visit.visit(base, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ //bases cannot be null
+ for (PyObject ob: bases) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ if (dict != null) {
+ retVal = visit.visit(dict, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (mro != null) {
+ for (PyObject ob: mro) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ //don't traverse subclasses since they are weak refs.
+ //ReferenceQueue<PyType> subclasses_refq = new ReferenceQueue<PyType>();
+ //Set<WeakReference<PyType>> subclasses = Generic.set();
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ if (ob == null) {
+ return false;
+ }
+ //bases cannot be null
+ for (PyObject obj: bases) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ if (mro != null) {
+ for (PyObject obj: mro) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ }
+ return ob == base || ob == dict;
+ }
}
diff --git a/src/org/python/core/PyTypeDerived.java b/src/org/python/core/PyTypeDerived.java
--- a/src/org/python/core/PyTypeDerived.java
+++ b/src/org/python/core/PyTypeDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyTypeDerived extends PyType implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyTypeDerived extends PyType implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,17 +26,35 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
public PyTypeDerived(PyType subtype) {
super(subtype);
slots=new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return 0;
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyUnicode.java b/src/org/python/core/PyUnicode.java
--- a/src/org/python/core/PyUnicode.java
+++ b/src/org/python/core/PyUnicode.java
@@ -20,6 +20,7 @@
/**
* a builtin python unicode string.
*/
+ at Untraversable
@ExposedType(name = "unicode", base = PyBaseString.class, doc = BuiltinDocs.unicode_doc)
public class PyUnicode extends PyString implements Iterable {
diff --git a/src/org/python/core/PyUnicodeDerived.java b/src/org/python/core/PyUnicodeDerived.java
--- a/src/org/python/core/PyUnicodeDerived.java
+++ b/src/org/python/core/PyUnicodeDerived.java
@@ -5,9 +5,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyUnicodeDerived extends PyUnicode implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyUnicodeDerived extends PyUnicode implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -28,9 +26,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -44,8 +56,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -62,10 +74,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/core/PyXRange.java b/src/org/python/core/PyXRange.java
--- a/src/org/python/core/PyXRange.java
+++ b/src/org/python/core/PyXRange.java
@@ -13,6 +13,7 @@
/**
* The builtin xrange type.
*/
+ at Untraversable
@ExposedType(name = "xrange", base = PyObject.class, isBaseType = false,
doc = BuiltinDocs.xrange_doc)
public class PyXRange extends PySequence {
diff --git a/src/org/python/core/PythonTraceFunction.java b/src/org/python/core/PythonTraceFunction.java
--- a/src/org/python/core/PythonTraceFunction.java
+++ b/src/org/python/core/PythonTraceFunction.java
@@ -2,7 +2,7 @@
package org.python.core;
-class PythonTraceFunction extends TraceFunction {
+class PythonTraceFunction extends TraceFunction implements Traverseproc {
PyObject tracefunc;
@@ -57,4 +57,16 @@
return safeCall(frame, "exception",
new PyTuple(exc.type, exc.value, safeTraceback));
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return tracefunc == null ? 0 : visit.visit(tracefunc, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == tracefunc;
+ }
}
diff --git a/src/org/python/core/SyspathArchive.java b/src/org/python/core/SyspathArchive.java
--- a/src/org/python/core/SyspathArchive.java
+++ b/src/org/python/core/SyspathArchive.java
@@ -3,6 +3,7 @@
import java.io.*;
import java.util.zip.*;
+ at Untraversable
public class SyspathArchive extends PyString {
private ZipFile zipFile;
diff --git a/src/org/python/core/Traverseproc.java b/src/org/python/core/Traverseproc.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/core/Traverseproc.java
@@ -0,0 +1,462 @@
+package org.python.core;
+
+/**
+ * <p>
+ * This interface defines a CPython equivalent traverse mechanism allowing
+ * to detect reference cycles. While this is crucial for cyclic gc support
+ * in CPython, it only serves debugging purposes in Jython. As a side effect
+ * it allows a more complete implementation of the gc module.
+ * </p>
+ * <p>
+ * Note that implementing this interface is only OPTIONAL.<b> Gc will work fine
+ * in Jython without it. </b>Still we took care to have all core classes implement
+ * it and recommend third party extension providers to do so as well with
+ * custom PyObject-implementations.
+ * </p>
+ * <p>
+ * Of course this interface shall only be implemented by PyObjects that
+ * potentially own direct references to other PyObjects. Note that indirect
+ * references via non-PyObjects should also be treated as "direct" (c.f.
+ * tracefunc in {@link org.python.core.PyFrame}).
+ * PyObjects that don't own references to other PyObjects under any condition
+ * and neither inherit such references from a superclass are strictly recommended
+ * to be annotated {@code {@literal @}Untraversable}
+ * (see {@link org.python.core.Untraversable} for details).
+ * </p>
+ * <p>
+ * Jython's traverse mechanism serves debugging purposes to ease finding memory
+ * leaks and compare gc behavior with CPython. While it is of course not required
+ * that gc behaviors of Jython and CPython equal, there might arise subtle bugs
+ * from these different behaviors. Jython's traverse mechanism is intended to
+ * allow finding such bugs by comparing gc behavior to CPython and isolating
+ * the Python code that is not robust enough to work invariant under different
+ * gc behaviors.
+ * </p>
+ * <p>
+ * Further this mechanism is crucial for some aspects of gc-support of the JyNI
+ * project. JyNI does not strictly depend on it to emulate CPython's gc
+ * for extensions, but would have to perform inefficient reflection-based
+ * traversal in some edge-cases (which might also conflict security managers).
+ * </p>
+ * <p>
+ * Note that the slots-array and - if existent - the user-dict of fooDerived classes
+ * is traversed by {@link org.python.core.TraverseProcDerived}.
+ * The gc module takes care of exploiting both traverse methods in its static traverse
+ * method. So for manual traversion one should always use {@code gc.traverse} rather
+ * than directly calling methods in this interface.
+ * </p>
+ * <p>
+ * Also note that {@code objtype} is not subject to {@code Traverseproc}s
+ * by default. In CPython only objects with heap-types traverse their
+ * ob_type field. In Jython, {@code fooDerived}-classes are the
+ * equivalents of heapTypes. For such classes, objtype is actually
+ * traversed (along with the user dict).
+ * </p>
+ * <p>
+ * Note for implementing:<br>
+ * Every non-static strong referenced PyObject should be passed to the
+ * {@link org.python.core.Visitproc}. If {@code Object}s or {@code interface}-types are
+ * referenced where it is not known, whether it is a {@code PyObject} or
+ * references other {@code PyObjects}, one should check for {@code PyObject}
+ * via {@code instanceof} and otherwise also check whether it at least
+ * implements {@code Traverseproc} itself. In latter case one should traverse
+ * it by delegating to its {@code Traverseproc} methods.<br>
+ * Warning:<br>
+ * If one lets non-{@code PyObject}s implement {@code Traverseproc}, extreme
+ * care must be taken, whether the traverse call shall be passed on to other
+ * non-{@code PyObject} {@code Traverseproc}-implementers, as this can cause
+ * infinite traverse cycles.<br>
+ * Examples for non-{@code PyObject}s that implement {@code Traverseproc} are
+ * {@link org.python.core.PyException} and {@link com.ziclix.python.sql.Fetch}.
+ * </p>
+ * <p>
+ * It follows a list of PyObject subclasses in Jython, excluding derived classes.<br>
+ * PyObject subclasses in Jython checked for need of Traverseproc:<br>
+ * <br>
+ * <br>
+ * org.python.core:<br>
+ * __builtin__:<br>
+ * BuiltinFunctions - no refs, untraversable<br>
+ * ImportFunction - no refs, untraversable<br>
+ * SortedFunction - no refs, untraversable<br>
+ * AllFunction - no refs, untraversable<br>
+ * AnyFunction - no refs, untraversable<br>
+ * FormatFunction - no refs, untraversable<br>
+ * PrintFunction - no refs, untraversable<br>
+ * MaxFunction - no refs, untraversable<br>
+ * MinFunction - no refs, untraversable<br>
+ * RoundFunction - no refs, untraversable<br>
+ * CompileFunction - no refs, untraversable<br>
+ * OpenFunction - no refs, untraversable<br>
+ * NextFunction - no refs, untraversable<br>
+ * BinFunction - no refs, untraversable<br>
+ * AstList - Traverseproc<br>
+ * BaseBytes - no refs, untraversable<br>
+ * IndexDelegate - no PyObject<br>
+ * BaseDictionaryView - Traverseproc<br>
+ * BaseSet - Traverseproc<br>
+ * ClasspathPyImporter - no refs, untraversable<br>
+ * ContextGuard: - no PyObject<br>
+ * ContextCode - Traverseproc<br>
+ * GeneratorContextManager - Traverseproc<br>
+ * exceptions - no refs, untraversable<br>
+ * BoundStaticJavaMethod - no refs, untraversable<br>
+ * JavaImporter - no refs, untraversable<br>
+ * JavaProxyList:<br>
+ * ListMethod - no refs, untraversable (extends PyBuiltinMethodNarrow)<br>
+ * ListMulProxyClass - no refs, untraversable<br>
+ * JavaProxyMap:<br>
+ * MapMethod - no refs, untraversable (extends PyBuiltinMethodNarrow)<br>
+ * MapClassMethod - no refs, untraversable (extends PyBuiltinClassMethodNarrow)<br>
+ * JavaProxySet:<br>
+ * SetMethod - no refs, untraversable (extends PyBuiltinMethodNarrow)<br>
+ * SetMethodVarargs - no refs, untraversable (extends SetMethod)<br>
+ * CopyMethod - no refs, untraversable<br>
+ * IsSubsetMethod - no refs, untraversable<br>
+ * IsSupersetMethod - no refs, untraversable<br>
+ * Py:<br>
+ * JavaCode - Traverseproc<br>
+ * JavaFunc - no refs, untraversable<br>
+ * Py2kBuffer - no refs, untraversable<br>
+ * PyArray - Traverseproc, traverses via reflection<br>
+ * PyBaseCode - no refs, abstract class<br>
+ * PyBaseException - Traverseproc<br>
+ * PyBaseString - no refs, abstract class<br>
+ * PyBeanEvent - no refs, untraversable<br>
+ * PyBeanEventProperty - no refs, untraversable<br>
+ * PyBeanProperty - no refs, untraversable<br>
+ * PyBoolean - no refs, untraversable<br>
+ * PyBuffer - no PyObject<br>
+ * PyBuiltinCallable - no refs, untraversable<br>
+ * PyBuiltinClassMethodNarrow - no refs, abstract class<br>
+ * PyBuiltinFunction - no refs, untraversable<br>
+ * PyBuiltinFunctionNarrow - no refs, untraversable<br>
+ * PyBuiltinFunctionSet - no refs, untraversable<br>
+ * PyBuiltinMethod - Traverseproc<br>
+ * PyBuiltinMethodNarrow - no refs, abstract class<br>
+ * PyBuiltinMethodSet - Traverseproc<br>
+ * PyByteArray - no refs, untraversable<br>
+ * PyBytecode - Traverseproc<br>
+ * PyStackWhy - no refs, untraversable<br>
+ * PyStackException - Traverseproc<br>
+ * PyTryBlock - no refs, untraversable<br>
+ * PyCallIter - Traverseproc (with call to super)<br>
+ * PyCell - Traverseproc<br>
+ * PyClass - Traverseproc<br>
+ * PyClassMethod - Traverseproc<br>
+ * PyClassMethodDescr - no refs, untraversable<br>
+ * PyCode - no refs, abstract class<br>
+ * PyComplex - no refs, untraversable<br>
+ * PyCompoundCallable - Traverseproc<br>
+ * PyDataDescr - no refs, untraversable<br>
+ * PyDescriptor - Traverseproc<br>
+ * PyDictionary - Traverseproc<br>
+ * ValuesIter - no refs, extends PyIterator<br>
+ * ItemsIter - no refs, extends PyIterator<br>
+ * PyMapKeyValSet - no PyObject<br>
+ * PyMapEntrySet - no PyObject<br>
+ * PyDictProxy - Traverseproc<br>
+ * PyEllipsis - no refs, untraversable<br>
+ * PyEnumerate - Traverseproc<br>
+ * PyFastSequenceIter - Traverseproc<br>
+ * PyFile - Traverseproc<br>
+ * PyFileReader - no refs, untraversable<br>
+ * PyFileWriter - no refs, untraversable<br>
+ * PyFloat - no refs, untraversable<br>
+ * PyFrame - Traverseproc<br>
+ * PyFunction - Traverseproc<br>
+ * PyGenerator - Traverseproc (with call to super)<br>
+ * PyIndentationError - no PyObject<br>
+ * PyInstance - Traverseproc<br>
+ * PyInteger - no refs, untraversable<br>
+ * PyIterator - Traverseproc<br>
+ * PyJavaPackage - Traverseproc<br>
+ * PyJavaType - Traverseproc (with call to super)<br>
+ * EnumerationIter - no refs, extends PyIterator<br>
+ * ComparableMethod - no refs, abstract class<br>
+ * PyList - Traverseproc<br>
+ * PyLong - no refs, untraversable<br>
+ * PyMemoryView - Traverseproc<br>
+ * PyMethod - Traverseproc<br>
+ * PyMethodDescr - Traverseproc<br>
+ * PyModule - Traverseproc<br>
+ * PyNewWrapper - Traverseproc<br>
+ * PyNone - no refs, untraversable<br>
+ * PyNotImplemented - no refs, untraversable<br>
+ * PyObject - no refs (objtype is special case)<br>
+ * PyIdentityTuple - Traverseproc<br>
+ * PyOverridableNew - no refs, abstract class<br>
+ * PyProperty - Traverseproc<br>
+ * PyReflectedConstructor - no refs, untraversable<br>
+ * PyReflectedField - no refs, untraversable<br>
+ * PyReflectedFunction - Traverseproc<br>
+ * PyReversedIterator - Traverseproc (with call to super)<br>
+ * PySequence - no refs, abstract class (default Traverseproc implementation)<br>
+ * PySequenceIter - Traverseproc (with call to super)<br>
+ * PySequenceList - no refs, abstract class<br>
+ * PySingleton - no refs, untraversable<br>
+ * PySlice - Traverseproc<br>
+ * PySlot - no refs, untraversable<br>
+ * PyStaticMethod - Traverseproc<br>
+ * PyString - no refs, untraversable (assuming baseBuffer is not a PyObject)<br>
+ * PyStringMap - Traverseproc<br>
+ * StringMapIter - no refs, extends PyIterator, abstract class<br>
+ * ItemsIter - no refs, extends StringMapIter<br>
+ * KeysIter - no refs, extends StringMapIter<br>
+ * ValuesIter - no refs, extends StringMapIter<br>
+ * PySuper - Traverseproc<br>
+ * PySyntaxError - no PyObject<br>
+ * PySystemState - Traverseproc<br>
+ * PySystemStateFunctions - no refs, untraversable<br>
+ * PyAttributeDeleted - no refs, untraversable<br>
+ * FloatInfo - Traverseproc<br>
+ * LongInfo - Traverseproc<br>
+ * PyTableCode - no refs, untraversable<br>
+ * PyTraceback - Traverseproc<br>
+ * PyTuple - Traverseproc<br>
+ * PyType - Traverseproc<br>
+ * PyUnicode - no refs, untraversable<br>
+ * PyXRange - no refs, untraversable<br>
+ * PyXRangeIter - no refs, extends PyIterator<br>
+ * SyspathArchive - no refs, untraversable<br>
+ * <br>
+ * org.python.core.stringlib:<br>
+ * FieldNameIterator - no refs, traverses via reflection<br>
+ * MarkupIterator - no refs, untraversable<br>
+ * <br>
+ * org.python.core.util:<br>
+ * importer - no refs, abstract class<br>
+ * <br>
+ * org.python.jsr223:<br>
+ * PyScriptEngineScope - no refs, untraversable<br>
+ * ScopeIterator - Traverseproc<br>
+ * <br>
+ * org.python.modules:<br>
+ * _codecs:<br>
+ * EncodingMap - no refs, untraversable<br>
+ * _hashlib:<br>
+ * Hash - no refs, untraversable<br>
+ * _marshal:<br>
+ * Marshaller - Traverseproc<br>
+ * Unmarshaller - Traverseproc<br>
+ * cStringIO:<br>
+ * StringIO - no refs, extends PyIterator<br>
+ * operator:<br>
+ * OperatorFunctions - no refs, untraversable<br>
+ * operator - no refs, untraversable<br>
+ * PyAttrGetter - Traverseproc<br>
+ * PyItemGetter - Traverseproc<br>
+ * PyMethodCaller - Traverseproc<br>
+ * PyStruct - no refs, untraversable<br>
+ * synchronize:<br>
+ * SynchronizedCallable - Traverseproc<br>
+ * <br>
+ * org.python.modules._collections:<br>
+ * PyDefaultDict - Traverseproc (with call to super)<br>
+ * PyDeque - Traverseproc (assuming, Nodes can't build cycles)<br>
+ * PyDequeIter - Traverseproc (with call to super)<br>
+ * <br>
+ * org.python.modules._csv:<br>
+ * PyDialect - no refs, untraversable<br>
+ * PyReader - Traverseproc (with call to super)<br>
+ * PyWriter - Traverseproc<br>
+ * <br>
+ * org.python.modules._functools:<br>
+ * PyPartial - Traverseproc<br>
+ * <br>
+ * org.python.modules._io:<br>
+ * PyFileIO - no refs, untraversable (there is a final PyString "mode", which is guarenteed to be a PyString and no subclass; as such it needs not be traversed since it cannot have refs itself)<br>
+ * PyIOBase - Traverseproc<br>
+ * PyRawIOBase - no refs, extends PyIOBase<br>
+ * <br>
+ * org.python.modules._json:<br>
+ * Encoder - Traverseproc<br>
+ * Scanner - Traverseproc<br>
+ * <br>
+ * org.python.modules._jythonlib:<br>
+ * dict_builder - Traverseproc<br>
+ * <br>
+ * org.python.modules._threading:<br>
+ * Condition - Traverseproc<br>
+ * Lock - no refs, untraversable<br>
+ * <br>
+ * org.python.modules._weakref:<br>
+ * AbstractReference - Traverseproc<br>
+ * ReferenceType - no refs, extends AbstractReference<br>
+ * ProxyType - no refs, extends AbstractReference<br>
+ * CallableProxyType - no refs, extends ProxyType<br>
+ * <br>
+ * org.python.modules.bz2:<br>
+ * PyBZ2Compressor - no refs, untraversable<br>
+ * PyBZ2Decompressor - Traverseproc<br>
+ * PyBZ2File - no refs, untraversable<br>
+ * BZ2FileIterator - no refs, extends PyIterator<br>
+ * <br>
+ * org.python.modules.itertools:<br>
+ * chain - Traverseproc (with call to super)<br>
+ * combinations - Traverseproc (with call to super)<br>
+ * combinationsWithReplacement - Traverseproc (with call to super)<br>
+ * compress - Traverseproc (with call to super)<br>
+ * count - Traverseproc (with call to super)<br>
+ * cycle - Traverseproc (with call to super)<br>
+ * dropwhile - Traverseproc (with call to super)<br>
+ * groupby - Traverseproc (with call to super)<br>
+ * ifilter - Traverseproc (with call to super)<br>
+ * ifiIterfalse - Traverseproc (with call to super)<br>
+ * imap - Traverseproc (with call to super)<br>
+ * islice - Traverseproc (with call to super)<br>
+ * itertools:<br>
+ * ItertoolsIterator - no refs, extends PyIterator, abstract class<br>
+ * FilterIterator - Traverseproc, extends ItertoolsIterator<br>
+ * WhileIterator - Traverseproc, extends ItertoolsIterator
+ * izip - Traverseproc (with call to super)<br>
+ * izipLongest - Traverseproc (with call to super)<br>
+ * permutations - Traverseproc (with call to super)<br>
+ * product - Traverseproc (with call to super)<br>
+ * PyTeeIterator - Traverseproc (with call to super)<br>
+ * repeat - Traverseproc (with call to super)<br>
+ * starmap - Traverseproc (with call to super)<br>
+ * takewhile - Traverseproc (with call to super)<br>
+ * <br>
+ * org.python.modules.jffi:<br>
+ * ArrayCData - Traverseproc (with call to super; maybe check referenceMemory field whether it extends PyObject)<br>
+ * ArrayIter - no refs, extends PyIterator<br>
+ * BasePointer - no refs, abstract class<br>
+ * ByReference - no refs, untraversable (maybe check memory field whether it extends PyObject)<br>
+ * CData - Traverseproc (maybe check referenceMemory field whether it extends PyObject)<br>
+ * CType - no refs, abstract class<br>
+ * DynamicLibrary - no refs, untraversable<br>
+ * StructLayout:<br>
+ * Field - Traverseproc<br>
+ * <br>
+ * org.python.modules.posix:<br>
+ * PosixModule:<br>
+ * FstatFunction - no refs, untraversable<br>
+ * LstatFunction - no refs, untraversable<br>
+ * StatFunction - no refs, untraversable<br>
+ * WindowsStatFunction - no refs, untraversable<br>
+ * PyStatResult - Traverseproc (with call to super)<br>
+ * <br>
+ * org.python.modules.random:<br>
+ * PyRandom - no refs, untraversable<br>
+ * <br>
+ * org.python.modules.sre:<br>
+ * MatchObject - Traverseproc<br>
+ * PatternObject - Traverseproc<br>
+ * ScannerObject - Traverseproc<br>
+ * <br>
+ * org.python.modules.thread:<br>
+ * PyLocal - Traverseproc<br>
+ * PyLock - no refs, untraversable<br>
+ * <br>
+ * org.python.modules.time:<br>
+ * PyTimeTuple - Traverseproc (with call to super)<br>
+ * Time:<br>
+ * TimeFunctions - no refs, untraversable<br>
+ * <br>
+ * org.python.util:<br>
+ * InteractiveInterpreter - no PyObject<br>
+ * <br>
+ * com.ziclix.python.sql:<br>
+ * DBApiType - no refs, untraversable<br>
+ * PyConnection - Traverseproc<br>
+ * ConnectionFunc - no refs, extends PyBuiltinMethodSet<br>
+ * PyCursor - Traverseproc<br>
+ * CursorFunc - no refs, extends PyBuiltinMethodSet<br>
+ * PyExtendedCursor - no refs, extends PyCursor<br>
+ * ExtendedCursorFunc - no refs, extends PyBuiltinMethodSet<br>
+ * PyStatement - Traverseproc (because Object sql could be a PyObject or Traverseproc)<br>
+ * zxJDBC - no refs, untraversable<br>
+ * zxJDBCFunc - no refs, untraversable<br>
+ * <br>
+ * com.ziclix.python.sql.connect:<br>
+ * Connect - no refs, untraversable<br>
+ * Connectx - no refs, untraversable<br>
+ * Lookup - no refs, untraversable<br>
+ * <br>
+ * com.ziclix.python.sql.util:<br>
+ * BCP - Traverseproc<br>
+ * BCPFunc - no refs, extends PyBuiltinMethodSet<br>
+ * <br>
+ * org.python.antlr:<br>
+ * AnalyzingParser:<br>
+ * AnalyzerTreeAdaptor - no PyObject<br>
+ * AST - no refs, untraversable<br>
+ * PythonErrorNode - no refs, extends PythonTree<br>
+ * PythonTree - Traverseproc<br>
+ * <br>
+ * org.python.antlr.ast:<br>
+ * alias - no refs, extends PythonTree<br>
+ * arguments - Traverseproc (with call to super)<br>
+ * comprehension - Traverseproc (with call to super)<br>
+ * keyword - Traverseproc (with call to super)<br>
+ * <br>
+ * org.python.antlr.base:<br>
+ * boolop - no refs, extends PythonTree<br>
+ * cmpop - no refs, extends PythonTree<br>
+ * excepthandler - no refs, extends PythonTree<br>
+ * expr_context - no refs, extends PythonTree<br>
+ * expr - no refs, extends PythonTree<br>
+ * mod - no refs, extends PythonTree<br>
+ * operator - no refs, extends PythonTree<br>
+ * slice - no refs, extends PythonTree<br>
+ * stmt - no refs, extends PythonTree<br>
+ * unaryop - no refs, extends PythonTree<br>
+ * <br>
+ * org.python.antlr.op:<br>
+ * Add - no refs, extends PythonTree<br>
+ * And - no refs, extends PythonTree<br>
+ * AugLoad - no refs, extends PythonTree<br>
+ * AugStore - no refs, extends PythonTree<br>
+ * BitAnd - no refs, extends PythonTree<br>
+ * BitOr - no refs, extends PythonTree<br>
+ * BitXor - no refs, extends PythonTree<br>
+ * Del - no refs, extends PythonTree<br>
+ * Div - no refs, extends PythonTree<br>
+ * Eq - no refs, extends PythonTree<br>
+ * FloorDiv - no refs, extends PythonTree<br>
+ * Gt - no refs, extends PythonTree<br>
+ * GtE - no refs, extends PythonTree<br>
+ * In - no refs, extends PythonTree<br>
+ * Invert - no refs, extends PythonTree<br>
+ * Is - no refs, extends PythonTree<br>
+ * IsNot - no refs, extends PythonTree<br>
+ * Load - no refs, extends PythonTree<br>
+ * LShift - no refs, extends PythonTree<br>
+ * Lt - no refs, extends PythonTree<br>
+ * LtE - no refs, extends PythonTree<br>
+ * Mod - no refs, extends PythonTree<br>
+ * Mult - no refs, extends PythonTree<br>
+ * Not - no refs, extends PythonTree<br>
+ * NotEq - no refs, extends PythonTree<br>
+ * NotIn - no refs, extends PythonTree<br>
+ * Or - no refs, extends PythonTree<br>
+ * Param - no refs, extends PythonTree<br>
+ * Pow - no refs, extends PythonTree<br>
+ * RShift - no refs, extends PythonTree<br>
+ * Store - no refs, extends PythonTree<br>
+ * Sub - no refs, extends PythonTree<br>
+ * UAdd - no refs, extends PythonTree<br>
+ * USub - no refs, extends PythonTree<br>
+ * </p>
+ */
+public interface Traverseproc {
+
+ /**
+ * Traverses all reachable {@code PyObject}s.
+ * Like in CPython, {@code arg} must be passed
+ * unmodified to {@code visit} as its second parameter.
+ * If {@code visit.visit} returns nonzero, this return value
+ * must be returned immediately by traverse.
+ */
+ public int traverse(Visitproc visit, Object arg);
+
+ /**
+ * Optional operation.
+ * Should only be implemented if it is more efficient
+ * than calling {@code traverse} with a visitproc
+ * that just watches out for {@code ob}.
+ * Must return {@code false} if {@code ob} is {@code null}.
+ */
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException;
+}
diff --git a/src/org/python/core/TraverseprocDerived.java b/src/org/python/core/TraverseprocDerived.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/core/TraverseprocDerived.java
@@ -0,0 +1,17 @@
+package org.python.core;
+
+/**
+ * This is used like Traverseproc, but traverses only the slots[] array
+ * of fooDerived classes. This way it is avoided that the traverse
+ * method of a traversable PyObject is overwritten by the derived
+ * version. The gc module takes care of exploiting both traverse methods.
+ *
+ */
+public interface TraverseprocDerived {
+ /**
+ * Traverses all reachable {@code PyObject}s.
+ * Like in CPython, {@code arg} must be passed
+ * unmodified to {@code visit} as its second parameter.
+ */
+ public int traverseDerived(Visitproc visit, Object arg);
+}
diff --git a/src/org/python/core/Untraversable.java b/src/org/python/core/Untraversable.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/core/Untraversable.java
@@ -0,0 +1,26 @@
+package org.python.core;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a given class is not traversable and does
+ * intentionally not implement {@link org.python.core.Traverseproc}.
+ * This annotation is ignored if the class implements {@code Traverseproc},
+ * i.e. it cannot be used to remove {@code Traverseproc} support of a
+ * superclass. Thus it is well defined what happens if both
+ * {@code Traverseproc} and {@code {@literal @}Untraversable}
+ * are present: {@code Traverseproc} wins.<br>
+ * If a class does not implement {@code Traverseproc} and is not
+ * annotated with {@code {@literal @}Untraversable}, gc assumes
+ * that the programmers were not aware of Jython's traverse
+ * mechanism and attempts to traverse the target object by using
+ * Java-reflection (which is assumably very inefficient).
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface Untraversable {
+ //this is a pure marker interface
+}
diff --git a/src/org/python/core/Visitproc.java b/src/org/python/core/Visitproc.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/core/Visitproc.java
@@ -0,0 +1,7 @@
+package org.python.core;
+
+public interface Visitproc {
+ /**Must not be called with {@code null}.
+ */
+ public int visit(PyObject object, Object arg);
+}
diff --git a/src/org/python/core/__builtin__.java b/src/org/python/core/__builtin__.java
--- a/src/org/python/core/__builtin__.java
+++ b/src/org/python/core/__builtin__.java
@@ -18,6 +18,7 @@
import org.python.core.util.RelativeFile;
import org.python.modules._functools._functools;
+ at Untraversable
class BuiltinFunctions extends PyBuiltinFunctionSet {
public static final PyObject module = Py.newString("__builtin__");
@@ -1249,6 +1250,7 @@
}
}
+ at Untraversable
class ImportFunction extends PyBuiltinFunction {
ImportFunction() {
super("__import__",
@@ -1280,6 +1282,7 @@
}
}
+ at Untraversable
class SortedFunction extends PyBuiltinFunction {
SortedFunction() {
super("sorted", "sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list");
@@ -1315,6 +1318,7 @@
}
}
+ at Untraversable
class AllFunction extends PyBuiltinFunctionNarrow {
AllFunction() {
super("all", 1, 1,
@@ -1337,6 +1341,7 @@
}
}
+ at Untraversable
class AnyFunction extends PyBuiltinFunctionNarrow {
AnyFunction() {
super("any", 1, 1,
@@ -1359,6 +1364,7 @@
}
}
+ at Untraversable
class FormatFunction extends PyBuiltinFunctionNarrow {
FormatFunction() {
super("format", 1, 2,
@@ -1382,6 +1388,7 @@
}
}
+ at Untraversable
class PrintFunction extends PyBuiltinFunction {
PrintFunction() {
@@ -1456,6 +1463,7 @@
}
}
+ at Untraversable
class MaxFunction extends PyBuiltinFunction {
MaxFunction() {
super("max",
@@ -1514,6 +1522,7 @@
}
+ at Untraversable
class MinFunction extends PyBuiltinFunction {
MinFunction() {
super("min",
@@ -1571,6 +1580,7 @@
}
}
+ at Untraversable
class RoundFunction extends PyBuiltinFunction {
RoundFunction() {
super("round", "round(number[, ndigits]) -> floating point number\n\n" +
@@ -1594,6 +1604,7 @@
}
}
+ at Untraversable
class CompileFunction extends PyBuiltinFunction {
CompileFunction() {
super("compile",
@@ -1684,6 +1695,7 @@
}
}
+ at Untraversable
class OpenFunction extends PyBuiltinFunction {
OpenFunction() {
super("open", "Open a file using the file() type, returns a file object. This is the\n"
@@ -1714,6 +1726,7 @@
}
}
+ at Untraversable
class NextFunction extends PyBuiltinFunction {
NextFunction() {
super("next", "next(iterator[, default])\n\n"
@@ -1745,6 +1758,7 @@
}
}
+ at Untraversable
class BinFunction extends PyBuiltinFunction {
BinFunction() {
super("bin", "bin(number)\n\n"
diff --git a/src/org/python/core/exceptions.java b/src/org/python/core/exceptions.java
--- a/src/org/python/core/exceptions.java
+++ b/src/org/python/core/exceptions.java
@@ -10,6 +10,7 @@
* The builtin exceptions module. The entire module should be imported from
* python. None of the methods defined here should be called from java.
*/
+ at Untraversable
public class exceptions extends PyObject implements ClassDictInit {
public static String __doc__ = "Python's standard exception class hierarchy.\n"
@@ -640,6 +641,7 @@
return new BoundStaticJavaMethod(name, javaMethod);
}
+ @Untraversable
static class BoundStaticJavaMethod extends PyBuiltinMethod {
/** The Java Method to be bound. Its signature must be:
diff --git a/src/org/python/core/finalization/FinalizableBuiltin.java b/src/org/python/core/finalization/FinalizableBuiltin.java
--- a/src/org/python/core/finalization/FinalizableBuiltin.java
+++ b/src/org/python/core/finalization/FinalizableBuiltin.java
@@ -4,15 +4,15 @@
* See documentation of {@link FinalizablePyObject}.
*/
-public interface FinalizableBuiltin extends HasFinalizeTrigger {
- /**
- * {@code __del_builtin__} is the built-in's own finalizer, while
- * {@code __del_derived__} refers to an instance's in-dict {@code __del__}.
- * A FinalizeTrigger calls {@code __del_derived__} first and
+public interface FinalizableBuiltin {
+ /**
+ * {@code __del_builtin__} is the built-in's own finalizer, while
+ * {@code __del_derived__} refers to an instance's in-dict {@code __del__}.
+ * A FinalizeTrigger calls {@code __del_derived__} first and
* - if existent - {@code __del_builtin__} after that. A plain {@code __del__}
* would behave as overwritten by {@code __del__Derived}, i.e. won't be called
* if the type implements {@code FinalizablePyObjectDerived} while
* {@code __del_builtin__} is called in any case.
- */
- public void __del_builtin__();
+ */
+ public void __del_builtin__();
}
diff --git a/src/org/python/core/finalization/FinalizablePyObject.java b/src/org/python/core/finalization/FinalizablePyObject.java
--- a/src/org/python/core/finalization/FinalizablePyObject.java
+++ b/src/org/python/core/finalization/FinalizablePyObject.java
@@ -1,5 +1,7 @@
package org.python.core.finalization;
+import org.python.core.JyAttribute;
+
/**
* <p>
* This interface allows {@code PyObject}s to have finalizers.
@@ -24,31 +26,18 @@
* </p>
* <p>
* If you are writing a custom built-in that shall directly
- * extend {@link org.python.core.PyObject} and have a finalizer, you can simply
- * extend {@link org.python.core.finalization.PyFinalizableObject}
- * and overwrite its {@code __del__}-method.
- * Follow the instructions below, starting at 4).
+ * extend {@link org.python.core.PyObject} or some other not-yet-finalizable
+ * builtin and have a finalizer, follow the instructions below.
* </p>
* <p>
- * If you want to extend some subclass of PyObject that does not yet implement
- * this interface, you have to take care of the following steps:
* <ol>
* <li>
* Let your subclass implement {@code FinalizablePyObject}
* (or {@link org.python.core.finalization.FinalizableBuiltin}).
* </li>
* <li>
- * Let it have a member<br>
- * {@code public FinalizeTrigger finalizeTrigger;}<br>
- * Other scopes also work, but might fail with security managers.
- * </li>
- * <li>
- * In every constructor initialize this member via<br>
- * {@code finalizeTrigger = FinalizeTrigger.makeTrigger(this);}<br>
- * or<br>
+ * In every constructor call<br>
* {@code FinalizeTrigger.ensureFinalizer(this);}<br>
- * The latter is a better abstraction, but slightly less performant,
- * since it uses reflection.
* </li>
* <li>
* Write your {@code __del__}-method however you intend it.
@@ -72,7 +61,7 @@
* <p>
* Note: Regarding to object resurrection, Jython currently behaves like CPython >= 3.4.
* That means the finalizer {@code __del__} or {@code __del_builtin__} is called only the
- * first time an object gets gc'ed. If pre 3.4. behavior is required for some reason (i.e.
+ * first time an object gets gc'ed. If pre-3.4.-behavior is required for some reason (i.e.
* have the finalizer called repeatedly on every collection after a resurrection), one can
* achieve this manually via step 5).
* </p>
@@ -98,12 +87,12 @@
* </p>
* <p>
* To turn off the finalizer, call</br>
- * {@code finalizeTrigger.clear();}</br>
+ * {@code ((FinalizeTrigger) JyAttribute.getAttr(this, JyAttribute.FINALIZE_TRIGGER_ATTR)).clear();}</br>
* To turn it on again, call</br>
- * {@code finalizeTrigger.trigger(this);}
+ * {@code ((FinalizeTrigger) JyAttribute.getAttr(this, JyAttribute.FINALIZE_TRIGGER_ATTR)).trigger(this);}
* </p>
*/
-public interface FinalizablePyObject extends HasFinalizeTrigger {
+public interface FinalizablePyObject {
public void __del__();
}
diff --git a/src/org/python/core/finalization/FinalizablePyObjectDerived.java b/src/org/python/core/finalization/FinalizablePyObjectDerived.java
--- a/src/org/python/core/finalization/FinalizablePyObjectDerived.java
+++ b/src/org/python/core/finalization/FinalizablePyObjectDerived.java
@@ -1,23 +1,24 @@
package org.python.core.finalization;
/**
- * This interface should never be used directly in any hand-written code.
+ * This interface should never be used directly in any hand-written code
+ * (except in FinalizeTrigger.java).
* It should only appear in automatically generated {@code fooDerived}-classes.
*
* To use finalizers in hand-written classes read the instructions at
* {@link org.python.core.finalization.FinalizablePyObject}.
*
*/
-public interface FinalizablePyObjectDerived extends HasFinalizeTrigger {
-
- /**
- * {@code __del_builtin__} is the built-in's own finalizer, while
- * {@code __del_derived__} refers to an instance's in-dict {@code __del__}.
- * A FinalizeTrigger calls {@code __del_derived__} first and
+public interface FinalizablePyObjectDerived {
+
+ /**
+ * {@code __del_builtin__} is the built-in's own finalizer, while
+ * {@code __del_derived__} refers to an instance's in-dict {@code __del__}.
+ * A FinalizeTrigger calls {@code __del_derived__} first and
* - if existent - {@code __del_builtin__} after that. A plain {@code __del__}
* would behave as overwritten by {@code __del_derived__}, i.e. won't be called
* if the type implements {@code FinalizablePyObjectDerived} while
* {@code __del_builtin__} is called in any case.
- */
- public void __del_derived__();
+ */
+ public void __del_derived__();
}
diff --git a/src/org/python/core/finalization/FinalizeTrigger.java b/src/org/python/core/finalization/FinalizeTrigger.java
--- a/src/org/python/core/finalization/FinalizeTrigger.java
+++ b/src/org/python/core/finalization/FinalizeTrigger.java
@@ -1,12 +1,60 @@
package org.python.core.finalization;
-import java.lang.reflect.Field;
+import org.python.core.PyObject;
+import org.python.core.JyAttribute;
+import org.python.core.Py;
+import org.python.modules.gc;
/**
* To use finalizers on {@code PyObject}s, read the documentation of
* {@link org.python.core.finalization.FinalizablePyObject}.
*/
public class FinalizeTrigger {
+ /**
+ * This flag tells the finalize trigger to call
+ * gc.notifyFinalize after it called the finalizer.
+ */
+ public static final byte NOTIFY_GC_FLAG = (1<<0);
+
+ /**
+ * This flag tells the finalize trigger to refrain from actually
+ * running the PyObject's {@code __del__} method (or variants for
+ * derived or builtins).
+ * It can be used to have finalize triggers for debugging and
+ * monitoring purposes. The actual purpose is for Jython gc's
+ * {@code DONT_FINALIZE_CYCLIC_GARBAGE} flag that tells the gc to emulate
+ * CPython's <3.4 policy never to finalize cyclic garbage.
+ */
+ //public static final byte INHIBIT_FINALIZER_FLAG = (1<<1);
+
+ /**
+ * Tells the finalizer to add the finalized PyObject to the gc's
+ * garbage list. This allows gc to mimic CPython's way to deal
+ * with cyclic finalizable objects prior 3.4
+ * (c.f. CPython's gc's DEBUG_SAVEALL flag).
+ */
+ //public static final byte ADD_TO_GARBAGE_LIST_FLAG = (1<<2);
+
+ /**
+ * Similar to {@code INHIBIT_FINALIZER_FLAG}, but indicates that the
+ * underlying PyObject was never intended to be finalized, while
+ * {@code INHIBIT_FINALIZER_FLAG} indicates that there actually *is* a
+ * finalizer that is just not processed due to special
+ * circumstances (i.e. inactive {@code DONT_FINALIZE_CYCLIC_GARBAGE} flag).
+ */
+ public static final byte NOT_FINALIZABLE_FLAG = (1<<3);
+
+ /**
+ * Indicates that only
+ * {@link org.python.core.finalization.FinalizableBuiltin}
+ * shall be called.
+ */
+ public static final byte ONLY_BUILTIN_FLAG = (1<<4);
+
+ /**
+ * Indicates that this trigger was already finalized.
+ */
+ public static final byte FINALIZED_FLAG = (1<<5);
/**
* This factory hook is reserved for use by JyNI.
@@ -15,7 +63,7 @@
*/
public static FinalizeTriggerFactory factory;
- public static FinalizeTrigger makeTrigger(HasFinalizeTrigger toFinalize) {
+ public static FinalizeTrigger makeTrigger(PyObject toFinalize) {
if (factory != null) {
return factory.makeTrigger(toFinalize);
} else {
@@ -23,80 +71,162 @@
}
}
+ public static boolean hasActiveTrigger(PyObject obj) {
+ Object fn = JyAttribute.getAttr(obj, JyAttribute.FINALIZE_TRIGGER_ATTR);
+ return fn != null && ((FinalizeTrigger) fn).isActive();
+ }
+
+ public static boolean isFinalizable(PyObject obj) {
+ return obj instanceof FinalizablePyObject || obj instanceof FinalizableBuiltin
+ || obj instanceof FinalizablePyObjectDerived;
+ }
+
/**
* Recreates the {@code FinalizeTrigger} of the given object. This makes sure that
* once the resurrected object is gc'ed again, its {@code __del__}-method will be
* called again.
*/
- public static void ensureFinalizer(HasFinalizeTrigger resurrect) {
- FinalizeTrigger trigger = makeTrigger(resurrect);
- setFinalizeTrigger(resurrect, trigger);
+ public static void ensureFinalizer(PyObject resurrect) {
+ JyAttribute.setAttr(resurrect, JyAttribute.FINALIZE_TRIGGER_ATTR,
+ makeTrigger(resurrect));
}
- public static void setFinalizeTrigger(HasFinalizeTrigger toFinalize, FinalizeTrigger trigger) {
- Field triggerField;
- try {
- triggerField = toFinalize.getClass().getDeclaredField("finalizeTrigger");
- } catch (NoSuchFieldException nfe) {
- throw new IllegalArgumentException(toFinalize.getClass()+" must have a field finalizeTrigger.");
+ public static void runFinalizer(PyObject toFinalize) {
+ runFinalizer(toFinalize, false);
+ }
+
+ public static void runFinalizer(PyObject toFinalize, boolean runBuiltinOnly) {
+ if (!runBuiltinOnly) {
+ if (toFinalize instanceof FinalizablePyObjectDerived) {
+ try {
+ ((FinalizablePyObjectDerived) toFinalize).__del_derived__();
+ } catch (Exception e) {}
+ } else if (toFinalize instanceof FinalizablePyObject) {
+ try {
+ ((FinalizablePyObject) toFinalize).__del__();
+ } catch (Exception e) {}
+ }
}
- try {
- triggerField.set(toFinalize, trigger);
- } catch (IllegalAccessException iae) {
+ if (toFinalize instanceof FinalizableBuiltin) {
try {
- triggerField.setAccessible(true);
- triggerField.set(toFinalize, trigger);
- } catch (Exception e) {
- throw new IllegalArgumentException("finalizeTrigger in "+toFinalize.getClass()+" must be accessible.");
- }
+ ((FinalizableBuiltin) toFinalize).__del_builtin__();
+ } catch (Exception e) {}
}
}
- public static FinalizeTrigger getFinalizeTrigger(HasFinalizeTrigger toFinalize) {
- Field triggerField;
- try {
- triggerField = toFinalize.getClass().getDeclaredField("finalizeTrigger");
- } catch (NoSuchFieldException nfe) {
- throw new IllegalArgumentException(toFinalize.getClass()+" must have a field finalizeTrigger.");
- }
- try {
- return (FinalizeTrigger) triggerField.get(toFinalize);
- } catch (IllegalAccessException iae) {
- try {
- triggerField.setAccessible(true);
- return (FinalizeTrigger) triggerField.get(toFinalize);
- } catch (Exception e) {
- throw new IllegalArgumentException("finalizeTrigger in "+toFinalize.getClass()+" must be accessible.");
- }
+ public static void appendFinalizeTriggerForBuiltin(PyObject obj) {
+ if (obj instanceof FinalizableBuiltin) {
+ FinalizeTrigger ft = makeTrigger(obj);
+ ft.flags = ONLY_BUILTIN_FLAG;
+ JyAttribute.setAttr(obj, JyAttribute.FINALIZE_TRIGGER_ATTR, ft);
+ } else {
+ JyAttribute.delAttr(obj, JyAttribute.FINALIZE_TRIGGER_ATTR);
}
}
-
- protected HasFinalizeTrigger toFinalize;
+ protected PyObject toFinalize;
+ public byte flags = 0;
public void clear() {
toFinalize = null;
}
- public void trigger(HasFinalizeTrigger toFinalize)
+ public void trigger(PyObject toFinalize)
{
this.toFinalize = toFinalize;
}
- protected FinalizeTrigger(HasFinalizeTrigger toFinalize) {
+ public boolean isActive() {
+ return toFinalize != null;
+ }
+
+ protected FinalizeTrigger(PyObject toFinalize) {
this.toFinalize = toFinalize;
}
- protected void finalize() throws Throwable {
- if (toFinalize != null) {
- if (toFinalize instanceof FinalizablePyObjectDerived) {
- ((FinalizablePyObjectDerived) toFinalize).__del_derived__();
- } else if (toFinalize instanceof FinalizablePyObject) {
- ((FinalizablePyObject) toFinalize).__del__();
- }
- if (toFinalize instanceof FinalizableBuiltin) {
- ((FinalizableBuiltin) toFinalize).__del_builtin__();
- }
+ protected boolean isCyclic() {
+ gc.CycleMarkAttr cm = (gc.CycleMarkAttr)
+ JyAttribute.getAttr(toFinalize, JyAttribute.GC_CYCLE_MARK_ATTR);
+ if (cm != null && cm.isCyclic()) {
+ return true;
+ } else {
+ gc.markCyclicObjects(toFinalize, (flags & NOT_FINALIZABLE_FLAG) == 0);
+ cm = (gc.CycleMarkAttr)
+ JyAttribute.getAttr(toFinalize, JyAttribute.GC_CYCLE_MARK_ATTR);
+ return cm != null && cm.isCyclic();
}
}
+
+ protected boolean isUncollectable() {
+ gc.CycleMarkAttr cm = (gc.CycleMarkAttr)
+ JyAttribute.getAttr(toFinalize, JyAttribute.GC_CYCLE_MARK_ATTR);
+ if (cm != null && cm.isUncollectable()) {
+ return true;
+ } else {
+ gc.markCyclicObjects(toFinalize, (flags & NOT_FINALIZABLE_FLAG) == 0);
+ cm = (gc.CycleMarkAttr)
+ JyAttribute.getAttr(toFinalize, JyAttribute.GC_CYCLE_MARK_ATTR);
+ return cm != null && cm.isUncollectable();
+ }
+ }
+
+ public void performFinalization() {
+ if (toFinalize != null) {
+ byte saveGarbage = 0;
+ if ((gc.getJythonGCFlags() & gc.DONT_FINALIZE_CYCLIC_GARBAGE) != 0) {
+ if (isUncollectable()) {
+ saveGarbage = 1;
+ } else if (!isCyclic()) {
+ saveGarbage = -1;
+ runFinalizer(toFinalize, (flags & ONLY_BUILTIN_FLAG) != 0);
+ }
+ } else {
+ if ((flags & NOT_FINALIZABLE_FLAG) == 0) {
+ runFinalizer(toFinalize, (flags & ONLY_BUILTIN_FLAG) != 0);
+ }
+ }
+ if ((gc.getJythonGCFlags() & gc.VERBOSE_FINALIZE) != 0) {
+ Py.writeDebug("gc", "finalization of "+toFinalize);
+ }
+ if (saveGarbage == 1 || (saveGarbage == 0 &&
+ (gc.get_debug() & gc.DEBUG_SAVEALL) != 0 && isCyclic())) {
+ if ((flags & NOT_FINALIZABLE_FLAG) == 0) {
+ //Finalizable objects in gc.garbage get a special FinalizeTrigger
+ //that only runs the builtin finalizer. This is needed because
+ //from Python the user can't call the builtin-part of the
+ //finalizer by hand.
+ appendFinalizeTriggerForBuiltin(toFinalize);
+ }
+ gc.garbage.add(toFinalize);
+ if ((gc.getJythonGCFlags() & gc.VERBOSE_FINALIZE) != 0) {
+ Py.writeDebug("gc", toFinalize+" added to garbage.");
+ }
+ }
+ }
+ if ((flags & NOTIFY_GC_FLAG) != 0) {
+ if ((gc.getJythonGCFlags() & gc.VERBOSE_FINALIZE) != 0) {
+ Py.writeDebug("gc", "notify finalization of "+toFinalize);
+ }
+ gc.notifyFinalize(toFinalize);
+ flags &= ~NOTIFY_GC_FLAG;
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ flags |= FINALIZED_FLAG;
+ gc.notifyPreFinalization();
+ if (gc.delayedFinalizationEnabled() && toFinalize != null) {
+ if ((gc.getJythonGCFlags() & gc.VERBOSE_FINALIZE) != 0) {
+ Py.writeDebug("gc", "delayed finalization for "+toFinalize);
+ }
+ gc.registerForDelayedFinalization(toFinalize);
+ } else {
+ performFinalization();
+ }
+ gc.notifyPostFinalization();
+ }
+
+ public boolean isFinalized() {
+ return (flags & FINALIZED_FLAG) != 0;
+ }
}
diff --git a/src/org/python/core/finalization/FinalizeTriggerFactory.java b/src/org/python/core/finalization/FinalizeTriggerFactory.java
--- a/src/org/python/core/finalization/FinalizeTriggerFactory.java
+++ b/src/org/python/core/finalization/FinalizeTriggerFactory.java
@@ -1,9 +1,11 @@
package org.python.core.finalization;
+import org.python.core.PyObject;
+
/**
* Reserved for use by JyNI.
*/
public interface FinalizeTriggerFactory {
- public FinalizeTrigger makeTrigger(HasFinalizeTrigger toFinalize);
+ public FinalizeTrigger makeTrigger(PyObject toFinalize);
}
diff --git a/src/org/python/core/finalization/HasFinalizeTrigger.java b/src/org/python/core/finalization/HasFinalizeTrigger.java
deleted file mode 100644
--- a/src/org/python/core/finalization/HasFinalizeTrigger.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.python.core.finalization;
-
-/**
- * This is a pure marker-interface to indicate that a
- * {@link org.python.core.PyObject} has a field declaration
- * {@code FinalizeTrigger finalizeTrigger;}
- * and thus can be treated by Jython's finalization API.
- *
- * For detailed instructions how to use finalizers in Jython, see
- * {@link org.python.core.finalization.FinalizablePyObject}.
- */
-public interface HasFinalizeTrigger {
-}
diff --git a/src/org/python/core/finalization/PyFinalizableObject.java b/src/org/python/core/finalization/PyFinalizableObject.java
deleted file mode 100644
--- a/src/org/python/core/finalization/PyFinalizableObject.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.python.core.finalization;
-
-import org.python.core.PyObject;;
-
-/**
- * For detailed intructions how to use finalizers on PyObjects,
- * read the documentation of {@link org.python.core.finalization.FinalizablePyObject}.
- */
-public abstract class PyFinalizableObject extends PyObject implements FinalizablePyObject {
-
- public FinalizeTrigger finalizeTrigger;
-
- public PyFinalizableObject() {
- super();
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
- }
-}
diff --git a/src/org/python/core/stringlib/FieldNameIterator.java b/src/org/python/core/stringlib/FieldNameIterator.java
--- a/src/org/python/core/stringlib/FieldNameIterator.java
+++ b/src/org/python/core/stringlib/FieldNameIterator.java
@@ -8,8 +8,11 @@
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.PyUnicode;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
+import org.python.modules.gc;
/**
* This class is an implementation of the iterator object returned by
@@ -20,8 +23,9 @@
* function, since as well as "being" the iterator, the object has an extra method {@link #head()}
* to return the required first member of the pair.
*/
+
@ExposedType(name = "fieldnameiterator", base = PyObject.class, isBaseType = false)
-public class FieldNameIterator extends PyObject {
+public class FieldNameIterator extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(FieldNameIterator.class);
@@ -219,4 +223,26 @@
/** Integer or String. */
public Object value;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (head == null || !gc.canLinkToPyObject(head.getClass(), true)) {
+ return 0;
+ }
+ return gc.traverseByReflection(head, visit, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob)
+ throws UnsupportedOperationException {
+ if (ob != null && ob == head) {
+ return true;
+ }
+ if (!gc.canLinkToPyObject(head.getClass(), true)) {
+ return false;
+ }
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/src/org/python/core/stringlib/MarkupIterator.java b/src/org/python/core/stringlib/MarkupIterator.java
--- a/src/org/python/core/stringlib/MarkupIterator.java
+++ b/src/org/python/core/stringlib/MarkupIterator.java
@@ -6,6 +6,7 @@
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.PyUnicode;
+import org.python.core.Untraversable;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
@@ -14,6 +15,7 @@
* is an iterator returning successive 4-tuples, the sequence being equivalent to the original
* string.
*/
+ at Untraversable
@ExposedType(name = "formatteriterator", base = PyObject.class, isBaseType = false)
public class MarkupIterator extends PyObject {
diff --git a/src/org/python/jsr223/PyScriptEngineScope.java b/src/org/python/jsr223/PyScriptEngineScope.java
--- a/src/org/python/jsr223/PyScriptEngineScope.java
+++ b/src/org/python/jsr223/PyScriptEngineScope.java
@@ -14,6 +14,8 @@
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyType;
+import org.python.core.Visitproc;
+import org.python.core.Untraversable;
import org.python.expose.ExposedType;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
@@ -24,6 +26,7 @@
* with its own bindings. We adapt this multi-scope object for use as both
* a local and global dictionary.
*/
+ at Untraversable
@ExposedType(name = "scope", isBaseType = false)
public final class PyScriptEngineScope extends PyObject {
public static final PyType TYPE = PyType.fromClass(PyScriptEngineScope.class);
@@ -202,5 +205,21 @@
}
return result;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return _keys != null ? visit.visit(_keys, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == _keys || super.refersDirectlyTo(ob));
+ }
}
}
diff --git a/src/org/python/modules/PyIOFileFactory.java b/src/org/python/modules/PyIOFileFactory.java
--- a/src/org/python/modules/PyIOFileFactory.java
+++ b/src/org/python/modules/PyIOFileFactory.java
@@ -7,6 +7,8 @@
import org.python.core.PyString;
import org.python.core.PyType;
import org.python.core.__builtin__;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
// XXX - add support for StringIO, not just cStringIO
@@ -59,7 +61,7 @@
// Use a PyFile as a file.
- static class FileIOFile implements PyIOFile {
+ static class FileIOFile implements PyIOFile, Traverseproc {
PyFile file;
@@ -89,11 +91,23 @@
String line = file.readline().toString();
return line.substring(0, line.length() - 1);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return file == null ? 0 : visit.visit(file, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == file;
+ }
}
// Use any python object as a file.
- static class ObjectIOFile implements PyIOFile {
+ static class ObjectIOFile implements PyIOFile, Traverseproc {
char[] charr = new char[1];
StringBuilder buff = new StringBuilder();
@@ -136,6 +150,31 @@
String line = readline.__call__().toString();
return line.substring(0, line.length() - 1);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (write != null) {
+ retVal = visit.visit(write, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (read != null) {
+ retVal = visit.visit(read, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return readline == null ? 0 : visit.visit(readline, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == write || ob == read || ob == readline);
+ }
}
}
diff --git a/src/org/python/modules/PyStruct.java b/src/org/python/modules/PyStruct.java
--- a/src/org/python/modules/PyStruct.java
+++ b/src/org/python/modules/PyStruct.java
@@ -8,11 +8,13 @@
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Untraversable;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "struct.Struct", base = PyObject.class)
public class PyStruct extends PyObject {
public static final PyType TYPE = PyType.fromClass(PyStruct.class);
diff --git a/src/org/python/modules/PyStructDerived.java b/src/org/python/modules/PyStructDerived.java
--- a/src/org/python/modules/PyStructDerived.java
+++ b/src/org/python/modules/PyStructDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyStructDerived extends PyStruct implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyStructDerived extends PyStruct implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/_codecs.java b/src/org/python/modules/_codecs.java
--- a/src/org/python/modules/_codecs.java
+++ b/src/org/python/modules/_codecs.java
@@ -20,6 +20,7 @@
import org.python.core.PyTuple;
import org.python.core.PyUnicode;
import org.python.core.codecs;
+import org.python.core.Untraversable;
import org.python.expose.ExposedType;
/**
@@ -1605,6 +1606,7 @@
* Uses a trie structure instead of a dictionary; the speedup primarily comes from not creating
* integer objects in the process. The trie is created by inverting the encoding map.
*/
+ @Untraversable
@ExposedType(name = "EncodingMap", isBaseType = false)
public static class EncodingMap extends PyObject {
diff --git a/src/org/python/modules/_collections/PyDefaultDict.java b/src/org/python/modules/_collections/PyDefaultDict.java
--- a/src/org/python/modules/_collections/PyDefaultDict.java
+++ b/src/org/python/modules/_collections/PyDefaultDict.java
@@ -12,6 +12,8 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedDelete;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
@@ -35,7 +37,7 @@
* passed to the dict constructor, including keyword arguments.
*/
@ExposedType(name = "collections.defaultdict")
-public class PyDefaultDict extends PyDictionary {
+public class PyDefaultDict extends PyDictionary implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyDefaultDict.class);
/**
@@ -176,4 +178,46 @@
return defaultObj;
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ retVal = visit.visit(defaultFactory, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (backingMap != null) {
+ for (Map.Entry<PyObject, PyObject> ent: backingMap.asMap().entrySet()) {
+ retVal = visit.visit(ent.getKey(), arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (ent.getValue() != null) {
+ retVal = visit.visit(ent.getValue(), arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null) {
+ return false;
+ } else if (super.refersDirectlyTo(ob)) {
+ return true;
+ }
+ if (backingMap == null) {
+ return false;
+ }
+ return backingMap.asMap().containsKey(ob) || backingMap.asMap().containsValue(ob);
+ }
}
diff --git a/src/org/python/modules/_collections/PyDefaultDictDerived.java b/src/org/python/modules/_collections/PyDefaultDictDerived.java
--- a/src/org/python/modules/_collections/PyDefaultDictDerived.java
+++ b/src/org/python/modules/_collections/PyDefaultDictDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyDefaultDictDerived extends PyDefaultDict implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyDefaultDictDerived extends PyDefaultDict implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/_collections/PyDeque.java b/src/org/python/modules/_collections/PyDeque.java
--- a/src/org/python/modules/_collections/PyDeque.java
+++ b/src/org/python/modules/_collections/PyDeque.java
@@ -9,6 +9,8 @@
import org.python.core.Py;
import org.python.core.PyException;
import org.python.core.ThreadState;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -33,7 +35,7 @@
* items are added, a corresponding number of items are discarded from the opposite end.
*/
@ExposedType(name = "collections.deque")
-public class PyDeque extends PyObject {
+public class PyDeque extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyDeque.class);
@@ -105,7 +107,7 @@
/**
* Add obj to the right side of the deque.
- */
+ */
@ExposedMethod
public synchronized final void deque_append(PyObject obj) {
if (maxlen >= 0) {
@@ -625,7 +627,7 @@
@ExposedMethod
final PyObject deque___copy__() {
- PyDeque pd = (PyDeque)this.getType().__call__();
+ PyDeque pd = (PyDeque)this.getType().__call__();
pd.deque_extend(this);
return pd;
}
@@ -674,5 +676,56 @@
return null;
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return lastReturned == null ? 0 : traverseNode(lastReturned, visit, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ if (ob == null) {
+ return false;
+ } else if (super.refersDirectlyTo(ob)) {
+ return true;
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ }
+ }
+
+
+ /* Traverseproc implementation */
+ private static int traverseNode(Node node, Visitproc visit, Object arg) {
+ int retVal;
+ if (node.data != null) {
+ retVal = visit.visit(node.data, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (node.left != null) {
+ retVal = traverseNode(node.left, visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return node.right == null ? 0 : traverseNode(node.right, visit, arg);
+ }
+
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return header == null ? 0 : traverseNode(header, visit, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
}
}
diff --git a/src/org/python/modules/_collections/PyDequeDerived.java b/src/org/python/modules/_collections/PyDequeDerived.java
--- a/src/org/python/modules/_collections/PyDequeDerived.java
+++ b/src/org/python/modules/_collections/PyDequeDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyDequeDerived extends PyDeque implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyDequeDerived extends PyDeque implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/_csv/PyDialect.java b/src/org/python/modules/_csv/PyDialect.java
--- a/src/org/python/modules/_csv/PyDialect.java
+++ b/src/org/python/modules/_csv/PyDialect.java
@@ -9,6 +9,7 @@
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyType;
+import org.python.core.Untraversable;
import org.python.expose.ExposedDelete;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedNew;
@@ -18,6 +19,7 @@
/**
* The Python CSV Dialect type.
*/
+ at Untraversable
@ExposedType(name = "_csv.Dialect", doc = PyDialect.Dialect_doc)
public class PyDialect extends PyObject {
public static final PyType TYPE = PyType.fromClass(PyDialect.class);
diff --git a/src/org/python/modules/_csv/PyDialectDerived.java b/src/org/python/modules/_csv/PyDialectDerived.java
--- a/src/org/python/modules/_csv/PyDialectDerived.java
+++ b/src/org/python/modules/_csv/PyDialectDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyDialectDerived extends PyDialect implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyDialectDerived extends PyDialect implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,17 +27,35 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
public PyDialectDerived(PyType subtype) {
super(subtype);
slots=new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return 0;
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/_csv/PyReader.java b/src/org/python/modules/_csv/PyReader.java
--- a/src/org/python/modules/_csv/PyReader.java
+++ b/src/org/python/modules/_csv/PyReader.java
@@ -6,6 +6,7 @@
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedType;
@@ -272,4 +273,33 @@
START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD, IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD,
QUOTE_IN_QUOTED_FIELD, EAT_CRNL;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (dialect != null) {
+ retVal = visit.visit(dialect, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (input_iter != null) {
+ retVal = visit.visit(input_iter, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return fields != null ? visit.visit(fields, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob == null && (ob == fields || ob == dialect
+ || ob == input_iter || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/_csv/PyWriter.java b/src/org/python/modules/_csv/PyWriter.java
--- a/src/org/python/modules/_csv/PyWriter.java
+++ b/src/org/python/modules/_csv/PyWriter.java
@@ -7,6 +7,8 @@
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedType;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedGet;
@@ -17,7 +19,7 @@
* Analogous to CPython's _csv.c::WriterObj struct.
*/
@ExposedType(name = "_csv.writer", doc = PyWriter.writer_doc)
-public class PyWriter extends PyObject {
+public class PyWriter extends PyObject implements Traverseproc {
public static final String writer_doc =
"CSV writer\n" +
@@ -137,7 +139,6 @@
} else if (field == Py.None) {
append_ok = join_append("", len == 1);
} else {
-
PyObject str;
//XXX: in 3.x this check can go away and we can just always use
// __str__
@@ -280,4 +281,22 @@
}
rec_len++;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (dialect != null) {
+ int retVal = visit.visit(dialect, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return writeline != null ? visit.visit(writeline, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == dialect || ob == writeline);
+ }
}
diff --git a/src/org/python/modules/_functools/PyPartial.java b/src/org/python/modules/_functools/PyPartial.java
--- a/src/org/python/modules/_functools/PyPartial.java
+++ b/src/org/python/modules/_functools/PyPartial.java
@@ -10,6 +10,8 @@
import org.python.core.PyStringMap;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -18,7 +20,7 @@
import org.python.util.Generic;
@ExposedType(name = "_functools.partial")
-public class PyPartial extends PyObject {
+public class PyPartial extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyPartial.class);
@@ -150,7 +152,7 @@
@Override
public void __setattr__(String name, PyObject value) {
- partial___setattr__(name, value);
+ partial___setattr__(name, value);
}
@ExposedMethod
@@ -185,4 +187,43 @@
__dict__ = new PyStringMap();
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (func != null) {
+ retVal = visit.visit(func, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (args != null) {
+ for (PyObject ob: args) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return __dict__ != null ? visit.visit(__dict__, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null) {
+ return false;
+ }
+ if (args != null) {
+ for (PyObject obj: args) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ }
+ return ob == func || ob == __dict__;
+ }
}
diff --git a/src/org/python/modules/_functools/PyPartialDerived.java b/src/org/python/modules/_functools/PyPartialDerived.java
--- a/src/org/python/modules/_functools/PyPartialDerived.java
+++ b/src/org/python/modules/_functools/PyPartialDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyPartialDerived extends PyPartial implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyPartialDerived extends PyPartial implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/_hashlib.java b/src/org/python/modules/_hashlib.java
--- a/src/org/python/modules/_hashlib.java
+++ b/src/org/python/modules/_hashlib.java
@@ -13,6 +13,7 @@
import org.python.core.PyString;
import org.python.core.PyType;
import org.python.core.PyUnicode;
+import org.python.core.Untraversable;
import org.python.core.util.StringUtil;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
@@ -111,6 +112,7 @@
/**
* A generic wrapper around a MessageDigest.
*/
+ @Untraversable
@ExposedType(name = "_hashlib.HASH")
public static class Hash extends PyObject {
diff --git a/src/org/python/modules/_io/Closer.java b/src/org/python/modules/_io/Closer.java
--- a/src/org/python/modules/_io/Closer.java
+++ b/src/org/python/modules/_io/Closer.java
@@ -30,7 +30,7 @@
private final WeakReference<C> client;
/** Interpreter state that will call {@link #call()} on shutdown. */
- private PySystemState sys;
+ protected PySystemState sys;
public Closer(C toClose, PySystemState sys) {
this.client = new WeakReference<C>(toClose);
diff --git a/src/org/python/modules/_io/PyFileIO.java b/src/org/python/modules/_io/PyFileIO.java
--- a/src/org/python/modules/_io/PyFileIO.java
+++ b/src/org/python/modules/_io/PyFileIO.java
@@ -19,6 +19,7 @@
import org.python.core.PyString;
import org.python.core.PyType;
import org.python.core.PyUnicode;
+import org.python.core.Untraversable;
import org.python.core.io.FileIO;
import org.python.core.io.RawIOBase;
import org.python.core.io.StreamIO;
@@ -30,6 +31,7 @@
import jnr.constants.platform.Errno;
+ at Untraversable
@ExposedType(name = "_io.FileIO", base = PyRawIOBase.class)
public class PyFileIO extends PyRawIOBase {
diff --git a/src/org/python/modules/_io/PyFileIODerived.java b/src/org/python/modules/_io/PyFileIODerived.java
--- a/src/org/python/modules/_io/PyFileIODerived.java
+++ b/src/org/python/modules/_io/PyFileIODerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyFileIODerived extends PyFileIO implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyFileIODerived extends PyFileIO implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,17 +27,35 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
public PyFileIODerived(PyType subtype,PyObject file,OpenMode mode,boolean closefd) {
super(subtype,file,mode,closefd);
slots=new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return 0;
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/_io/PyIOBase.java b/src/org/python/modules/_io/PyIOBase.java
--- a/src/org/python/modules/_io/PyIOBase.java
+++ b/src/org/python/modules/_io/PyIOBase.java
@@ -19,6 +19,8 @@
import org.python.core.finalization.FinalizableBuiltin;
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.io.FileIO;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -40,24 +42,22 @@
* in Python.
*/
@ExposedType(name = "_io._IOBase", doc = PyIOBase.doc)
-public class PyIOBase extends PyObject implements FinalizableBuiltin {
+public class PyIOBase extends PyObject implements FinalizableBuiltin, Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyIOBase.class);
/** The ioDelegate's closer object; ensures the stream is closed at shutdown */
private Closer<PyIOBase> closer;
-
- public FinalizeTrigger finalizeTrigger;
protected PyIOBase() {
this(TYPE);
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
protected PyIOBase(PyType subtype) {
super(subtype);
closer = new Closer<PyIOBase>(this, Py.getSystemState());
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
/**
@@ -910,4 +910,23 @@
+ "fp is closed after the suite of the with statement is complete:\n" + "\n"
+ "with open('spam.txt', 'r') as fp:\n" + " fp.write('Spam and eggs!')\n";
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ //closer cannot be null
+ if (closer.sys != null) {
+ int retVal = visit.visit(closer.sys, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ //__dict__ cannot be null
+ return visit.visit(__dict__, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == closer.sys || ob == __dict__);
+ }
}
diff --git a/src/org/python/modules/_io/PyIOBaseDerived.java b/src/org/python/modules/_io/PyIOBaseDerived.java
--- a/src/org/python/modules/_io/PyIOBaseDerived.java
+++ b/src/org/python/modules/_io/PyIOBaseDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyIOBaseDerived extends PyIOBase implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyIOBaseDerived extends PyIOBase implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,17 +27,35 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
public PyIOBaseDerived(PyType subtype) {
super(subtype);
slots=new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return 0;
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/_io/PyRawIOBaseDerived.java b/src/org/python/modules/_io/PyRawIOBaseDerived.java
--- a/src/org/python/modules/_io/PyRawIOBaseDerived.java
+++ b/src/org/python/modules/_io/PyRawIOBaseDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyRawIOBaseDerived extends PyRawIOBase implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyRawIOBaseDerived extends PyRawIOBase implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,17 +27,35 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
public PyRawIOBaseDerived(PyType subtype) {
super(subtype);
slots=new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return 0;
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/_json/Encoder.java b/src/org/python/modules/_json/Encoder.java
--- a/src/org/python/modules/_json/Encoder.java
+++ b/src/org/python/modules/_json/Encoder.java
@@ -3,7 +3,6 @@
import org.python.core.ArgParser;
import org.python.core.Py;
import org.python.core.PyDictionary;
-import org.python.core.PyException;
import org.python.core.PyFloat;
import org.python.core.PyInteger;
import org.python.core.PyLong;
@@ -13,11 +12,13 @@
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.PyUnicode;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedType;
@ExposedType(name = "_json.encoder", base = PyObject.class)
-public class Encoder extends PyObject {
+public class Encoder extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(Encoder.class);
@@ -201,4 +202,55 @@
}
rval.append(new PyString("]"));
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (markers != null) {
+ retVal = visit.visit(markers, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (defaultfn != null) {
+ retVal = visit.visit(defaultfn, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (encoder != null) {
+ retVal = visit.visit(encoder, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (indent != null) {
+ retVal = visit.visit(indent, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (key_separator != null) {
+ retVal = visit.visit(key_separator, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (item_separator != null) {
+ retVal = visit.visit(item_separator, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return sort_keys != null ? visit.visit(sort_keys, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == markers || ob == defaultfn
+ || ob == encoder || ob == indent || ob == key_separator
+ || ob == item_separator || ob == sort_keys);
+ }
}
diff --git a/src/org/python/modules/_json/Scanner.java b/src/org/python/modules/_json/Scanner.java
--- a/src/org/python/modules/_json/Scanner.java
+++ b/src/org/python/modules/_json/Scanner.java
@@ -7,14 +7,15 @@
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.PyType;
-import org.python.core.PyUnicode;
import org.python.core.codecs;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedType;
@ExposedType(name = "_json.Scanner", base = PyObject.class)
-public class Scanner extends PyObject {
+public class Scanner extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(Scanner.class);
@@ -77,7 +78,6 @@
PyString str = pystr;
int end_idx = pystr.__len__() - 1;
PyList pairs = new PyList();
- PyObject item;
PyObject key;
PyObject val;
@@ -156,7 +156,6 @@
PyString str = pystr;
int end_idx = pystr.__len__() - 1;
PyList rval = new PyList();
- int next_idx;
/* skip whitespace after [ */
while (idx <= end_idx && IS_WHITESPACE(str.getInt(idx))) idx++;
@@ -340,4 +339,40 @@
}
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (object_hook != null) {
+ retVal = visit.visit(object_hook, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (pairs_hook != null) {
+ retVal = visit.visit(pairs_hook, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (parse_float != null) {
+ retVal = visit.visit(parse_float, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (parse_int != null) {
+ retVal = visit.visit(parse_int, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return parse_constant != null ? visit.visit(parse_constant, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == object_hook || ob == pairs_hook
+ || ob == parse_float || ob == parse_int || ob == parse_constant);
+ }
}
diff --git a/src/org/python/modules/_jythonlib/dict_builder.java b/src/org/python/modules/_jythonlib/dict_builder.java
--- a/src/org/python/modules/_jythonlib/dict_builder.java
+++ b/src/org/python/modules/_jythonlib/dict_builder.java
@@ -5,6 +5,8 @@
import org.python.core.PyDictionaryDerived;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import java.util.concurrent.ConcurrentMap;
@@ -21,7 +23,7 @@
* also be unboxed this way, so the wrapping thread could not be looked up!
*/
-public class dict_builder extends PyObject {
+public class dict_builder extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(dict_builder.class);
private final PyObject factory;
@@ -51,4 +53,15 @@
return dict;
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return factory != null ? visit.visit(factory, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && factory == ob;
+ }
}
diff --git a/src/org/python/modules/_marshal.java b/src/org/python/modules/_marshal.java
--- a/src/org/python/modules/_marshal.java
+++ b/src/org/python/modules/_marshal.java
@@ -17,6 +17,8 @@
import org.python.core.PySet;
import org.python.core.PyTuple;
import org.python.core.PyUnicode;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
public class _marshal implements ClassDictInit {
@@ -50,7 +52,7 @@
private final static int MAX_MARSHAL_STACK_DEPTH = 2000;
private final static int CURRENT_VERSION = 2;
- public static class Marshaller extends PyObject {
+ public static class Marshaller extends PyObject implements Traverseproc {
private final PyIOFile file;
private final int version;
@@ -241,11 +243,24 @@
}
depth--;
+ }
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return file != null && file instanceof Traverseproc ?
+ ((Traverseproc) file).traverse(visit, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return file != null && file instanceof Traverseproc ?
+ ((Traverseproc) file).refersDirectlyTo(ob) : false;
}
}
- public static class Unmarshaller extends PyObject {
+ public static class Unmarshaller extends PyObject implements Traverseproc {
private final PyIOFile file;
private final PyList strings = new PyList();
@@ -518,6 +533,30 @@
throw Py.ValueError("bad marshal data");
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (file instanceof Traverseproc) {
+ int retVal = ((Traverseproc) file).traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return visit.visit(strings, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null) {
+ return false;
+ } else if (file != null && file instanceof Traverseproc
+ && ((Traverseproc) file).refersDirectlyTo(ob)) {
+ return true;
+ } else {
+ return ob == strings;
+ }
+ }
}
}
-
diff --git a/src/org/python/modules/_threading/Condition.java b/src/org/python/modules/_threading/Condition.java
--- a/src/org/python/modules/_threading/Condition.java
+++ b/src/org/python/modules/_threading/Condition.java
@@ -10,9 +10,11 @@
import org.python.expose.ExposedType;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
@ExposedType(name = "_threading.Condition")
-public class Condition extends PyObject implements ContextManager {
+public class Condition extends PyObject implements ContextManager, Traverseproc {
public static final PyType TYPE = PyType.fromClass(Condition.class);
private final Lock _lock;
@@ -138,5 +140,16 @@
final boolean Condition__is_owned() {
return _lock._lock.isHeldByCurrentThread();
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return _lock != null ? visit.visit(_lock, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && _lock == ob;
+ }
}
-
diff --git a/src/org/python/modules/_threading/Lock.java b/src/org/python/modules/_threading/Lock.java
--- a/src/org/python/modules/_threading/Lock.java
+++ b/src/org/python/modules/_threading/Lock.java
@@ -8,10 +8,12 @@
import org.python.core.PyObject;
import org.python.core.PyType;
import org.python.core.ThreadState;
+import org.python.core.Untraversable;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "_threading.Lock")
public class Lock extends PyObject implements ContextManager {
diff --git a/src/org/python/modules/_weakref/AbstractReference.java b/src/org/python/modules/_weakref/AbstractReference.java
--- a/src/org/python/modules/_weakref/AbstractReference.java
+++ b/src/org/python/modules/_weakref/AbstractReference.java
@@ -1,14 +1,18 @@
/* Copyright (c) Jython Developers */
package org.python.modules._weakref;
+import org.python.core.JyAttribute;
import org.python.core.Py;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
+import org.python.modules.gc;
/**
* Base class for weakref types.
*/
-public abstract class AbstractReference extends PyObject {
+public abstract class AbstractReference extends PyObject implements Traverseproc {
PyObject callback;
@@ -32,7 +36,7 @@
}
protected PyObject py() {
- PyObject o = (PyObject)gref.get();
+ PyObject o = get();
if (o == null) {
throw Py.ReferenceError("weakly-referenced object no longer exists");
}
@@ -53,8 +57,8 @@
if (other.getClass() != getClass()) {
return null;
}
- PyObject pythis = (PyObject)gref.get();
- PyObject pyother = (PyObject)((AbstractReference)other).gref.get();
+ PyObject pythis = get();
+ PyObject pyother = ((AbstractReference) other).get();
if (pythis == null || pyother == null) {
return this == other ? Py.True : Py.False;
}
@@ -65,11 +69,57 @@
if (other.getClass() != getClass()) {
return Py.True;
}
- PyObject pythis = (PyObject)gref.get();
- PyObject pyother = (PyObject)((AbstractReference)other).gref.get();
+ PyObject pythis = get();
+ PyObject pyother = ((AbstractReference) other).get();
if (pythis == null || pyother == null) {
return this == other ? Py.False : Py.True;
}
return pythis._eq(pyother).__not__();
}
+
+ protected PyObject get() {
+ PyObject result = gref.get();
+ if (result == null && (gc.getJythonGCFlags() & gc.PRESERVE_WEAKREFS_ON_RESURRECTION) != 0) {
+ if (gref.cleared) {
+ return null;
+ }
+ if ((gc.getJythonGCFlags() & gc.VERBOSE_WEAKREF) != 0) {
+ Py.writeDebug("gc", "pending in get of abstract ref "+this+": "+
+ Thread.currentThread().getId());
+ }
+ JyAttribute.setAttr(this, JyAttribute.WEAKREF_PENDING_GET_ATTR, Thread.currentThread());
+ while (!gref.cleared && result == null) {
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException ie) {}
+ result = gref.get();
+ }
+ JyAttribute.delAttr(this, JyAttribute.WEAKREF_PENDING_GET_ATTR);
+ if ((gc.getJythonGCFlags() & gc.VERBOSE_WEAKREF) != 0) {
+ Py.writeDebug("gc", "pending of "+this+" resolved: "+
+ Thread.currentThread().getId());
+ if (gref.cleared) {
+ Py.writeDebug("gc", "reference was cleared.");
+ } else if (result != null){
+ Py.writeDebug("gc", "reference was restored.");
+ } else {
+ Py.writeDebug("gc", "something went very wrong.");
+ }
+ }
+ return result;
+ } else {
+ return result;
+ }
+ }
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return callback != null ? visit.visit(callback, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && callback == ob;
+ }
}
diff --git a/src/org/python/modules/_weakref/GlobalRef.java b/src/org/python/modules/_weakref/GlobalRef.java
--- a/src/org/python/modules/_weakref/GlobalRef.java
+++ b/src/org/python/modules/_weakref/GlobalRef.java
@@ -1,7 +1,6 @@
/* Copyright (c) Jython Developers */
package org.python.modules._weakref;
-import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -10,13 +9,15 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.python.core.JyAttribute;
import org.python.core.Py;
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.core.PySystemState;
import org.python.util.Generic;
+import org.python.modules.gc;
-public class GlobalRef extends WeakReference {
+public class GlobalRef extends WeakReference<PyObject> {
/**
* This reference's hashCode: the System.identityHashCode of the referent. Only used
@@ -33,14 +34,25 @@
/** Whether pythonHashCode was already determined. */
private boolean havePythonHashCode;
- private List references = new ArrayList();
+ /**
+ * This boolean is set true when the callback is processed. If the reference is
+ * cleared it might potentially be restored until this boolean is set true.
+ * If weak reference restoring is activated (c.f.
+ * gc.PRESERVE_WEAKREFS_ON_RESURRECTION), AbstractReference.get would block
+ * until a consistent state is reached (i.e. referent is non-null or
+ * cleared == true).
+ */
+ protected boolean cleared = false;
- private static ReferenceQueue referenceQueue = new ReferenceQueue();
+ private List<WeakReference<AbstractReference>> references = new ArrayList<>();
+
+ private static ReferenceQueue<PyObject> referenceQueue = new ReferenceQueue<>();
private static Thread reaperThread;
private static ReentrantReadWriteLock reaperLock = new ReentrantReadWriteLock();
private static ConcurrentMap<GlobalRef, GlobalRef> objects = Generic.concurrentMap();
+ private static List<GlobalRef> delayedCallbacks;
public GlobalRef(PyObject object) {
super(object, referenceQueue);
@@ -48,17 +60,17 @@
}
public synchronized void add(AbstractReference ref) {
- Reference r = new WeakReference(ref);
+ WeakReference<AbstractReference> r = new WeakReference<>(ref);
references.add(r);
}
private final AbstractReference getReferenceAt(int idx) {
- WeakReference wref = (WeakReference)references.get(idx);
- return (AbstractReference)wref.get();
+ WeakReference<AbstractReference> wref = references.get(idx);
+ return wref.get();
}
/**
- * Search for a reusable refrence. To be reused, it must be of the
+ * Search for a reusable reference. To be reused, it must be of the
* same class and it must not have a callback.
*/
synchronized AbstractReference find(Class cls) {
@@ -77,16 +89,57 @@
* Call each of the registered references.
*/
synchronized void call() {
- for (int i = references.size() - 1; i >= 0; i--) {
- AbstractReference r = getReferenceAt(i);
- if (r == null) {
- references.remove(i);
- } else {
- r.call();
+ if (!cleared) {
+ cleared = true;
+ for (int i = references.size() - 1; i >= 0; i--) {
+ AbstractReference r = getReferenceAt(i);
+ if (r == null) {
+ references.remove(i);
+ } else {
+ Thread pendingGet = (Thread) JyAttribute.getAttr(
+ r, JyAttribute.WEAKREF_PENDING_GET_ATTR);
+ if (pendingGet != null) {
+ pendingGet.interrupt();
+ }
+ r.call();
+ }
}
}
}
+ /**
+ * Call all callbacks that were enqueued via delayedCallback method.
+ */
+ public static void processDelayedCallbacks() {
+ if (delayedCallbacks != null) {
+ synchronized (delayedCallbacks) {
+ for (GlobalRef gref: delayedCallbacks) {
+ gref.call();
+ }
+ delayedCallbacks.clear();
+ }
+ }
+ }
+
+ /**
+ * Stores the callback for later processing. This is needed if
+ * weak reference restoration (c.f. gc.PRESERVE_WEAKREFS_ON_RESURRECTION)
+ * is activated. In this case the callback is delayed until it was
+ * determined whether a resurrection restored the reference.
+ */
+ private static void delayedCallback(GlobalRef cl) {
+ if (delayedCallbacks == null) {
+ delayedCallbacks = new ArrayList<>();
+ }
+ synchronized (delayedCallbacks) {
+ delayedCallbacks.add(cl);
+ }
+ }
+
+ public static boolean hasDelayedCallbacks() {
+ return delayedCallbacks != null && !delayedCallbacks.isEmpty();
+ }
+
synchronized public int count() {
for (int i = references.size() - 1; i >= 0; i--) {
AbstractReference r = getReferenceAt(i);
@@ -98,7 +151,7 @@
}
synchronized public PyList refs() {
- List list = new ArrayList();
+ List<AbstractReference> list = new ArrayList<>();
for (int i = references.size() - 1; i >= 0; i--) {
AbstractReference r = getReferenceAt(i);
if (r == null) {
@@ -123,10 +176,57 @@
GlobalRef ref = objects.putIfAbsent(newRef, newRef);
if (ref == null) {
ref = newRef;
+ JyAttribute.setAttr(object, JyAttribute.WEAK_REF_ATTR, ref);
+ } else {
+ // We clear the not-needed Global ref so that it won't
+ // pop up in ref-reaper thread's activity.
+ newRef.clear();
+ newRef.cleared = true;
}
return ref;
}
+ /**
+ * Restores this weak reference to its former referent.
+ * This actually means that a fresh GlobalRef is created
+ * and inserted into all adjacent AbstractRefs. The
+ * current GlobalRef is disbanded.
+ * If the given PyObject is not the former referent of
+ * this weak reference, an IllegalArgumentException is
+ * thrown.
+ */
+ public void restore(PyObject formerReferent) {
+ if (JyAttribute.getAttr(formerReferent, JyAttribute.WEAK_REF_ATTR) != this) {
+ throw new IllegalArgumentException(
+ "Argument is not former referent of this GlobalRef.");
+ }
+ if (delayedCallbacks != null) {
+ synchronized (delayedCallbacks) {
+ delayedCallbacks.remove(this);
+ }
+ }
+ clear();
+ createReaperThreadIfAbsent();
+ GlobalRef restore = new GlobalRef(formerReferent);
+ restore.references = references;
+ objects.remove(this);
+ objects.put(restore, restore);
+ AbstractReference aref;
+ for (int i = references.size() - 1; i >= 0; i--) {
+ aref = getReferenceAt(i);
+ if (aref == null) {
+ references.remove(i);
+ } else {
+ aref.gref = restore;
+ Thread pendingGet = (Thread) JyAttribute.getAttr(
+ aref, JyAttribute.WEAKREF_PENDING_GET_ATTR);
+ if (pendingGet != null) {
+ pendingGet.interrupt();
+ }
+ }
+ }
+ }
+
private static void createReaperThreadIfAbsent() {
reaperLock.readLock().lock();
try {
@@ -233,12 +333,17 @@
private Thread thread;
public void collect() throws InterruptedException {
- GlobalRef gr = (GlobalRef)referenceQueue.remove();
- gr.call();
+ GlobalRef gr = (GlobalRef) referenceQueue.remove();
+ if ((gc.getJythonGCFlags() & gc.PRESERVE_WEAKREFS_ON_RESURRECTION) == 0) {
+ gr.call();
+ } else {
+ delayedCallback(gr);
+ }
objects.remove(gr);
gr = null;
}
+ @Override
public void run() {
// Store the actual reaper thread so that when PySystemState.cleanup()
// is called this thread can be interrupted and die.
@@ -264,7 +369,6 @@
this.thread.interrupt();
this.thread = null;
}
-
return null;
}
}
diff --git a/src/org/python/modules/_weakref/ReferenceType.java b/src/org/python/modules/_weakref/ReferenceType.java
--- a/src/org/python/modules/_weakref/ReferenceType.java
+++ b/src/org/python/modules/_weakref/ReferenceType.java
@@ -3,10 +3,8 @@
import org.python.core.ArgParser;
import org.python.core.Py;
-import org.python.core.PyList;
import org.python.core.PyNewWrapper;
import org.python.core.PyObject;
-import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -44,7 +42,6 @@
if (callback == null) {
ReferenceType ret = (ReferenceType)gref.find(ReferenceType.class);
if (ret != null) {
- // We can re-use an existing reference.
return ret;
}
}
@@ -92,11 +89,11 @@
@ExposedMethod
final PyObject weakref___call__(PyObject args[], String keywords[]) {
new ArgParser("__call__", args, keywords, Py.NoKeywords, 0);
- return Py.java2py(gref.get());
+ return Py.java2py(get());
}
public String toString() {
- PyObject obj = (PyObject)gref.get();
+ PyObject obj = get();
if (obj == null) {
return String.format("<weakref at %s; dead>", Py.idstr(this));
}
diff --git a/src/org/python/modules/_weakref/ReferenceTypeDerived.java b/src/org/python/modules/_weakref/ReferenceTypeDerived.java
--- a/src/org/python/modules/_weakref/ReferenceTypeDerived.java
+++ b/src/org/python/modules/_weakref/ReferenceTypeDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ReferenceTypeDerived extends ReferenceType implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ReferenceTypeDerived extends ReferenceType implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/_weakref/WeakrefModule.java b/src/org/python/modules/_weakref/WeakrefModule.java
--- a/src/org/python/modules/_weakref/WeakrefModule.java
+++ b/src/org/python/modules/_weakref/WeakrefModule.java
@@ -3,12 +3,9 @@
import org.python.core.ClassDictInit;
import org.python.core.Py;
-import org.python.core.PyIgnoreMethodTag;
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.core.PyString;
-import org.python.core.PyStringMap;
-import org.python.core.PyType;
/**
* The _weakref module.
@@ -63,5 +60,3 @@
return GlobalRef.getRefs(object);
}
}
-
-
diff --git a/src/org/python/modules/bz2/PyBZ2Compressor.java b/src/org/python/modules/bz2/PyBZ2Compressor.java
--- a/src/org/python/modules/bz2/PyBZ2Compressor.java
+++ b/src/org/python/modules/bz2/PyBZ2Compressor.java
@@ -10,11 +10,13 @@
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyType;
+import org.python.core.Untraversable;
import org.python.core.util.StringUtil;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "bz2.BZ2Compressor")
public class PyBZ2Compressor extends PyObject {
diff --git a/src/org/python/modules/bz2/PyBZ2CompressorDerived.java b/src/org/python/modules/bz2/PyBZ2CompressorDerived.java
--- a/src/org/python/modules/bz2/PyBZ2CompressorDerived.java
+++ b/src/org/python/modules/bz2/PyBZ2CompressorDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyBZ2CompressorDerived extends PyBZ2Compressor implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyBZ2CompressorDerived extends PyBZ2Compressor implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/bz2/PyBZ2Decompressor.java b/src/org/python/modules/bz2/PyBZ2Decompressor.java
--- a/src/org/python/modules/bz2/PyBZ2Decompressor.java
+++ b/src/org/python/modules/bz2/PyBZ2Decompressor.java
@@ -16,9 +16,11 @@
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
@ExposedType(name = "bz2.BZ2Decompressor")
-public class PyBZ2Decompressor extends PyObject {
+public class PyBZ2Decompressor extends PyObject implements Traverseproc {
@ExposedGet
public PyString unused_data = Py.EmptyString;
@@ -110,4 +112,15 @@
return returnData;
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return unused_data != null ? visit.visit(unused_data, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && unused_data == ob;
+ }
}
diff --git a/src/org/python/modules/bz2/PyBZ2DecompressorDerived.java b/src/org/python/modules/bz2/PyBZ2DecompressorDerived.java
--- a/src/org/python/modules/bz2/PyBZ2DecompressorDerived.java
+++ b/src/org/python/modules/bz2/PyBZ2DecompressorDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyBZ2DecompressorDerived extends PyBZ2Decompressor implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyBZ2DecompressorDerived extends PyBZ2Decompressor implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/bz2/PyBZ2File.java b/src/org/python/modules/bz2/PyBZ2File.java
--- a/src/org/python/modules/bz2/PyBZ2File.java
+++ b/src/org/python/modules/bz2/PyBZ2File.java
@@ -24,6 +24,7 @@
import org.python.core.PySequence;
import org.python.core.PyString;
import org.python.core.PyType;
+import org.python.core.Untraversable;
import org.python.core.finalization.FinalizablePyObject;
import org.python.core.finalization.FinalizableBuiltin;
import org.python.core.finalization.FinalizeTrigger;
@@ -39,6 +40,7 @@
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "bz2.BZ2File")
public class PyBZ2File extends PyObject implements FinalizablePyObject, FinalizableBuiltin {
@@ -61,18 +63,15 @@
private boolean needReadBufferInit = false;
private boolean inReadMode = false;
private boolean inWriteMode = false;
-
- public FinalizeTrigger finalizeTrigger;
-
public PyBZ2File() {
super(TYPE);
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
public PyBZ2File(PyType subType) {
super(subType);
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
@Override
diff --git a/src/org/python/modules/bz2/PyBZ2FileDerived.java b/src/org/python/modules/bz2/PyBZ2FileDerived.java
--- a/src/org/python/modules/bz2/PyBZ2FileDerived.java
+++ b/src/org/python/modules/bz2/PyBZ2FileDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyBZ2FileDerived extends PyBZ2File implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyBZ2FileDerived extends PyBZ2File implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/gc.java b/src/org/python/modules/gc.java
--- a/src/org/python/modules/gc.java
+++ b/src/org/python/modules/gc.java
@@ -1,56 +1,2432 @@
-package org.python.modules;
-
-import org.python.core.Py;
-import org.python.core.PyObject;
-
-public class gc {
-
- public static final String __doc__ =
- "This module provides access to the garbage collector.\n" +
- "\n" +
- "enable() -- Enable automatic garbage collection (does nothing).\n" +
- "isenabled() -- Returns True because Java garbage collection cannot be disabled.\n" +
- "collect() -- Trigger a Java garbage collection (potentially expensive).\n" +
- "get_debug() -- Get debugging flags (returns 0).\n" +
- "\n" +
- "Other functions raise NotImplementedError because they do not apply to Java.\n";
-
- public static final String __name__ = "gc";
-
- public static void enable() {}
- public static void disable() {
- throw Py.NotImplementedError("can't disable Java GC");
- }
- public static boolean isenabled() { return true; }
-
- public static void collect() {
- System.gc();
- }
-
- public static PyObject get_count() {
- throw Py.NotImplementedError("not applicable to Java GC");
- }
-
- public static void set_debug(int flags) {
- throw Py.NotImplementedError("not applicable to Java GC");
- }
- public static int get_debug() { return 0; }
-
- public static void set_threshold(PyObject[] args, String[] kwargs) {
- throw Py.NotImplementedError("not applicable to Java GC");
- }
- public static PyObject get_threshold() {
- throw Py.NotImplementedError("not applicable to Java GC");
- }
-
- public static PyObject get_objects() {
- throw Py.NotImplementedError("not applicable to Java GC");
- }
- public static PyObject get_referrers(PyObject[] args, String[] kwargs) {
- throw Py.NotImplementedError("not applicable to Java GC");
- }
- public static PyObject get_referents(PyObject[] args, String[] kwargs) {
- throw Py.NotImplementedError("not applicable to Java GC");
- }
-
-}
+package org.python.modules;
+
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.IdentityHashMap;
+import java.util.HashSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import org.python.core.JyAttribute;
+import org.python.core.Py;
+import org.python.core.PyList;
+import org.python.core.PyObject;
+import org.python.core.PyInstance;
+import org.python.core.Traverseproc;
+import org.python.core.TraverseprocDerived;
+import org.python.core.Visitproc;
+import org.python.core.Untraversable;
+import org.python.core.finalization.FinalizeTrigger;
+import org.python.modules._weakref.GlobalRef;
+
+public class gc {
+ /**
+ * A constant that can occur as result of {@code gc.collect} and
+ * indicates an unknown number of collected cyclic trash.
+ * It is intentionally not valued -1 as that value is
+ * reserved to indicate an error.
+ */
+ public static final int UNKNOWN_COUNT = -2;
+
+ /* Jython-specific gc-flags: */
+ /**
+ * Tells every newly created PyObject to register for
+ * gc-monitoring. This allows {@code gc.collect} to report the
+ * number of collected objects.
+ */
+ public static final short MONITOR_GLOBAL = (1<<0);
+
+ /**
+ * CPython prior to 3.4 does not finalize cyclic garbage
+ * PyObjects, while Jython does this by default. This flag
+ * tells Jython's gc to mimic CPython <3.4 behavior (i.e.
+ * add such objects to {@code gc.garbage} list instead).
+ */
+ public static final short DONT_FINALIZE_CYCLIC_GARBAGE = (1<<1);
+
+ /**
+ * If a PyObject is resurrected during its finalization
+ * process and was weakly referenced, Jython breaks the
+ * weak references to the resurrected PyObject by default.
+ * In CPython these persist, if the object was indirectly
+ * resurrected due to resurrection of its owner.
+ * This flag tells Jython's gc to preserve weak references
+ * to such resurrected PyObjects.
+ * It only works if all involved objects implement the
+ * traverseproc mechanism properly (see
+ * {@link org.python.core.Traverseproc}).
+ * Note that this feature comes with some cost as it can
+ * delay garbage collection of some weak referenced objects
+ * for several gc cycles if activated. So we recommend to
+ * use it only for debugging.
+ */
+ public static final short PRESERVE_WEAKREFS_ON_RESURRECTION = (1<<2);
+
+ /**
+ * If in CPython an object is resurrected via its finalizer
+ * and contained strong references to other objects, these
+ * are also resurrected and not finalized in CPython (as
+ * their reference count never drops to zero). In contrast
+ * to that, Jython calls finalizers for all objects that
+ * were unreachable when gc started (regardless of resurrections
+ * and in unpredictable order). This flag emulates CPython
+ * behavior in Jython. Note that this emulation comes with a
+ * significant cost as it can delay collection of many objects
+ * for several gc-cycles. Its main intention is for debugging
+ * resurrection-sensitive code.
+ */
+ public static final short DONT_FINALIZE_RESURRECTED_OBJECTS = (1<<3);
+
+ /**
+ * Reflection-based traversion is currently an experimental feature and
+ * is deactivated by default for now. This means that
+ * {@code DONT_TRAVERSE_BY_REFLECTION} is set by default.
+ * Once it is stable, reflection-based traversion will be active by default.
+ */
+ public static final short DONT_TRAVERSE_BY_REFLECTION = (1<<4);
+
+ /**
+ * <p>
+ * If this flag is not set, gc warns whenever an object would be subject to
+ * reflection-based traversion.
+ * Note that if this flag is not set, the warning will occur even if
+ * reflection-based traversion is not active. The purpose of this behavior is
+ * to identify objects that don't properly support the traverseproc-mechanism,
+ * i.e. instances of PyObject-subclasses that neither implement
+ * {@link org.python.core.Traverseproc},
+ * nor are annotated with the {@link org.python.core.Untraversable}-annotation.
+ * </p>
+ * <p>
+ * A SUPPRESS-flag was chosen rather than a WARN-flag, so that warning is the
+ * default behavior - the user must actively set this flag in order to not to
+ * be warned.
+ * This is because in an ideal implementation reflection-based traversion never
+ * occurs; it is only an inefficient fallback.
+ * </p>
+ */
+ public static final short SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING = (1<<5);
+
+ /**
+ * In Jython one usually uses {@code Py.writeDebug} for debugging output.
+ * However that method is only verbose if an appropriate verbose-level
+ * was set. In CPython it is enough to set gc-{@code DEBUG} flags to get
+ * gc-messages, no matter what overall verbose level is selected.
+ * This flag tells Jython to use {@code Py.writeDebug} for debugging output.
+ * If it is not set (default-case), gc-debugging output (if gc-{@code VERBOSE}
+ * or -{@code DEBUG} flags are set) is directly written to {@code System.err}.
+ */
+ public static final short USE_PY_WRITE_DEBUG = (1<<6);
+
+ public static final short VERBOSE_COLLECT = (1<<7);
+ public static final short VERBOSE_WEAKREF = (1<<8);
+ public static final short VERBOSE_DELAYED = (1<<9);
+ public static final short VERBOSE_FINALIZE = (1<<10);
+ public static final short VERBOSE =
+ VERBOSE_COLLECT | VERBOSE_WEAKREF | VERBOSE_DELAYED | VERBOSE_FINALIZE;
+
+ /* set for debugging information */
+ /**
+ * print collection statistics
+ * (in Jython scoped on monitored objects)
+ */
+ public static final int DEBUG_STATS = (1<<0);
+
+ /**
+ * print collectable objects
+ * (in Jython scoped on monitored objects)
+ */
+ public static final int DEBUG_COLLECTABLE = (1<<1);
+
+ /**
+ * print uncollectable objects
+ * (in Jython scoped on monitored objects)
+ */
+ public static final int DEBUG_UNCOLLECTABLE = (1<<2);
+
+ /**
+ * print instances
+ * (in Jython scoped on monitored objects)
+ */
+ public static final int DEBUG_INSTANCES = (1<<3);
+
+ /**
+ * print other objects
+ * (in Jython scoped on monitored objects)
+ */
+ public static final int DEBUG_OBJECTS = (1<<4);
+
+ /**
+ * save all garbage in gc.garbage
+ * (in Jython scoped on monitored objects)
+ */
+ public static final int DEBUG_SAVEALL = (1<<5);
+ public static final int DEBUG_LEAK = DEBUG_COLLECTABLE |
+ DEBUG_UNCOLLECTABLE |
+ DEBUG_INSTANCES |
+ DEBUG_OBJECTS |
+ DEBUG_SAVEALL;
+
+ private static short gcFlags = DONT_TRAVERSE_BY_REFLECTION;
+ private static int debugFlags = 0;
+ private static boolean monitorNonTraversable = false;
+ private static boolean waitingForFinalizers = false;
+ private static AtomicBoolean gcRunning = new AtomicBoolean(false);
+ private static HashSet<WeakReferenceGC> monitoredObjects;
+ private static ReferenceQueue<Object> gcTrash;
+ private static int finalizeWaitCount = 0;
+ private static int initWaitTime = 10, defaultWaitFactor = 2;
+ private static long lastRemoveTimeStamp = -1, maxWaitTime = initWaitTime;
+ private static int gcMonitoredRunCount = 0;
+ public static long gcRecallTime = 4000;
+ public static PyList garbage = new PyList();
+
+ //Finalization preprocess/postprocess-related declarations:
+ private static List<Runnable> preFinalizationProcess, postFinalizationProcess;
+ private static List<Runnable> preFinalizationProcessRemove, postFinalizationProcessRemove;
+ private static Thread postFinalizationProcessor;
+ private static long postFinalizationTimeOut = 100;
+ private static long postFinalizationTimestamp = System.currentTimeMillis()-2*postFinalizationTimeOut;
+ private static int openFinalizeCount = 0;
+ private static boolean postFinalizationPending = false;
+ private static boolean lockPostFinalization = false;
+
+ //Resurrection-safe finalizer- and weakref-related declarations:
+ private static IdentityHashMap<PyObject, PyObject> delayedFinalizables, resurrectionCritics;
+ private static int abortedCyclicFinalizers = 0;
+ //Some modes to control aspects of delayed finalization:
+ private static final byte DO_NOTHING_SPECIAL = 0;
+ private static final byte MARK_REACHABLE_CRITICS = 1;
+ private static final byte NOTIFY_FOR_RERUN = 2;
+ private static byte delayedFinalizationMode = DO_NOTHING_SPECIAL;
+ private static boolean notifyRerun = false;
+
+ public static final String __doc__ =
+ "This module provides access to the garbage collector.\n" +
+ "\n" +
+ "enable() -- Enable automatic garbage collection (does nothing).\n" +
+ "isenabled() -- Returns True because Java garbage collection cannot be disabled.\n" +
+ "collect() -- Trigger a Java garbage collection (potentially expensive).\n" +
+ "get_debug() -- Get debugging flags (returns 0).\n" +
+ "\n" +
+ "Other functions raise NotImplementedError because they do not apply to Java.\n";
+
+ public static final String __name__ = "gc";
+
+
+ public static class CycleMarkAttr {
+ private boolean cyclic = false;
+ private boolean uncollectable = false;
+ public boolean monitored = false;
+
+ CycleMarkAttr() {
+ }
+
+ CycleMarkAttr(boolean cyclic, boolean uncollectable) {
+ this.cyclic = cyclic;
+ this.uncollectable = uncollectable;
+ }
+
+ public boolean isCyclic() {
+ return cyclic || uncollectable;
+ }
+
+ public boolean isUncollectable() {
+ return uncollectable;
+ }
+
+ public void setFlags(boolean cyclic, boolean uncollectable) {
+ this.cyclic = cyclic;
+ this.uncollectable = uncollectable;
+ }
+ }
+
+ private static class WeakReferenceGC extends WeakReference<PyObject> {
+ int hashCode;
+ public String str = null, inst_str = null;
+ public String cls;
+ boolean isInstance;
+ boolean hasFinalizer = false;
+ CycleMarkAttr cycleMark;
+
+ WeakReferenceGC(PyObject referent) {
+ super(referent);
+ isInstance = referent instanceof PyInstance;
+ cycleMark = (CycleMarkAttr)
+ JyAttribute.getAttr(referent, JyAttribute.GC_CYCLE_MARK_ATTR);
+ hashCode = System.identityHashCode(referent);
+ cls = referent.getClass().getName();
+ updateHasFinalizer();
+ }
+
+ WeakReferenceGC(PyObject referent, ReferenceQueue<Object> q) {
+ super(referent, q);
+ isInstance = referent instanceof PyInstance;
+ cycleMark = (CycleMarkAttr)
+ JyAttribute.getAttr(referent, JyAttribute.GC_CYCLE_MARK_ATTR);
+ hashCode = System.identityHashCode(referent);
+ cls = referent.getClass().getName();
+ updateHasFinalizer();
+ }
+
+ public void updateHasFinalizer() {
+ PyObject gt = get();
+ Object fn = JyAttribute.getAttr(gt, JyAttribute.FINALIZE_TRIGGER_ATTR);
+ hasFinalizer = fn != null && ((FinalizeTrigger) fn).isActive();
+ }
+
+ public void initStr(PyObject referent) {
+ PyObject ref = referent;
+ if (referent == null) {
+ ref = get();
+ }
+ try {
+ if (ref instanceof PyInstance) {
+ String name = ((PyInstance) ref).fastGetClass().__name__;
+ if (name == null) {
+ name = "?";
+ }
+ inst_str = String.format("<%.100s instance at %s>",
+ name, Py.idstr(ref));
+ }
+ str = String.format("<%.100s %s>",
+ ref.getType().getName(), Py.idstr(ref));
+ } catch (Exception e) {
+ str = "<"+ref.getClass().getSimpleName()+" "
+ +System.identityHashCode(ref)+">";
+ }
+ }
+
+ public String toString() {
+ return str;
+ }
+
+ public int hashCode() {
+ return hashCode;
+ }
+
+ public boolean equals(Object ob) {
+ if (ob instanceof WeakReferenceGC) {
+ return ((WeakReferenceGC) ob).get().equals(get())
+ && ((WeakReferenceGC) ob).hashCode() == hashCode();
+ } else if (ob instanceof WeakrefGCCompareDummy) {
+ return ((WeakrefGCCompareDummy) ob).compare != null
+ && ((WeakrefGCCompareDummy) ob).compare.equals(get());
+ } else {
+ return false;
+ }
+ }
+ }
+
+ private static class WeakrefGCCompareDummy {
+ public static WeakrefGCCompareDummy defaultInstance =
+ new WeakrefGCCompareDummy();
+ PyObject compare;
+ int hashCode;
+
+ public void setCompare(PyObject compare) {
+ this.compare = compare;
+ hashCode = System.identityHashCode(compare);
+ }
+
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public boolean equals(Object ob) {
+ if (ob instanceof Reference) {
+ return compare.equals(((Reference) ob).get());
+ } else if (ob instanceof WeakrefGCCompareDummy) {
+ return compare.equals(((WeakrefGCCompareDummy) ob).compare);
+ } else {
+ return compare.equals(ob);
+ }
+ }
+ }
+
+ private static class GCSentinel {
+ Thread waiting;
+
+ public GCSentinel(Thread notifyOnFinalize) {
+ waiting = notifyOnFinalize;
+ }
+
+ protected void finalize() throws Throwable {
+ //TODO: Find out why this would cause test to fail:
+ //notifyPreFinalization();
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "Sentinel finalizer called...");
+ }
+ if (lastRemoveTimeStamp != -1) {
+ long diff = maxWaitTime*defaultWaitFactor-System.currentTimeMillis()+lastRemoveTimeStamp;
+ while (diff > 0) {
+ try {
+ Thread.sleep(diff);
+ } catch (InterruptedException ie) {}
+ diff = maxWaitTime*defaultWaitFactor-System.currentTimeMillis()+lastRemoveTimeStamp;
+ }
+ }
+ if (waiting != null) {
+ waiting.interrupt();
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "Sentinel finalizer done");
+ }
+ //notifyPostFinalization();
+ }
+ }
+
+ private static void writeDebug(String type, String msg) {
+ if ((gcFlags & USE_PY_WRITE_DEBUG) != 0) {
+ Py.writeDebug(type, msg);
+ } else {
+ System.err.println(type + ": " + msg);
+ }
+ }
+
+ //----------delayed finalization section-----------------------------------
+
+ private static class DelayedFinalizationProcess implements Runnable {
+ static DelayedFinalizationProcess defaultInstance =
+ new DelayedFinalizationProcess();
+
+ private void performFinalization(PyObject del) {
+ if ((gcFlags & VERBOSE_DELAYED) != 0) {
+ writeDebug("gc", "delayed finalize of "+del);
+ }
+ FinalizeTrigger ft = (FinalizeTrigger)
+ JyAttribute.getAttr(del, JyAttribute.FINALIZE_TRIGGER_ATTR);
+ if (ft != null) {
+ ft.performFinalization();
+ } else if ((gcFlags & VERBOSE_DELAYED) != 0) {
+ writeDebug("gc", "no FinalizeTrigger");
+ }
+ }
+
+ private void restoreFinalizer(PyObject obj, boolean cyclic) {
+ FinalizeTrigger ft =
+ (FinalizeTrigger) JyAttribute.getAttr(obj, JyAttribute.FINALIZE_TRIGGER_ATTR);
+ FinalizeTrigger.ensureFinalizer(obj);
+ boolean notify = false;
+ if (ft != null) {
+ ((FinalizeTrigger)
+ JyAttribute.getAttr(obj, JyAttribute.FINALIZE_TRIGGER_ATTR)).flags
+ = ft.flags;
+ notify = (ft.flags & FinalizeTrigger.NOTIFY_GC_FLAG) != 0;
+ }
+ if ((gcFlags & VERBOSE_DELAYED) != 0 || (gcFlags & VERBOSE_FINALIZE) != 0) {
+ writeDebug("gc", "restore finalizer of "+obj+"; cyclic? "+cyclic);
+ }
+ CycleMarkAttr cm = (CycleMarkAttr)
+ JyAttribute.getAttr(obj, JyAttribute.GC_CYCLE_MARK_ATTR);
+ if (cm != null && cm.monitored) {
+ monitorObject(obj, true);
+ }
+ if (notify) {
+ if ((gcFlags & VERBOSE_DELAYED) != 0 || (gcFlags & VERBOSE_FINALIZE) != 0) {
+ writeDebug("gc", "notify finalizer abort.");
+ }
+ notifyAbortFinalize(obj, cyclic);
+ }
+ }
+
+ public void run() {
+ if ((gcFlags & VERBOSE_DELAYED) != 0) {
+ writeDebug("gc", "run delayed finalization. Index: "+
+ gcMonitoredRunCount);
+ }
+ Set<PyObject> critics = resurrectionCritics.keySet();
+ Set<PyObject> cyclicCritics = removeNonCyclic(critics);
+ cyclicCritics.retainAll(critics);
+ critics.removeAll(cyclicCritics);
+ Set<PyObject> criticReachablePool = findReachables(critics);
+ //to avoid concurrent modification:
+ ArrayList<PyObject> criticReachables = new ArrayList<>();
+ FinalizeTrigger fn;
+ if (delayedFinalizationMode == MARK_REACHABLE_CRITICS) {
+ for (PyObject obj: criticReachablePool) {
+ fn = (FinalizeTrigger) JyAttribute.getAttr(obj,
+ JyAttribute.FINALIZE_TRIGGER_ATTR);
+ if (fn != null && fn.isActive() && fn.isFinalized()) {
+ criticReachables.add(obj);
+ JyAttribute.setAttr(obj,
+ JyAttribute.GC_DELAYED_FINALIZE_CRITIC_MARK_ATTR,
+ Integer.valueOf(gcMonitoredRunCount));
+ }
+ }
+ } else {
+ for (PyObject obj: criticReachablePool) {
+ fn = (FinalizeTrigger) JyAttribute.getAttr(obj,
+ JyAttribute.FINALIZE_TRIGGER_ATTR);
+ if (fn != null && fn.isActive() && fn.isFinalized()) {
+ criticReachables.add(obj);
+ }
+ }
+ }
+ critics.removeAll(criticReachables);
+ if ((gcFlags & PRESERVE_WEAKREFS_ON_RESURRECTION) != 0) {
+ if ((gcFlags & VERBOSE_DELAYED) != 0) {
+ writeDebug("gc", "restore potentially resurrected weak references...");
+ }
+ GlobalRef toRestore;
+ for (PyObject rst: criticReachablePool) {
+ toRestore = (GlobalRef)
+ JyAttribute.getAttr(rst, JyAttribute.WEAK_REF_ATTR);
+ if (toRestore != null) {
+ toRestore.restore(rst);
+ }
+ }
+ GlobalRef.processDelayedCallbacks();
+ }
+ criticReachablePool.clear();
+ if ((gcFlags & DONT_FINALIZE_RESURRECTED_OBJECTS) != 0) {
+ //restore all finalizers that might belong to resurrected
+ //objects:
+ if ((gcFlags & VERBOSE_DELAYED) != 0) {
+ writeDebug("gc", "restore "+criticReachables.size()+
+ " potentially resurrected finalizers...");
+ }
+ for (PyObject obj: criticReachables) {
+ CycleMarkAttr cm = (CycleMarkAttr)
+ JyAttribute.getAttr(obj, JyAttribute.GC_CYCLE_MARK_ATTR);
+ if (cm != null && cm.isUncollectable()) {
+ restoreFinalizer(obj, true);
+ } else {
+ gc.markCyclicObjects(obj, true);
+ cm = (CycleMarkAttr)
+ JyAttribute.getAttr(obj, JyAttribute.GC_CYCLE_MARK_ATTR);
+ restoreFinalizer(obj, cm != null && cm.isUncollectable());
+ }
+ }
+ } else {
+ if ((gcFlags & VERBOSE_DELAYED) != 0) {
+ writeDebug("gc", "delayed finalization of "+criticReachables.size()+
+ " potentially resurrected finalizers...");
+ }
+ for (PyObject del: criticReachables) {
+ performFinalization(del);
+ }
+ }
+ cyclicCritics.removeAll(criticReachables);
+ if ((gcFlags & VERBOSE_DELAYED) != 0 && !delayedFinalizables.isEmpty()) {
+ writeDebug("gc", "process "+delayedFinalizables.size()+
+ " delayed finalizers...");
+ }
+ for (PyObject del: delayedFinalizables.keySet()) {
+ performFinalization(del);
+ }
+ if ((gcFlags & VERBOSE_DELAYED) != 0 && !cyclicCritics.isEmpty()) {
+ writeDebug("gc", "process "+cyclicCritics.size()+" cyclic delayed finalizers...");
+ }
+ for (PyObject del: cyclicCritics) {
+ performFinalization(del);
+ }
+ if ((gcFlags & VERBOSE_DELAYED) != 0 && !critics.isEmpty()) {
+ writeDebug("gc", "calling "+critics.size()+
+ " critic finalizers not reachable by other critic finalizers...");
+ }
+ if (delayedFinalizationMode == MARK_REACHABLE_CRITICS &&
+ !critics.isEmpty() && !criticReachables.isEmpty()) {
+ // This means some critic-reachables might be not critic-reachable any more.
+ // In a synchronized gc collection approach System.gc should run again while
+ // something like this is found. (Yes, not exactly a cheap task, but since this
+ // is for debugging, correctness counts.)
+ notifyRerun = true;
+ }
+ if (delayedFinalizationMode == NOTIFY_FOR_RERUN && !notifyRerun) {
+ for (PyObject del: critics) {
+ if (!notifyRerun) {
+ Object m = JyAttribute.getAttr(del,
+ JyAttribute.GC_DELAYED_FINALIZE_CRITIC_MARK_ATTR);
+ if (m != null && ((Integer) m).intValue() == gcMonitoredRunCount) {
+ notifyRerun = true;
+ }
+ }
+ performFinalization(del);
+ }
+ } else {
+ for (PyObject del: critics) {
+ performFinalization(del);
+ }
+ }
+ delayedFinalizables.clear();
+ resurrectionCritics.clear();
+ if ((gcFlags & VERBOSE_DELAYED) != 0) {
+ writeDebug("gc", "delayed finalization run done");
+ }
+ }
+ }
+
+ public static boolean delayedFinalizationEnabled() {
+ return (gcFlags & (PRESERVE_WEAKREFS_ON_RESURRECTION |
+ DONT_FINALIZE_RESURRECTED_OBJECTS)) != 0;
+ }
+
+ private static void updateDelayedFinalizationState() {
+ if (delayedFinalizationEnabled()) {
+ resumeDelayedFinalization();
+ } else if (indexOfPostFinalizationProcess(
+ DelayedFinalizationProcess.defaultInstance) != -1) {
+ suspendDelayedFinalization();
+ }
+ if ((gcFlags & PRESERVE_WEAKREFS_ON_RESURRECTION) == 0) {
+ if (GlobalRef.hasDelayedCallbacks()) {
+ Thread dlcProcess = new Thread() {
+ public void run() {
+ GlobalRef.processDelayedCallbacks();
+ }
+ };
+ dlcProcess.start();
+ }
+ }
+ }
+
+ private static void resumeDelayedFinalization() {
+ if (delayedFinalizables == null) {
+ delayedFinalizables = new IdentityHashMap<>();
+ }
+ if (resurrectionCritics == null) {
+ resurrectionCritics = new IdentityHashMap<>();
+ }
+ //add post-finalization process (and cancel pending suspension process if any)
+ try {
+ synchronized(postFinalizationProcessRemove) {
+ postFinalizationProcessRemove.remove(
+ DelayedFinalizationProcess.defaultInstance);
+ if (postFinalizationProcessRemove.isEmpty()) {
+ postFinalizationProcessRemove = null;
+ }
+ }
+ } catch (NullPointerException npe) {}
+ if (indexOfPostFinalizationProcess(
+ DelayedFinalizationProcess.defaultInstance) == -1) {
+ registerPostFinalizationProcess(
+ DelayedFinalizationProcess.defaultInstance);
+ }
+ }
+
+ private static void suspendDelayedFinalization() {
+ unregisterPostFinalizationProcessAfterNextRun(
+ DelayedFinalizationProcess.defaultInstance);
+ }
+
+ private static boolean isResurrectionCritic(PyObject ob) {
+ return (isTraversable(ob))
+ && FinalizeTrigger.hasActiveTrigger(ob);
+ }
+
+ public static void registerForDelayedFinalization(PyObject ob) {
+ if (isResurrectionCritic(ob)) {
+ resurrectionCritics.put(ob, ob);
+ } else {
+ delayedFinalizables.put(ob, ob);
+ }
+ }
+ //----------end of delayed finalization section----------------------------
+
+
+
+
+ //----------Finalization preprocess/postprocess section--------------------
+
+ protected static class PostFinalizationProcessor implements Runnable {
+ protected static PostFinalizationProcessor defaultInstance =
+ new PostFinalizationProcessor();
+
+ public void run() {
+ // We wait until last postFinalizationTimestamp is at least timeOut ago.
+ // This should only be measured when openFinalizeCount is zero.
+ long current = System.currentTimeMillis();
+ while (true) {
+ if (!lockPostFinalization && openFinalizeCount == 0
+ && current - postFinalizationTimestamp
+ > postFinalizationTimeOut) {
+ break;
+ }
+ try {
+ long time = postFinalizationTimeOut - current + postFinalizationTimestamp;
+ if (openFinalizeCount != 0 || lockPostFinalization || time < 0) {
+ time = gcRecallTime;
+ }
+ Thread.sleep(time);
+ } catch (InterruptedException ie) {
+ }
+ current = System.currentTimeMillis();
+ }
+ postFinalizationProcessor = null;
+ postFinalizationProcess();
+ synchronized(PostFinalizationProcessor.class) {
+ postFinalizationPending = false;
+ PostFinalizationProcessor.class.notify();
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * Registers a process that will be called before any finalization during gc-run
+ * takes place ("finalization" refers to Jython-style finalizers ran by
+ * {@link org.python.core.finalization.FinalizeTrigger}s;
+ * to care for other finalizers these must call
+ * {@code gc.notifyPreFinalization()} before anything else is done and
+ * {@code gc.notifyPostFinalization()} afterwards; between these calls the finalizer
+ * must not terminate by throwing an exception). (Note: Using this for extern
+ * finalizers is currently experimental and needs more testing.)
+ * This works independently from monitoring, which is mainly needed to allow
+ * counting of cyclic garbage in {@code gc.collect}.
+ * </p>
+ * <p>
+ * This feature compensates that Java's gc does not provide any guarantees about
+ * finalization order. Java not even guarantees that when a weak reference is
+ * added to a reference queue, its finalizer already ran or not yet ran, if any.
+ * </p>
+ * <p>
+ * The only guarantee is that {@link java.lang.ref.PhantomReference}s are enqueued
+ * after finalization of their referents, but this happens in another gc-cycle then.
+ * </p>
+ * <p>
+ * Actually there are still situations that can cause pre-finalization process to
+ * run again during finalization phase. This can happen if external frameworks use
+ * their own finalizers. This can be cured by letting these finalizers call
+ * {@code gc.notifyPreFinalization()} before anything else is done and
+ * {@code gc.notifyPostFinalization()} right before the finalization method returns.
+ * Between these calls the finalizer must not terminate by throwing an exception.
+ * (Note: Using this for extern finalizers is currently experimental and needs more testing.)
+ * </p>
+ * <p>
+ * We recommend to use this feature in a way such that false-positive runs are
+ * not critically harmful, e.g. use it to enhance performance, but don't let it
+ * cause a crash if preprocess is rerun unexpectedly.
+ * </p>
+ */
+ public static void registerPreFinalizationProcess(Runnable process) {
+ registerPreFinalizationProcess(process, -1);
+ }
+
+ /**
+ * See doc of {@core registerPreFinalizationProcess(Runnable process)}.
+ */
+ public static void registerPreFinalizationProcess(Runnable process, int index) {
+ while (true) {
+ try {
+ synchronized (preFinalizationProcess) {
+ preFinalizationProcess.add(index < 0 ?
+ index+preFinalizationProcess.size()+1 : index, process);
+ }
+ return;
+ } catch (NullPointerException npe) {
+ preFinalizationProcess = new ArrayList<>(1);
+ }
+ }
+ }
+
+ public static int indexOfPreFinalizationProcess(Runnable process) {
+ try {
+ synchronized (preFinalizationProcess) {
+ return preFinalizationProcess.indexOf(process);
+ }
+ } catch (NullPointerException npe) {
+ return -1;
+ }
+ }
+
+ public static boolean unregisterPreFinalizationProcess(Runnable process) {
+ try {
+ synchronized (preFinalizationProcess) {
+ boolean result = preFinalizationProcess.remove(process);
+ if (result && preFinalizationProcess.isEmpty()) {
+ preFinalizationProcess = null;
+ }
+ return result;
+ }
+ } catch (NullPointerException npe) {
+ return false;
+ }
+ }
+
+ /**
+ * Useful if a process wants to remove another one or itself during its execution.
+ * This asynchronous unregister method circumvents the synchronized-state on
+ * pre-finalization process list.
+ */
+ public static void unregisterPreFinalizationProcessAfterNextRun(Runnable process) {
+ while (true) {
+ try {
+ synchronized (preFinalizationProcessRemove) {
+ preFinalizationProcessRemove.add(process);
+ }
+ return;
+ } catch (NullPointerException npe) {
+ preFinalizationProcessRemove = new ArrayList<>(1);
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * Registers a process that will be called after all finalization during gc-run
+ * is done ("finalization" refers to Jython-style finalizers ran by
+ * {@link org.python.core.finalization.FinalizeTrigger}s;
+ * to care for other finalizers these must call
+ * {@code gc.notifyPreFinalization()} before anything else is done and
+ * {@code gc.notifyPostFinalization()} afterwards; between these calls the finalizer
+ * must not terminate by throwing an exception). (Note: Using this for extern
+ * finalizers is currently experimental and needs more testing.)
+ * This works independently from monitoring (which is mainly needed to allow
+ * garbage counting in {@code gc.collect}).
+ * </p>
+ * <p>
+ * This feature compensates that Java's gc does not provide any guarantees about
+ * finalization order. Java not even guarantees that when a weak reference is
+ * added to a reference queue, its finalizer already ran or not yet ran, if any.
+ * </p>
+ * <p>
+ * The only guarantee is that {@link java.lang.ref.PhantomReference}s are
+ * enqueued after finalization of the referents, but this
+ * happens - however - in another gc-cycle then.
+ * </p>
+ * <p>
+ * There are situations that can cause post finalization process to run
+ * already during finalization phase. This can happen if external frameworks use
+ * their own finalizers. This can be cured by letting these finalizers call
+ * {@code gc.notifyPreFinalization()} before anything else is done and
+ * {@code notifyPostFinalization()} right before the finalization method returns.
+ * Between these calls the finalizer must not terminate by throwing an exception.
+ * (Note: Using this for extern finalizers is currently experimental and needs more testing.)
+ * </p>
+ * <p>
+ * If it runs too early, we can at least guarantee that it will run again after
+ * finalization was really done. So we recommend to use this feature in a way
+ * such that false-positive runs are not critically harmful.
+ * </p>
+ */
+ public static void registerPostFinalizationProcess(Runnable process) {
+ registerPostFinalizationProcess(process, -1);
+ }
+
+ /**
+ * See doc of {@code registerPostFinalizationProcess(Runnable process)}.
+ */
+ public static void registerPostFinalizationProcess(Runnable process, int index) {
+ while (true) {
+ try {
+ synchronized (postFinalizationProcess) {
+ postFinalizationProcess.add(index < 0 ?
+ index+postFinalizationProcess.size()+1 : index, process);
+ }
+ return;
+ } catch (NullPointerException npe) {
+ postFinalizationProcess = new ArrayList<>(1);
+ }
+ }
+ }
+
+ public static int indexOfPostFinalizationProcess(Runnable process) {
+ try {
+ synchronized (postFinalizationProcess) {
+ return postFinalizationProcess.indexOf(process);
+ }
+ } catch (NullPointerException npe) {
+ return -1;
+ }
+ }
+
+ public static boolean unregisterPostFinalizationProcess(Runnable process) {
+ try {
+ synchronized (postFinalizationProcess) {
+ boolean result = postFinalizationProcess.remove(process);
+ if (result && postFinalizationProcess.isEmpty()) {
+ postFinalizationProcess = null;
+ }
+ return result;
+ }
+ } catch (NullPointerException npe) {
+ return false;
+ }
+ }
+
+ /**
+ * Useful if a process wants to remove another one or itself during its execution.
+ * This asynchronous unregister method circumvents the synchronized-state on
+ * post-finalization process list.
+ */
+ public static void unregisterPostFinalizationProcessAfterNextRun(Runnable process) {
+ while (true) {
+ try {
+ synchronized (postFinalizationProcessRemove) {
+ postFinalizationProcessRemove.add(process);
+ }
+ return;
+ } catch (NullPointerException npe) {
+ postFinalizationProcessRemove = new ArrayList<>(1);
+ }
+ }
+ }
+
+ public static void notifyPreFinalization() {
+ ++openFinalizeCount;
+ if (System.currentTimeMillis() - postFinalizationTimestamp
+ < postFinalizationTimeOut) {
+ return;
+ }
+ try {
+ synchronized(preFinalizationProcess) {
+ for (Runnable r: preFinalizationProcess) {
+ try {
+ r.run();
+ } catch (Exception preProcessError) {
+ Py.writeError("gc", "Finalization preprocess "+r+" caused error: "
+ +preProcessError);
+ }
+ }
+ try {
+ synchronized (preFinalizationProcessRemove) {
+ preFinalizationProcess.removeAll(preFinalizationProcessRemove);
+ preFinalizationProcessRemove = null;
+ }
+ if (preFinalizationProcess.isEmpty()) {
+ preFinalizationProcess = null;
+ }
+ } catch (NullPointerException npe0) {}
+ }
+ } catch (NullPointerException npe) {
+ preFinalizationProcessRemove = null;
+ }
+
+ try {
+ synchronized(postFinalizationProcess) {
+ if (!postFinalizationProcess.isEmpty() &&
+ postFinalizationProcessor == null) {
+ postFinalizationPending = true;
+ postFinalizationProcessor = new Thread(
+ PostFinalizationProcessor.defaultInstance);
+ postFinalizationProcessor.start();
+ }
+ }
+ } catch (NullPointerException npe) {}
+ }
+
+ public static void notifyPostFinalization() {
+ postFinalizationTimestamp = System.currentTimeMillis();
+ --openFinalizeCount;
+ if (openFinalizeCount == 0 && postFinalizationProcessor != null) {
+ postFinalizationProcessor.interrupt();
+ }
+ }
+
+ protected static void postFinalizationProcess() {
+ try {
+ synchronized(postFinalizationProcess) {
+ for (Runnable r: postFinalizationProcess) {
+ try {
+ r.run();
+ } catch (Exception postProcessError) {
+ System.err.println("Finalization postprocess "+r+" caused error:");
+ System.err.println(postProcessError);
+ }
+ }
+ try {
+ synchronized (postFinalizationProcessRemove) {
+ postFinalizationProcess.removeAll(postFinalizationProcessRemove);
+ postFinalizationProcessRemove = null;
+ }
+ if (postFinalizationProcess.isEmpty()) {
+ postFinalizationProcess = null;
+ }
+ } catch (NullPointerException npe0) {}
+ }
+ } catch (NullPointerException npe) {
+ postFinalizationProcessRemove = null;
+ }
+ }
+ //----------end of Finalization preprocess/postprocess section-------------
+
+
+
+
+ //----------Monitoring section---------------------------------------------
+
+ public static void monitorObject(PyObject ob) {
+ monitorObject(ob, false);
+ }
+
+ public static void monitorObject(PyObject ob, boolean initString) {
+ //Already collected garbage should not be monitored,
+ //thus also not the garbage list:
+ if (ob == garbage) {
+ return;
+ }
+ if (!monitorNonTraversable && !isTraversable(ob)) {
+ if (!JyAttribute.hasAttr(ob, JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ return;
+ }
+ }
+ if (gcTrash == null) {
+ gcTrash = new ReferenceQueue<>();
+ }
+ while (true) {
+ try {
+ synchronized(monitoredObjects) {
+ if (!isMonitored(ob)) {
+ CycleMarkAttr cm = new CycleMarkAttr();
+ JyAttribute.setAttr(ob, JyAttribute.GC_CYCLE_MARK_ATTR, cm);
+ WeakReferenceGC refPut = new WeakReferenceGC(ob, gcTrash);
+ if (initString) {
+ refPut.initStr(ob);
+ }
+ monitoredObjects.add(refPut);
+ cm.monitored = true;
+ }
+ }
+ return;
+ } catch (NullPointerException npe) {
+ monitoredObjects = new HashSet<WeakReferenceGC>();
+ }
+ }
+ }
+
+ /**
+ * Avoid to use this method. It is inefficient and no intended purpose of the
+ * backing Set of objects. In normal business it should not be needed and only
+ * exists for bare debugging purposes.
+ */
+ public static WeakReferenceGC getMonitorReference(PyObject ob) {
+ try {
+ synchronized(monitoredObjects) {
+ for (WeakReferenceGC ref: monitoredObjects) {
+ if (ref.equals(ob)) {
+ return ref;
+ }
+ }
+ }
+ } catch (NullPointerException npe) {}
+ return null;
+ }
+
+ public static boolean isMonitoring() {
+ try {
+ synchronized(monitoredObjects) {
+ return !monitoredObjects.isEmpty();
+ }
+ } catch (NullPointerException npe) {
+ return false;
+ }
+ }
+
+ public static boolean isMonitored(PyObject ob) {
+ try {
+ synchronized(monitoredObjects) {
+ WeakrefGCCompareDummy.defaultInstance.setCompare(ob);
+ boolean result = monitoredObjects.contains(
+ WeakrefGCCompareDummy.defaultInstance);
+ WeakrefGCCompareDummy.defaultInstance.compare = null;
+ return result;
+ }
+ } catch (NullPointerException npe) {
+ return false;
+ }
+ }
+
+ public static boolean unmonitorObject(PyObject ob) {
+ try {
+ synchronized(monitoredObjects) {
+ WeakrefGCCompareDummy.defaultInstance.setCompare(ob);
+ WeakReferenceGC rem = getMonitorReference(ob);
+ if (rem != null) {
+ rem.clear();
+ }
+ boolean result = monitoredObjects.remove(
+ WeakrefGCCompareDummy.defaultInstance);
+ WeakrefGCCompareDummy.defaultInstance.compare = null;
+ JyAttribute.delAttr(ob, JyAttribute.GC_CYCLE_MARK_ATTR);
+ FinalizeTrigger ft = (FinalizeTrigger)
+ JyAttribute.getAttr(ob, JyAttribute.FINALIZE_TRIGGER_ATTR);
+ if (ft != null) {
+ ft.flags &= ~FinalizeTrigger.NOTIFY_GC_FLAG;
+ }
+ return result;
+ }
+ } catch (NullPointerException npe) {
+ return false;
+ }
+ }
+
+ public static void unmonitorAll() {
+ try {
+ synchronized(monitoredObjects) {
+ FinalizeTrigger ft;
+ for (WeakReferenceGC mo: monitoredObjects) {
+ PyObject rfrt = mo.get();
+ if (rfrt != null) {
+ JyAttribute.delAttr(rfrt, JyAttribute.GC_CYCLE_MARK_ATTR);
+ ft = (FinalizeTrigger)
+ JyAttribute.getAttr(rfrt, JyAttribute.FINALIZE_TRIGGER_ATTR);
+ if (ft != null) {
+ ft.flags &= ~FinalizeTrigger.NOTIFY_GC_FLAG;
+ }
+ }
+ mo.clear();
+ }
+ monitoredObjects.clear();
+ }
+ } catch (NullPointerException npe) {
+ }
+ }
+
+ public static void stopMonitoring() {
+ setMonitorGlobal(false);
+ if (monitoredObjects != null) {
+ unmonitorAll();
+ monitoredObjects = null;
+ }
+ }
+
+ public static boolean getMonitorGlobal() {
+ return PyObject.gcMonitorGlobal;
+ }
+
+ public static void setMonitorGlobal(boolean flag) {
+ if (flag) {
+ gcFlags |= MONITOR_GLOBAL;
+ } else {
+ gcFlags &= ~MONITOR_GLOBAL;
+ }
+ PyObject.gcMonitorGlobal = flag;
+ }
+ //----------end of Monitoring section--------------------------------------
+
+
+ public static short getJythonGCFlags() {
+ if (((gcFlags & MONITOR_GLOBAL) != 0) != PyObject.gcMonitorGlobal) {
+ if (PyObject.gcMonitorGlobal) {
+ gcFlags |= MONITOR_GLOBAL;
+ } else {
+ gcFlags &= ~MONITOR_GLOBAL;
+ }
+ }
+ return gcFlags;
+ }
+
+ public static void setJythonGCFlags(short flags) {
+ gcFlags = flags;
+ PyObject.gcMonitorGlobal = (gcFlags & MONITOR_GLOBAL) != 0;
+ updateDelayedFinalizationState();
+ }
+
+ /**
+ * This is a convenience method to add flags via bitwise or.
+ */
+ public static void addJythonGCFlags(short flags) {
+ gcFlags |= flags;
+ PyObject.gcMonitorGlobal = (gcFlags & MONITOR_GLOBAL) != 0;
+ updateDelayedFinalizationState();
+ }
+
+ /**
+ * This is a convenience method to remove flags via bitwise and-not.
+ */
+ public static void removeJythonGCFlags(short flags) {
+ gcFlags &= ~flags;
+ PyObject.gcMonitorGlobal = (gcFlags & MONITOR_GLOBAL) != 0;
+ updateDelayedFinalizationState();
+ }
+
+ /**
+ * Do not call this method manually.
+ * It should only be called by
+ * {@link org.python.core.finalization.FinalizeTrigger}.
+ */
+ public static void notifyFinalize(PyObject finalized) {
+ if (--finalizeWaitCount == 0 && waitingForFinalizers) {
+ synchronized(GCSentinel.class) {
+ GCSentinel.class.notify();
+ }
+ }
+ }
+
+ /**
+ * For now this just calls {@code notifyFinalize}, as the only current
+ * purpose is to decrement the open finalizer count.
+ */
+ private static void notifyAbortFinalize(PyObject abort, boolean cyclic) {
+ if (cyclic) {
+ ++abortedCyclicFinalizers;
+ }
+ notifyFinalize(abort);
+ }
+
+ public static void enable() {}
+
+ public static void disable() {
+ throw Py.NotImplementedError("can't disable Java GC");
+ }
+
+ public static boolean isenabled() { return true; }
+
+ /**
+ * The generation parameter is only for compatibility with
+ * CPython {@code gc.collect} and is ignored.
+ * @param generation (ignored)
+ * @return Collected monitored cyclic trash-objects or
+ * {@code gc.UNKNOWN_COUNT} if nothing is monitored or -1 if
+ * an error occurred and collection did not complete.
+ */
+ public static int collect(int generation) {
+ return collect();
+ }
+
+ private static boolean needsTrashPrinting() {
+ return ((debugFlags & DEBUG_COLLECTABLE) != 0 ||
+ (debugFlags & DEBUG_UNCOLLECTABLE) != 0) &&
+ ((debugFlags & DEBUG_INSTANCES) != 0 ||
+ (debugFlags & DEBUG_OBJECTS) != 0);
+ }
+
+ private static boolean needsCollectBuffer() {
+ return (debugFlags & DEBUG_STATS) != 0 || needsTrashPrinting();
+ }
+
+ /**
+ * If no objects are monitored, this just delegates to
+ * {@code System.gc} and returns {@code gc.UNKNOWN_COUNT} as a
+ * non-erroneous default value. If objects are monitored,
+ * it emulates a synchronous gc run in the sense that it waits
+ * until all collected monitored objects were finalized.
+ *
+ * @return Number of collected monitored cyclic trash-objects
+ * or {@code gc.UNKNOWN_COUNT} if nothing is monitored or -1
+ * if an error occurred and collection did not complete.
+ */
+ public static int collect() {
+ try {
+ return collect_intern();
+ } catch (java.util.ConcurrentModificationException cme) {
+ cme.printStackTrace();
+ } catch (NullPointerException npe) {
+ npe.printStackTrace();
+ }
+ return -1;
+ }
+
+ private static int collect_intern() {
+ long t1 = 0;
+ int result;
+ if ((debugFlags & DEBUG_STATS) != 0) {
+ t1 = System.currentTimeMillis();
+ }
+ if (!isMonitoring()) {
+ if ((debugFlags & DEBUG_STATS) != 0) {
+ writeDebug("gc", "collecting generation x...");
+ writeDebug("gc", "objects in each generation: unknown");
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "no monitoring; perform ordinary async System.gc...");
+ }
+ System.gc();
+ result = UNKNOWN_COUNT; //indicates unknown result (-1 would indicate error)
+ } else {
+ if (!gcRunning.compareAndSet(false, true)) {
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "collect already running...");
+ }
+ //We must fail fast in this case to avoid deadlocks.
+ //Deadlock would for instance occur if a finalizer calls
+ //gc.collect (like is done in some tests in test_gc).
+ //Former version: throw new IllegalStateException("GC is already running.");
+ return -1; //better not throw exception here, as calling code
+ //is usually not prepared for that
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "perform monitored sync gc run...");
+ }
+ if (needsTrashPrinting() || (gcFlags & VERBOSE) != 0) {
+ // When the weakrefs are enqueued, the referents won't be available
+ // any more to provide their string representations, so we must
+ // save the string representations in the weak ref objects while
+ // the referents are still alive.
+ // We cannot save the string representations in the moment when the
+ // objects get monitored, because with monitorGlobal activated
+ // the objects get monitored just when they are created and some
+ // of them are in an invalid state then and cannot directly obtain
+ // their string representation (produce overflow errors and such bad
+ // stuff). So we do it here...
+ List<WeakReferenceGC> lst = new ArrayList<>();
+ for (WeakReferenceGC wr: monitoredObjects) {
+ if (wr.str == null) {
+ lst.add(wr);
+ }
+ }
+ for (WeakReferenceGC ol: lst) {
+ ol.initStr(null);
+ }
+ lst.clear();
+ }
+ ++gcMonitoredRunCount;
+ delayedFinalizationMode = MARK_REACHABLE_CRITICS;
+ notifyRerun = false;
+
+ int[] stat = {0, 0};
+
+ syncCollect(stat, (debugFlags & DEBUG_STATS) != 0);
+ delayedFinalizationMode = NOTIFY_FOR_RERUN;
+
+ if (notifyRerun) {
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "initial sync collect done.");
+ }
+ while (notifyRerun) {
+ notifyRerun = false;
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "rerun gc...");
+ }
+ syncCollect(stat, false);
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "all sync collect runs done.");
+ }
+ } else if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "sync collect done.");
+ }
+
+ delayedFinalizationMode = DO_NOTHING_SPECIAL;
+ gcRunning.set(false);
+ result = stat[0];
+ if ((debugFlags & DEBUG_STATS) != 0) {
+ if (result != UNKNOWN_COUNT) {
+ StringBuilder sb = new StringBuilder("done, ");
+ sb.append(stat[0]);
+ sb.append(" unreachable, ");
+ sb.append(stat[1]);
+ sb.append(" uncollectable");
+ if (t1 != 0) {
+ sb.append(", ");
+ sb.append((System.currentTimeMillis()-t1)/1000.0);
+ sb.append("s elapsed");
+ }
+ sb.append(".");
+ writeDebug("gc", sb.toString());
+ }
+ }
+ }
+ if ((debugFlags & DEBUG_STATS) != 0 && result == UNKNOWN_COUNT) {
+ StringBuilder sb = new StringBuilder("done");
+ if (t1 != 0) {
+ sb.append(", ");
+ sb.append((System.currentTimeMillis()-t1)/1000.0);
+ sb.append("s elapsed");
+ }
+ sb.append(".");
+ writeDebug("gc", sb.toString());
+ }
+ return result;
+ }
+
+ private static void syncCollect(int[] stat, boolean debugStat) {
+ abortedCyclicFinalizers = 0;
+ lockPostFinalization = true;
+ Reference<? extends Object> trash;
+ try {
+ trash = gcTrash.remove(initWaitTime);
+ if (trash != null && (gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "monitored objects from previous gc-run found.");
+ }
+ } catch (InterruptedException ie) {
+ trash = null;
+ }
+ Set<WeakReferenceGC> cyclic;
+ IdentityHashMap<PyObject, WeakReferenceGC> cyclicLookup;
+ synchronized(monitoredObjects) {
+ if (trash != null) {
+ while (trash != null) {
+ monitoredObjects.remove(trash);
+ try {
+ trash = gcTrash.remove(initWaitTime);
+ } catch (InterruptedException ie) {
+ trash = null;
+ }
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "cleaned up previous trash.");
+ }
+ }
+ FinalizeTrigger ft;
+ for (WeakReferenceGC wrg: monitoredObjects) {
+ wrg.updateHasFinalizer();
+ if (wrg.hasFinalizer) {
+ ft = (FinalizeTrigger)
+ JyAttribute.getAttr(wrg.get(), JyAttribute.FINALIZE_TRIGGER_ATTR);
+ ft.flags |= FinalizeTrigger.NOTIFY_GC_FLAG;
+ //The NOTIFY_GC_FLAG is needed, because monitor state changes during
+ //collection. So the FinalizeTriggers can't use gc.isMonitored to know
+ //whether gc notification is needed.
+ }
+ }
+
+ //Typically this line causes a gc-run:
+ cyclicLookup = removeNonCyclicWeakRefs(monitoredObjects);
+ cyclic = new HashSet<>(cyclicLookup.values());
+ if (debugStat) {
+ writeDebug("gc", "collecting generation x...");
+ writeDebug("gc", "objects in each generation: "+cyclic.size());
+ }
+
+ if ((debugFlags & DEBUG_SAVEALL) != 0
+ || (gcFlags & DONT_FINALIZE_RESURRECTED_OBJECTS) != 0) {
+ cyclic.retainAll(monitoredObjects);
+ for (WeakReferenceGC wrg: cyclic) {
+ if (!wrg.hasFinalizer) {
+ PyObject obj = wrg.get();
+ FinalizeTrigger.ensureFinalizer(obj);
+ wrg.updateHasFinalizer();
+ ft = (FinalizeTrigger)
+ JyAttribute.getAttr(obj, JyAttribute.FINALIZE_TRIGGER_ATTR);
+ ft.flags |= FinalizeTrigger.NOT_FINALIZABLE_FLAG;
+ ft.flags |= FinalizeTrigger.NOTIFY_GC_FLAG;
+ }
+ }
+ }
+ }
+ maxWaitTime = initWaitTime;
+ WeakReference<GCSentinel> sentRef =
+ new WeakReference<>(new GCSentinel(Thread.currentThread()), gcTrash);
+ lastRemoveTimeStamp = System.currentTimeMillis();
+ if (finalizeWaitCount != 0) {
+ System.err.println("Finalize wait count should be initially 0!");
+ finalizeWaitCount = 0;
+ }
+
+ // We tidy up a bit... (Because it is not unlikely that
+ // the preparation-stuff done so far has caused a gc-run.)
+ // This is not entirely safe as gc could interfere with
+ // this process at any time again. Since this is intended
+ // for debugging, this solution is sufficient in practice.
+ // Maybe we will include more mechanisms to ensure safety
+ // in the future.
+
+ try {
+ trash = gcTrash.remove(initWaitTime);
+ if (trash != null && (gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "monitored objects from interferring gc-run found.");
+ }
+ } catch (InterruptedException ie) {
+ trash = null;
+ }
+ if (trash != null) {
+ while (trash != null) {
+ monitoredObjects.remove(trash);
+ if (cyclic.remove(trash) && (gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "cyclic interferring trash: "+trash);
+ } else if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "interferring trash: "+trash);
+ }
+ try {
+ trash = gcTrash.remove(initWaitTime);
+ } catch (InterruptedException ie) {
+ trash = null;
+ }
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "cleaned up interferring trash.");
+ }
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "call System.gc.");
+ }
+ cyclicLookup = null;
+ System.gc();
+ List<WeakReferenceGC> collectBuffer = null;
+ if (needsCollectBuffer()) {
+ collectBuffer = new ArrayList<>();
+ }
+ long removeTime;
+ try {
+ while(true) {
+ removeTime = System.currentTimeMillis()-lastRemoveTimeStamp;
+ if (removeTime > maxWaitTime) {
+ maxWaitTime = removeTime;
+ }
+ lastRemoveTimeStamp = System.currentTimeMillis();
+ trash = gcTrash.remove(Math.max(gcRecallTime, maxWaitTime*defaultWaitFactor));
+ if (trash != null) {
+ if (trash instanceof WeakReferenceGC) {
+ synchronized(monitoredObjects) {
+ monitoredObjects.remove(trash);
+ }
+ //We avoid counting jython-specific objects in order to
+ //obtain CPython-comparable results.
+ if (cyclic.contains(trash) && !((WeakReferenceGC) trash).cls.contains("Java")) {
+ ++stat[0];
+ if (collectBuffer != null) {
+ collectBuffer.add((WeakReferenceGC) trash);
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "Collected cyclic object: "+trash);
+ }
+ }
+ if (((WeakReferenceGC) trash).hasFinalizer) {
+ ++finalizeWaitCount;
+ if ((gcFlags & VERBOSE_FINALIZE) != 0) {
+ writeDebug("gc", "Collected finalizable object: "+trash);
+ writeDebug("gc", "New finalizeWaitCount: "+finalizeWaitCount);
+ }
+ }
+ } else if (trash == sentRef && (gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "Sentinel collected.");
+ }
+ } else {
+ System.gc();
+ }
+ }
+ } catch (InterruptedException iex) {}
+
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "all objects from run enqueud in trash queue.");
+ writeDebug("gc", "pending finalizers: "+finalizeWaitCount);
+ }
+ //lockPostFinalization assures that postFinalization process
+ //only runs once per syncCollect-call.
+ lockPostFinalization = false;
+ if (postFinalizationProcessor != null) {
+ //abort the remaining wait-time if a postFinalizationProcessor is waiting
+ postFinalizationProcessor.interrupt();
+ }
+ waitingForFinalizers = true;
+ if (finalizeWaitCount != 0) {
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "waiting for "+finalizeWaitCount+
+ " pending finalizers.");
+ if (finalizeWaitCount < 0) {
+ //Maybe even throw exception here?
+ Py.writeError("gc", "There should never be "+
+ "less than zero pending finalizers!");
+ }
+ }
+ // It is important to have the while *inside* the synchronized block.
+ // Otherwise the notify might come just between the check and the wait,
+ // causing an endless waiting.
+ synchronized(GCSentinel.class) {
+ while (finalizeWaitCount != 0) {
+ try {
+ GCSentinel.class.wait();
+ } catch (InterruptedException ie2) {}
+ }
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "no more finalizers pending.");
+ }
+ }
+ waitingForFinalizers = false;
+
+ if (postFinalizationPending) {
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc",
+ "waiting for pending post-finalization process.");
+ }
+ // It is important to have the while (which is actually an "if" since the
+ // InterruptedException is very unlikely to occur) *inside* the synchronized
+ // block. Otherwise the notify might come just between the check and the wait,
+ // causing an endless waiting. This is no pure academic consideration, but was
+ // actually observed to happen from time to time, especially on faster systems.
+ synchronized(PostFinalizationProcessor.class) {
+ while (postFinalizationPending) {
+ try {
+ PostFinalizationProcessor.class.wait();
+ } catch (InterruptedException ie3) {}
+ }
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", "post-finalization finished.");
+ }
+ }
+ if (collectBuffer != null) {
+ /* There is a little discrepancy in CPython's behavior.
+ * The documentation tells that all uncollectable objects
+ * are stored in gc.garbage, but it actually stores only
+ * those uncollectable objects that have finalizers.
+ * In contrast to that the uncollectable counting and
+ * listing related to DEBUG_X-flags also counts/lists
+ * objects that participate in a cycle with uncollectable
+ * finalizable objects.
+ *
+ * Comprehension:
+ * An object is uncollectable if it is in a ref cycle and
+ * has a finalizer.
+ *
+ * CPython
+ *
+ * - counts and prints the whole uncollectable cycle in context
+ * of DEBUG_X-flags.
+ *
+ * - stores only those objects from the cycle that actually have
+ * finalizers in gc.garbage.
+ *
+ * While slightly contradictionary to the doc, we reproduce this
+ * behavior here.
+ */
+ if ((debugFlags & gc.DEBUG_COLLECTABLE) != 0 &&
+ ( (debugFlags & gc.DEBUG_OBJECTS) != 0 ||
+ (debugFlags & gc.DEBUG_INSTANCES) != 0)) {
+ //note that all cycleMarks should have been initialized when
+ //objects became monitored.
+
+ for (WeakReferenceGC wrg: collectBuffer) {
+ if (!wrg.cycleMark.isUncollectable()) {
+ if (wrg.isInstance) {
+ writeDebug("gc", "collectable "+
+ ((debugFlags & gc.DEBUG_INSTANCES) != 0 ?
+ wrg.inst_str : wrg.str));
+ } else if ((debugFlags & gc.DEBUG_OBJECTS) != 0) {
+ writeDebug("gc", "collectable "+wrg.str);
+ }
+ } else {
+ ++stat[1];
+ }
+ }
+ } else if ((debugFlags & gc.DEBUG_STATS) != 0) {
+ for (WeakReferenceGC wrg: collectBuffer) {
+ if (wrg.cycleMark.isUncollectable()) {
+ ++stat[1];
+ }
+ }
+ }
+ if ((debugFlags & gc.DEBUG_UNCOLLECTABLE) != 0 &&
+ ( (debugFlags & gc.DEBUG_OBJECTS) != 0 ||
+ (debugFlags & gc.DEBUG_INSTANCES) != 0)) {
+ for (WeakReferenceGC wrg: collectBuffer) {
+ if (wrg.cycleMark.isUncollectable()) {
+ if (wrg.isInstance) {
+ writeDebug("gc", "uncollectable "+
+ ((debugFlags & gc.DEBUG_INSTANCES) != 0 ?
+ wrg.inst_str : wrg.str));
+ } else if ((debugFlags & gc.DEBUG_OBJECTS) != 0) {
+ writeDebug("gc", "uncollectable "+wrg.str);
+ }
+ }
+ }
+ }
+ }
+ if ((gcFlags & VERBOSE_COLLECT) != 0) {
+ writeDebug("gc", abortedCyclicFinalizers+
+ " finalizers aborted.");
+ }
+ stat[0] -= abortedCyclicFinalizers;
+ stat[1] -= abortedCyclicFinalizers;
+ }
+
+ public static PyObject get_count() {
+ throw Py.NotImplementedError("not applicable to Java GC");
+ }
+
+ public static void set_debug(int flags) {
+ debugFlags = flags;
+ }
+
+ public static int get_debug() {
+ return debugFlags;
+ }
+
+ public static void set_threshold(PyObject[] args, String[] kwargs) {
+ throw Py.NotImplementedError("not applicable to Java GC");
+ }
+
+ public static PyObject get_threshold() {
+ throw Py.NotImplementedError("not applicable to Java GC");
+ }
+
+ public static PyObject get_objects() {
+ throw Py.NotImplementedError("not applicable to Java GC");
+ }
+
+ /**
+ * Only works reliably if {@code monitorGlobal} is active, as it depends on
+ * monitored objects to search for referrers. It only finds referrers that
+ * properly implement the traverseproc mechanism (unless reflection-based
+ * traversion is activated and works stable).
+ * Further note that the resulting list will contain referrers in no specific
+ * order and may even include duplicates.
+ */
+ public static PyObject get_referrers(PyObject[] args, String[] kwargs) {
+ if (!isMonitoring()) {
+ throw Py.NotImplementedError(
+ "not applicable in Jython if gc module is not monitoring PyObjects");
+ }
+ if (args == null) {
+ return Py.None;
+ }
+ PyObject result = new PyList();
+ PyObject[] coll = {null, result};
+ PyObject src;
+ synchronized(monitoredObjects) {
+ for (PyObject ob: args) {
+ for (WeakReferenceGC src0: monitoredObjects) {
+ src = (PyObject) src0.get(); //Sentinels should not be in monitoredObjects
+ if (src instanceof Traverseproc) {
+ try {
+ if (((Traverseproc) src).refersDirectlyTo(ob)) {
+ result.__add__(src);
+ }
+ } catch (UnsupportedOperationException uoe) {
+ coll[0] = ob;
+ traverse(ob, ReferrerFinder.defaultInstance, coll);
+ }
+ } else if (isTraversable(src)) {
+ coll[0] = ob;
+ traverse(ob, ReferrerFinder.defaultInstance, coll);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Only works reliably if all objects in args properly
+ * implement the Traverseproc mechanism (unless reflection-based traversion
+ * is activated and works stable).
+ * Further note that the resulting list will contain referents in no
+ * specific order and may even include duplicates.
+ */
+ public static PyObject get_referents(PyObject[] args, String[] kwargs) {
+ if (args == null) {
+ return Py.None;
+ }
+ PyObject result = new PyList();
+ for (PyObject ob: args) {
+ traverse(ob, ReferentsFinder.defaultInstance, result);
+ }
+ return result;
+ }
+
+ /**
+ * {@code is_tracked} is - in Jython case - interpreted in the sense that
+ * {@code gc.collect} will be able to count the object as collected if it
+ * participates in a cycle. This mimics CPython behavior and passes
+ * the corresponding unit test in {@code test_gc.py}.
+ */
+ public static PyObject is_tracked(PyObject[] args, String[] kwargs) {
+ if (isTraversable(args[0]) &&
+ (monitoredObjects == null || isMonitored(args[0]))) {
+ return Py.True;
+ } else {
+ return Py.False;
+ }
+ }
+
+ /**
+ * Returns all objects from {@code pool} that are part of reference cycles as a new set.
+ * If a reference-cycle is not entirely contained in {@code pool}, it will be entirely
+ * contained in the resulting set, i.e. missing participants will be added.
+ * This method completely operates on weak references to ensure that the returned
+ * set does not manipulate gc-behavior.
+ *
+ * Note that this method is not thread-safe. Within the gc-module it is only used
+ * by the collect-method which ensures thread-safety by a synchronized block.
+ */
+ private static IdentityHashMap<PyObject, WeakReferenceGC>
+ removeNonCyclicWeakRefs(Iterable<WeakReferenceGC> pool) {
+ @SuppressWarnings("unchecked")
+ IdentityHashMap<PyObject, WeakReferenceGC>[] pools = new IdentityHashMap[2];
+
+ pools[0] = new IdentityHashMap<PyObject, WeakReferenceGC>();
+ pools[1] = new IdentityHashMap<PyObject, WeakReferenceGC>();
+ PyObject referent;
+ if (monitorNonTraversable) {
+ //this means there might be non-traversable objects in the pool we must filter out now
+ for (WeakReferenceGC ref: pool) {
+ referent = ref.get();
+ if (referent != null && isTraversable(referent)) {
+ pools[0].put(referent, ref);
+ }
+ }
+ } else {
+ //this means the pool is already entirely traversable
+ for (WeakReferenceGC ref: pool) {
+ referent = ref.get();
+ if (referent != null)
+ pools[0].put(referent, ref);
+ }
+ }
+ IdentityHashMap<PyObject, WeakReferenceGC> tmp;
+ IdentityHashMap<PyObject, WeakReferenceGC> toProcess = new IdentityHashMap<>();
+ //We complete pools[0] with all reachable objects.
+ for (WeakReferenceGC ref: pools[0].values()) {
+ traverse((PyObject) ref.get(), ReachableFinderWeakRefs.defaultInstance, pools);
+ }
+ while (!pools[1].isEmpty()) {
+ tmp = pools[1];
+ pools[1] = toProcess;
+ toProcess = tmp;
+ pools[0].putAll(toProcess);
+ for (WeakReferenceGC ref: toProcess.values()) {
+ traverse((PyObject) ref.get(), ReachableFinderWeakRefs.defaultInstance, pools);
+ }
+ toProcess.clear();
+ }
+ //pools[0] should now be a closed set in the sense that it contains all PyObjects
+ //reachable from pools[0]. Now we are going to remove non-cyclic objects:
+
+ boolean done = false;
+ while (!done) {
+ done = true;
+ //After this loop pools[1] contains all objects from pools[0]
+ //that some object in pools[0] points to.
+ //toRemove will contain all objects from pools[0] that don't
+ //point to any object in pools[0]. Removing toRemove from
+ //pools[1] and repeating this procedure until nothing changes
+ //any more will let only cyclic trash remain.
+ for (WeakReferenceGC ref: pools[0].values()) {
+ RefInListFinder.defaultInstance.found = false;
+ referent = ref.get();
+ traverse(referent , RefInListFinder.defaultInstance, pools);
+ if (!RefInListFinder.defaultInstance.found) {
+ toProcess.put(referent, ref);
+ done = false;
+ }
+ }
+ for (PyObject ref: toProcess.keySet()) {
+ pools[1].remove(ref);
+ }
+ toProcess.clear();
+ done = done && pools[0].size() == pools[1].size();
+ tmp = pools[0];
+ tmp.clear();
+ pools[0] = pools[1];
+ pools[1] = tmp;
+ }
+ return pools[0];
+ }
+
+ /**
+ * Computes the set of objects reachable from {@code pool}, not necessarily
+ * including {@code pool} itself; only those objects from {@code pool} that are
+ * reachable from at least one other object in {@code pool} will be included
+ * in the result.
+ */
+ private static Set<PyObject> findReachables(Iterable<PyObject> pool) {
+ @SuppressWarnings("unchecked")
+ IdentityHashMap<PyObject, PyObject>[] pools = new IdentityHashMap[2];
+
+ pools[0] = new IdentityHashMap<PyObject, PyObject>();
+ pools[1] = new IdentityHashMap<PyObject, PyObject>();
+ IdentityHashMap<PyObject, PyObject> tmp;
+ IdentityHashMap<PyObject, PyObject> toProcess = new IdentityHashMap<>();
+
+ //We complete pools[0] with all reachable objects.
+ //Note the difference to the implementation in removeNonCyclic.
+ //There pools[0] was initialized with the contents of pool and
+ //then used here as iteration source. In contrast to that we don't
+ //want to have pool contained in the reachable set in any case here.
+ for (PyObject obj: pool) {
+ if (isTraversable(obj)) {
+ traverse(obj, ReachableFinder.defaultInstance, pools);
+ }
+ }
+ while (!pools[1].isEmpty()) {
+ tmp = pools[1];
+ pools[1] = toProcess;
+ toProcess = tmp;
+ pools[0].putAll(toProcess);
+ for (PyObject obj: toProcess.keySet()) {
+ traverse(obj, ReachableFinder.defaultInstance, pools);
+ }
+ toProcess.clear();
+ }
+ //pools[0] should now be a closed set in the sense that it contains all PyObjects
+ //reachable from pools[0].
+ return pools[0].keySet();
+ }
+
+ /**
+ * Returns all objects from {@code pool} that are part of reference-cycles as a new set.
+ * If a reference-cycle is not entirely contained in {@code pool}, it will be entirely
+ * contained in the resulting set, i.e. missing participants will be added.
+ * This method completely operates on weak references to ensure that the returned
+ * set does not manipulate gc-behavior.
+ *
+ * Note that this method is not thread-safe. Within the gc-module it is only used
+ * by the collect-method which ensures thread-safety by a synchronized block.
+ */
+ private static Set<PyObject> removeNonCyclic(Iterable<PyObject> pool) {
+ @SuppressWarnings("unchecked")
+ IdentityHashMap<PyObject, PyObject>[] pools = new IdentityHashMap[2];
+
+ pools[0] = new IdentityHashMap<PyObject, PyObject>();
+ pools[1] = new IdentityHashMap<PyObject, PyObject>();
+ if (monitorNonTraversable) {
+ //this means there might be non-traversable objects in the pool we must filter out now
+ for (PyObject obj: pool) {
+ if (isTraversable(obj)) {
+ pools[0].put(obj, obj);
+ }
+ }
+ } else {
+ //this means the pool is already entirely traversable
+ for (PyObject obj: pool) {
+ pools[0].put(obj, obj);
+ }
+ }
+ IdentityHashMap<PyObject, PyObject> tmp;
+ IdentityHashMap<PyObject, PyObject> toProcess = new IdentityHashMap<>();
+
+ //We complete pools[0] with all reachable objects.
+ for (PyObject obj: pools[0].keySet()) {
+ traverse(obj, ReachableFinder.defaultInstance, pools);
+ }
+ while (!pools[1].isEmpty()) {
+ tmp = pools[1];
+ pools[1] = toProcess;
+ toProcess = tmp;
+ pools[0].putAll(toProcess);
+ for (PyObject obj: toProcess.keySet()) {
+ traverse(obj, ReachableFinder.defaultInstance, pools);
+ }
+ toProcess.clear();
+ }
+ //pools[0] now is a closed set in the sense that it contains all PyObjects
+ //reachable from pools[0]. Now we are going to remove non-cyclic objects:
+
+ boolean done = false;
+ while (!done) {
+ done = true;
+ // After this loop pools[1] contains all objects from pools[0]
+ // that some object in pools[0] points to.
+ // toRemove will contain all objects from pools[0] that don't
+ // point to any object in pools[0]. Removing toRemove from
+ // pools[1] and repeating this procedure until nothing changes
+ // any more will let only cyclic trash remain.
+ for (PyObject obj: pools[0].keySet()) {
+ ObjectInListFinder.defaultInstance.found = false;
+ traverse(obj, ObjectInListFinder.defaultInstance, pools);
+ if (!ObjectInListFinder.defaultInstance.found) {
+ toProcess.put(obj, obj);
+ done = false;
+ }
+ }
+ for (PyObject obj: toProcess.keySet()) {
+ pools[1].remove(obj);
+ }
+ toProcess.clear();
+ done = done && pools[0].size() == pools[1].size();
+ tmp = pools[0];
+ tmp.clear();
+ pools[0] = pools[1];
+ pools[1] = tmp;
+ }
+ return pools[0].keySet();
+ }
+
+ /**
+ * Mark all objects that are reachable from start AND can reach start,
+ * thus participate in a cycle with start.
+ */
+ public static void markCyclicObjects(PyObject start, boolean uncollectable) {
+ Set<PyObject> search = findCyclicObjects(start);
+ if (search == null) {
+ return;
+ }
+ //Search contains the cyclic objects that participate in a cycle with start,
+ //i.e. which are reachable from start AND can reach start.
+ //Mark these...
+ CycleMarkAttr cm;
+ for (PyObject obj: search) {
+ cm = (CycleMarkAttr) JyAttribute.getAttr(obj, JyAttribute.GC_CYCLE_MARK_ATTR);
+ if (cm == null) {
+ cm = new CycleMarkAttr(true, uncollectable);
+ JyAttribute.setAttr(obj,
+ JyAttribute.GC_CYCLE_MARK_ATTR, cm);
+ } else {
+ cm.setFlags(true, uncollectable);
+ }
+ }
+ }
+
+ /**
+ * Return objects that are reachable from start AND can reach start,
+ * thus participate in a cycle with start.
+ * Returns {@code null} if start does not participate in any cycle.
+ */
+ public static Set<PyObject> findCyclicObjects(PyObject start) {
+ IdentityHashMap<PyObject, PyObject> map = findCyclicObjectsIntern(start);
+ return map == null ? null : map.keySet();
+ }
+
+ private static IdentityHashMap<PyObject, PyObject> findCyclicObjectsIntern(PyObject start) {
+ if (!isTraversable(start)) {
+ return null;
+ }
+ //first determine the reachable set:
+ @SuppressWarnings("unchecked")
+ IdentityHashMap<PyObject, PyObject>[] reachSearch =
+ (IdentityHashMap<PyObject, PyObject>[]) new IdentityHashMap[2];
+ reachSearch[0] = new IdentityHashMap<PyObject, PyObject>();
+ reachSearch[1] = new IdentityHashMap<PyObject, PyObject>();
+ IdentityHashMap<PyObject, PyObject> tmp, search = new IdentityHashMap<PyObject, PyObject>();
+ traverse(start, ReachableFinder.defaultInstance, reachSearch);
+ tmp = search;
+ search = reachSearch[1];
+ tmp.clear();
+ reachSearch[1] = tmp;
+ while (!search.isEmpty()) {
+ reachSearch[0].putAll(search);
+ for (PyObject obj: search.keySet()) {
+ traverse(obj, ReachableFinder.defaultInstance, reachSearch);
+ }
+ tmp = search;
+ search = reachSearch[1];
+ tmp.clear();
+ reachSearch[1] = tmp;
+ }
+ //reachSearch[0] is now the reachable set, but still contains non-cyclic objects
+ if (!reachSearch[0].containsKey(start)) {
+ return null;
+ }
+ search.clear();
+ search.put(start, start);
+ boolean changed = true;
+ while (changed) {
+ changed = false;
+ for (PyObject obj: reachSearch[0].keySet()) {
+ if (traverse(obj, RefersToSetFinder.defaultInstance, search.keySet()) == 1) {
+ changed = true;
+ tmp.put(obj, obj);
+ }
+ }
+ //move all objects that can reach start from reachSearch[0] to search
+ search.putAll(tmp);
+ for (PyObject key: tmp.keySet()) {
+ reachSearch[0].remove(key);
+ }
+ tmp.clear();
+ }
+ return search;
+ }
+
+ public static int traverse(PyObject ob, Visitproc visit, Object arg) {
+ int retVal;
+ boolean traversed = false;
+ if (ob instanceof Traverseproc) {
+ retVal = ((Traverseproc) ob).traverse(visit, arg);
+ traversed = true;
+ if (retVal != 0) return retVal;
+ }
+ if (ob instanceof TraverseprocDerived) {
+ retVal = ((TraverseprocDerived) ob).traverseDerived(visit, arg);
+ traversed = true;
+ if (retVal != 0) return retVal;
+ }
+ if ((gcFlags & SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING) == 0) {
+ if (! (ob instanceof Traverseproc || ob instanceof TraverseprocDerived ||
+ ob.getClass() == PyObject.class ||
+ ob.getClass().isAnnotationPresent(Untraversable.class)) ) {
+ Py.writeWarning("gc", "The PyObject-subclass "+ob.getClass().getName()+"\n" +
+ "should either implement Traverseproc or be marked with the\n" +
+ "@Untraversable annotation. See the instructions\n" +
+ "in javadoc of org.python.core.Traverseproc.java.");
+ }
+ }
+ if ((gcFlags & DONT_TRAVERSE_BY_REFLECTION) != 0) {
+ return 0;
+ }
+ Class<?> cls = ob.getClass();
+ if (traversed || cls == PyObject.class ||
+ cls.isAnnotationPresent(Untraversable.class)) {
+ return 0;
+ }
+ if ((gcFlags & SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING) == 0) {
+ Py.writeWarning("gc", "Traverse by reflection: "+ob.getClass().getName()+"\n" +
+ "This is an inefficient procedure. It is recommended to\n" +
+ "implement the traverseproc mechanism properly.");
+ }
+ return traverseByReflection(ob, visit, arg);
+ }
+
+ /**
+ * <p>
+ * This method recursively traverses fields of {@code ob}.
+ * If a field is a PyObject, it is passed to {@code visit}.
+ * and recursion ends in that branch.
+ * If a field is an array, the elements are checked whether
+ * they are PyObjects. {@code PyObject}-elements are passed to
+ * {@code visit}. Elements that are arrays themselves are again
+ * processed elementwise and so on.
+ * </p>
+ * <p>
+ * Through the whole search this method fails fast if
+ * {@code visit} returns non-zero.
+ * </p>
+ * <p>
+ * Note that we intentionally don't traverse iterables by
+ * iterating them. Since we perform recursion, this should reach
+ * all contained references anyway - in Java every object
+ * can only contain references as fields or arrays.
+ * On the one hand, exploiting iterables would ease the
+ * access to private fields, but on the other hand during
+ * iteration they might change inner state, create
+ * new (Py)Objects or obtain objects from native methods.
+ * Additionally we might run into concurrent modification issues.
+ * So all in all the traversal is cleaner and safer if just
+ * fields and arrays are traversed.
+ * </p>
+ */
+ public static int traverseByReflection(Object ob, Visitproc visit, Object arg) {
+ IdentityHashMap<Object, Object> alreadyTraversed = new IdentityHashMap<>();
+ alreadyTraversed.put(ob, ob);
+ return traverseByReflectionIntern(ob, alreadyTraversed, visit, arg);
+ }
+
+ private static int traverseByReflectionIntern(Object ob,
+ IdentityHashMap<Object, Object> alreadyTraversed, Visitproc visit, Object arg) {
+ Class<? extends Object> cls = ob.getClass();
+ int result;
+ Object element;
+ if (cls.isArray() && canLinkToPyObject(cls.getComponentType(), false)) {
+ for (int i = 0; i < Array.getLength(ob); ++i) {
+ element = Array.get(ob, i);
+ if (element != null && !alreadyTraversed.containsKey(element)) {
+ alreadyTraversed.put(element, element);
+ if (element instanceof PyObject) {
+ result = visit.visit((PyObject) element, arg);
+ } else {
+ result = traverseByReflectionIntern(element,
+ alreadyTraversed, visit, arg);
+ }
+ if (result != 0) {
+ return result;
+ }
+ }
+ }
+ } else {
+ while (cls != Object.class && cls != PyObject.class) {
+ Field[] declFields = cls.getDeclaredFields();
+ for (int i = 0; i < declFields.length; ++i) {
+ if (!Modifier.isStatic(declFields[i].getModifiers()) &&
+ !declFields[i].getType().isPrimitive()) {
+ if (!declFields[i].isAccessible()) {
+ declFields[i].setAccessible(true);
+ }
+ if (canLinkToPyObject(declFields[i].getType(), false)) {
+ try {
+ element = declFields[i].get(ob);
+ if (!alreadyTraversed.containsKey(element)) {
+ alreadyTraversed.put(element, element);
+ if (element instanceof PyObject) {
+ result = visit.visit((PyObject) element, arg);
+ } else {
+ result = traverseByReflectionIntern(element,
+ alreadyTraversed, visit, arg);
+ }
+ if (result != 0) {
+ return result;
+ }
+ }
+ } catch (Exception e) {}
+ }
+ }
+ }
+ cls = cls.getSuperclass();
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * <p>
+ * This method checks via type-checking-only, whether an object
+ * of the given class can in principle hold a ref to a {@code PyObject}.
+ * Especially if arrays are involved, this can safe a lot performance.
+ * For now, no generic-type info is exploited.
+ * </p>
+ * <p>
+ * If {@code actual} is true, the answer will hold for an object
+ * that<b> is </b>an instance of the given class.
+ * Otherwise it is assumed that cls is the type of a field holding an
+ * object, so cls is considered as upper bound for an objects actual
+ * type.
+ * </p>
+ * <p>
+ * One should call with {@code actual == true}, if cls was obtained
+ * by {@code ob.getClass()} and with {@code actual == false}, if cls
+ * was obtained as a field-type or component-type of an array.
+ * </p>
+ */
+ public static boolean canLinkToPyObject(Class<?> cls, boolean actual) {
+ // At first some quick fail fast/succeed fast-checks:
+ if (quickCheckCannotLinkToPyObject(cls)) {
+ return false;
+ }
+ if (!actual && (!Modifier.isFinal(cls.getModifiers()))) {
+ return true; //a subclass could contain anything
+ }
+ if (quickCheckCanLinkToPyObject(cls)) {
+ return true;
+ }
+ if (cls.isInterface() || Modifier.isAbstract(cls.getModifiers())) {
+ return true;
+ }
+ if (cls.isArray()) {
+ return canLinkToPyObject(cls.getComponentType(), false);
+ }
+ Class<?> cls2 = cls;
+
+ // Fail fast if no fields exist in cls:
+ int fieldCount = cls2.getDeclaredFields().length;
+ while (fieldCount == 0 && cls2 != Object.class) {
+ cls2 = cls2.getSuperclass();
+ fieldCount += cls.getDeclaredFields().length;
+ }
+ if (fieldCount == 0) {
+ return false;
+ }
+ IdentityHashMap<Class<?>, Class<?>> alreadyChecked = new IdentityHashMap<>();
+ alreadyChecked.put(cls, cls);
+ cls2 = cls;
+ Class<?> ft;
+ while (cls2 != Object.class) {
+ for (Field f: cls2.getDeclaredFields()) {
+ if (!Modifier.isStatic(f.getModifiers())) {
+ ft = f.getType();
+ if (!ft.isPrimitive() && !alreadyChecked.containsKey(ft)) {
+ alreadyChecked.put(ft, ft);
+ if (canLinkToPyObjectIntern(ft, alreadyChecked)) {
+ return true;
+ }
+ }
+ }
+ }
+ cls2 = cls2.getSuperclass();
+ }
+ return false;
+ }
+
+ private static boolean quickCheckCanLinkToPyObject(Class<?> cls) {
+ if (!Modifier.isFinal(cls.getModifiers())) {
+ return true;
+ }
+ if (cls.isAssignableFrom(PyObject.class)) {
+ return true;
+ }
+ if (PyObject.class.isAssignableFrom(cls)) {
+ return true;
+ }
+ if (cls.isArray()) {
+ return quickCheckCanLinkToPyObject(cls.getComponentType());
+ }
+ return false;
+ }
+
+ private static boolean quickCheckCannotLinkToPyObject(Class<?> cls) {
+ if (cls.isPrimitive()) {
+ return true;
+ }
+ if (cls == String.class || cls == Class.class ||
+ cls == Field.class || cls == java.lang.reflect.Method.class) {
+ return true;
+ }
+ if (cls.isArray()) {
+ return quickCheckCannotLinkToPyObject(cls.getComponentType());
+ }
+ return false;
+ }
+
+ private static boolean canLinkToPyObjectIntern(Class<?> cls,
+ IdentityHashMap<Class<?>, Class<?>> alreadyChecked) {
+ if (quickCheckCanLinkToPyObject(cls)) {
+ return true;
+ }
+ if (quickCheckCannotLinkToPyObject(cls)) {
+ return false;
+ }
+ if (cls.isArray()) {
+ return canLinkToPyObjectIntern(cls.getComponentType(), alreadyChecked);
+ }
+ Class<?> cls2 = cls;
+ Class<?> ft;
+ while (cls2 != Object.class) {
+ for (Field f: cls2.getDeclaredFields()) {
+ if (!Modifier.isStatic(f.getModifiers())) {
+ ft = f.getType();
+ if (!ft.isPrimitive() && !alreadyChecked.containsKey(ft)) {
+ alreadyChecked.put(ft, ft);
+ if (canLinkToPyObjectIntern(ft, alreadyChecked)) {
+ return true;
+ }
+ }
+ }
+ }
+ cls2 = cls2.getSuperclass();
+ }
+ return false;
+ }
+
+ public static boolean isTraversable(PyObject ob) {
+ if (ob == null) {
+ return false;
+ }
+ if (ob instanceof Traverseproc || ob instanceof TraverseprocDerived) {
+ return true;
+ }
+ if ((gcFlags & DONT_TRAVERSE_BY_REFLECTION) != 0) {
+ return false;
+ }
+ Class<?> cls = ob.getClass();
+ return !(cls == PyObject.class ||
+ cls.isAnnotationPresent(Untraversable.class));
+ }
+
+ //----------Visitproc section----------------------------------------------
+
+ static class ReferentsFinder implements Visitproc {
+ public static ReferentsFinder defaultInstance = new ReferentsFinder();
+
+ /**
+ * Expects arg to be a list-like {@code PyObject} where the
+ * referents will be inserted.
+ */
+ public int visit(PyObject object, Object arg) {
+ ((org.python.core.PySequenceList) arg).pyadd(object);
+ return 0;
+ }
+ }
+
+ /**
+ * Helper to find the reachable set of an object. {@code arg} must be a
+ * 2-component array of type {@code IdentityHashMap<PyObject, PyObject>[]}.
+ * Although these are maps, the components of {@code arg} are conceptually
+ * used as sets. {@code arg[0]} shall contain all objects already known to
+ * be reachable. The visitproc adds all newly discovered objects to
+ * {@code arg[1]}, so the user can later add these to the reachable set and
+ * knows they need to be explored further. Only traversable objects are
+ * considered by this visitproc.
+ */
+ static class ReachableFinder implements Visitproc {
+ public static ReachableFinder defaultInstance = new ReachableFinder();
+
+ /**
+ * Expects arg to be a list-like {@code PyObject} where the
+ * referents will be inserted.
+ */
+ @SuppressWarnings("unchecked")
+ public int visit(PyObject object, Object arg) {
+ IdentityHashMap<PyObject, PyObject>[] reachSearch =
+ (IdentityHashMap<PyObject, PyObject>[]) arg;
+ if ((isTraversable(object)) &&
+ !reachSearch[0].containsKey(object)) {
+ reachSearch[1].put(object, object);
+ }
+ return 0;
+ }
+ }
+
+ static class ReachableFinderWeakRefs implements Visitproc {
+ public static ReachableFinderWeakRefs defaultInstance = new ReachableFinderWeakRefs();
+
+ @SuppressWarnings("unchecked")
+ public int visit(PyObject object, Object arg) {
+ if (isTraversable(object)) {
+ IdentityHashMap<PyObject, WeakReferenceGC>[] pools =
+ (IdentityHashMap<PyObject, WeakReferenceGC>[]) arg;
+ WeakReferenceGC ref = pools[0].get(object);
+ if (ref == null) {
+ ref = new WeakReferenceGC(object);
+ pools[1].put(object, ref);
+ }
+ }
+ return 0;
+ }
+ }
+
+ static class ReferrerFinder implements Visitproc {
+ public static ReferrerFinder defaultInstance = new ReferrerFinder();
+
+ /**
+ * Expects {@code arg} to be a 2-component array ({@code PyObject[]})
+ * consisting of the {@code PyObject} to be referred to at
+ * {@code arg[0]} and the destination list (a list-like {@code PyObject}
+ * where the referrers will be inserted) at {@code arg[1]}.
+ */
+ public int visit(PyObject object, Object arg) {
+ if (((PyObject[]) arg)[0].__eq__(object).__nonzero__()) {
+ ((org.python.core.PySequenceList) ((PyObject[]) arg)[1]).pyadd(object);
+ }
+ return 0;
+ }
+ }
+
+ /**
+ * Like {@code RefInListFinder} this visitproc looks whether the traversed object
+ * refers to one of the objects in a given set. Here we perform fail-fast
+ * behavior. This method is useful if one is not interested in the referrers,
+ * but only wants to know (quickly) whether a connection exists or not.
+ */
+ static class RefersToSetFinder implements Visitproc {
+ public static RefersToSetFinder defaultInstance = new RefersToSetFinder();
+
+ @SuppressWarnings("unchecked")
+ public int visit(PyObject object, Object arg) {
+ return ((Set<PyObject>) arg).contains(object) ? 1 : 0;
+ }
+ }
+
+ /**
+ * This visitproc looks whether an object refers to one of the objects in
+ * a given set.<br>
+ * {@code arg} must be a 2-component-array of
+ * {@code HashMap<Object, WeakReferenceGC>}.
+ * These maps are actually used as sets, but resolve the strongref/weakref
+ * views to the objects.<br>
+ * {@code arg[0]} is the pool we search referrers for. When the traverse method
+ * iterates through the referents of a source object, this visitproc checks
+ * for each referent, whether it is in {@code arg[0]}. If it is, then it is added
+ * to {@code arg[1]} (no double entries here since it is a set-like structure)
+ * and {@code found} is set to {@code true}.<br>
+ * By repeated use one can collect all objects referring to a given set
+ * of objects in another set.
+ */
+ static class RefInListFinder implements Visitproc {
+ public static RefInListFinder defaultInstance = new RefInListFinder();
+ public boolean found = false;
+
+ /**
+ * Expects {@code arg} to be a 2-component array of
+ * {@link java.util.Map}s.
+ */
+ public int visit(PyObject object, Object arg) {
+ @SuppressWarnings("unchecked")
+ IdentityHashMap<PyObject, WeakReferenceGC>[] pools =
+ (IdentityHashMap<PyObject, WeakReferenceGC>[]) arg;
+ WeakReferenceGC ref = pools[0].get(object);
+ if (ref != null) {
+ pools[1].put(object, ref);
+ found = true;
+ }
+ return 0;
+ }
+ }
+
+ static class ObjectInListFinder implements Visitproc {
+ public static ObjectInListFinder defaultInstance = new ObjectInListFinder();
+ public boolean found = false;
+
+ /**
+ * Expects {@code arg} to be a 2-component array of
+ * {@link java.util.Map}s.
+ */
+ public int visit(PyObject object, Object arg) {
+ @SuppressWarnings("unchecked")
+ IdentityHashMap<PyObject, PyObject>[] pools =
+ (IdentityHashMap<PyObject, PyObject>[]) arg;
+ if (pools[0].containsKey(object)) {
+ pools[1].put(object, object);
+ found = true;
+ }
+ return 0;
+ }
+ }
+ //----------end of Visitproc section---------------------------------------
+}
diff --git a/src/org/python/modules/itertools/PyTeeIterator.java b/src/org/python/modules/itertools/PyTeeIterator.java
--- a/src/org/python/modules/itertools/PyTeeIterator.java
+++ b/src/org/python/modules/itertools/PyTeeIterator.java
@@ -8,6 +8,7 @@
import org.python.core.PyNewWrapper;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -140,4 +141,50 @@
public final PyTeeIterator tee___copy__() {
return new PyTeeIterator(teeData);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (teeData != null) {
+ if (teeData.iterator != null) {
+ retVal = visit.visit(teeData.iterator, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (teeData.buffer != null) {
+ for (PyObject ob: teeData.buffer.values()) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ if (teeData.stopException != null) {
+ retVal = teeData.stopException.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ if (ob == null) {
+ return false;
+ } else if (super.refersDirectlyTo(ob)) {
+ return true;
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ }
}
diff --git a/src/org/python/modules/itertools/PyTeeIteratorDerived.java b/src/org/python/modules/itertools/PyTeeIteratorDerived.java
--- a/src/org/python/modules/itertools/PyTeeIteratorDerived.java
+++ b/src/org/python/modules/itertools/PyTeeIteratorDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyTeeIteratorDerived extends PyTeeIterator implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyTeeIteratorDerived extends PyTeeIterator implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/chain.java b/src/org/python/modules/itertools/chain.java
--- a/src/org/python/modules/itertools/chain.java
+++ b/src/org/python/modules/itertools/chain.java
@@ -6,6 +6,7 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedClassMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedMethod;
@@ -90,4 +91,19 @@
return doNext(__iternext__());
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/chainDerived.java b/src/org/python/modules/itertools/chainDerived.java
--- a/src/org/python/modules/itertools/chainDerived.java
+++ b/src/org/python/modules/itertools/chainDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class chainDerived extends chain implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class chainDerived extends chain implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/combinations.java b/src/org/python/modules/itertools/combinations.java
--- a/src/org/python/modules/itertools/combinations.java
+++ b/src/org/python/modules/itertools/combinations.java
@@ -6,6 +6,7 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -90,4 +91,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/combinationsDerived.java b/src/org/python/modules/itertools/combinationsDerived.java
--- a/src/org/python/modules/itertools/combinationsDerived.java
+++ b/src/org/python/modules/itertools/combinationsDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class combinationsDerived extends combinations implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class combinationsDerived extends combinations implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/combinationsWithReplacement.java b/src/org/python/modules/itertools/combinationsWithReplacement.java
--- a/src/org/python/modules/itertools/combinationsWithReplacement.java
+++ b/src/org/python/modules/itertools/combinationsWithReplacement.java
@@ -7,6 +7,7 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -93,4 +94,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/combinationsWithReplacementDerived.java b/src/org/python/modules/itertools/combinationsWithReplacementDerived.java
--- a/src/org/python/modules/itertools/combinationsWithReplacementDerived.java
+++ b/src/org/python/modules/itertools/combinationsWithReplacementDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class combinationsWithReplacementDerived extends combinationsWithReplacement implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class combinationsWithReplacementDerived extends combinationsWithReplacement implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/compress.java b/src/org/python/modules/itertools/compress.java
--- a/src/org/python/modules/itertools/compress.java
+++ b/src/org/python/modules/itertools/compress.java
@@ -6,6 +6,7 @@
import org.python.core.PyIterator;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -77,4 +78,19 @@
return doNext(__iternext__());
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/compressDerived.java b/src/org/python/modules/itertools/compressDerived.java
--- a/src/org/python/modules/itertools/compressDerived.java
+++ b/src/org/python/modules/itertools/compressDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class compressDerived extends compress implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class compressDerived extends compress implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/count.java b/src/org/python/modules/itertools/count.java
--- a/src/org/python/modules/itertools/count.java
+++ b/src/org/python/modules/itertools/count.java
@@ -11,6 +11,7 @@
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.__builtin__;
+import org.python.core.Visitproc;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
@@ -158,4 +159,35 @@
return doNext(__iternext__());
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (iter != null) {
+ retVal = visit.visit(iter, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (counter != null) {
+ retVal = visit.visit(counter, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (stepper != null) {
+ retVal = visit.visit(stepper, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return super.traverse(visit, arg);
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || counter == ob
+ || stepper == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/countDerived.java b/src/org/python/modules/itertools/countDerived.java
--- a/src/org/python/modules/itertools/countDerived.java
+++ b/src/org/python/modules/itertools/countDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class countDerived extends count implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class countDerived extends count implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/cycle.java b/src/org/python/modules/itertools/cycle.java
--- a/src/org/python/modules/itertools/cycle.java
+++ b/src/org/python/modules/itertools/cycle.java
@@ -4,6 +4,7 @@
import org.python.core.PyIterator;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -90,5 +91,20 @@
return doNext(__iternext__());
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/cycleDerived.java b/src/org/python/modules/itertools/cycleDerived.java
--- a/src/org/python/modules/itertools/cycleDerived.java
+++ b/src/org/python/modules/itertools/cycleDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class cycleDerived extends cycle implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class cycleDerived extends cycle implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/dropwhile.java b/src/org/python/modules/itertools/dropwhile.java
--- a/src/org/python/modules/itertools/dropwhile.java
+++ b/src/org/python/modules/itertools/dropwhile.java
@@ -5,6 +5,7 @@
import org.python.core.PyIterator;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -60,4 +61,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/dropwhileDerived.java b/src/org/python/modules/itertools/dropwhileDerived.java
--- a/src/org/python/modules/itertools/dropwhileDerived.java
+++ b/src/org/python/modules/itertools/dropwhileDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class dropwhileDerived extends dropwhile implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class dropwhileDerived extends dropwhile implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/groupby.java b/src/org/python/modules/itertools/groupby.java
--- a/src/org/python/modules/itertools/groupby.java
+++ b/src/org/python/modules/itertools/groupby.java
@@ -8,6 +8,7 @@
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.PyXRange;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -118,4 +119,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/groupbyDerived.java b/src/org/python/modules/itertools/groupbyDerived.java
--- a/src/org/python/modules/itertools/groupbyDerived.java
+++ b/src/org/python/modules/itertools/groupbyDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class groupbyDerived extends groupby implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class groupbyDerived extends groupby implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/ifilter.java b/src/org/python/modules/itertools/ifilter.java
--- a/src/org/python/modules/itertools/ifilter.java
+++ b/src/org/python/modules/itertools/ifilter.java
@@ -5,6 +5,7 @@
import org.python.core.PyIterator;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
@@ -62,4 +63,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/ifilterDerived.java b/src/org/python/modules/itertools/ifilterDerived.java
--- a/src/org/python/modules/itertools/ifilterDerived.java
+++ b/src/org/python/modules/itertools/ifilterDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ifilterDerived extends ifilter implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ifilterDerived extends ifilter implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/ifilterfalse.java b/src/org/python/modules/itertools/ifilterfalse.java
--- a/src/org/python/modules/itertools/ifilterfalse.java
+++ b/src/org/python/modules/itertools/ifilterfalse.java
@@ -4,6 +4,7 @@
import org.python.core.PyIterator;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
@@ -61,4 +62,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/ifilterfalseDerived.java b/src/org/python/modules/itertools/ifilterfalseDerived.java
--- a/src/org/python/modules/itertools/ifilterfalseDerived.java
+++ b/src/org/python/modules/itertools/ifilterfalseDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class ifilterfalseDerived extends ifilterfalse implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class ifilterfalseDerived extends ifilterfalse implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/imap.java b/src/org/python/modules/itertools/imap.java
--- a/src/org/python/modules/itertools/imap.java
+++ b/src/org/python/modules/itertools/imap.java
@@ -6,6 +6,7 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
@@ -103,4 +104,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/islice.java b/src/org/python/modules/itertools/islice.java
--- a/src/org/python/modules/itertools/islice.java
+++ b/src/org/python/modules/itertools/islice.java
@@ -7,6 +7,7 @@
import org.python.core.PyNone;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -136,4 +137,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/isliceDerived.java b/src/org/python/modules/itertools/isliceDerived.java
--- a/src/org/python/modules/itertools/isliceDerived.java
+++ b/src/org/python/modules/itertools/isliceDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class isliceDerived extends islice implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class isliceDerived extends islice implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/itertools.java b/src/org/python/modules/itertools/itertools.java
--- a/src/org/python/modules/itertools/itertools.java
+++ b/src/org/python/modules/itertools/itertools.java
@@ -9,6 +9,7 @@
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyTuple;
+import org.python.core.Visitproc;
/**
* Functional tools for creating and using iterators. Java implementation of the CPython module
@@ -160,6 +161,29 @@
}
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (iterator != null) {
+ retVal = visit.visit(iterator, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return predicate != null ? visit.visit(predicate, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == iterator || ob == predicate ||
+ super.refersDirectlyTo(ob));
+ }
}
/**
@@ -210,6 +234,29 @@
}
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (iterator != null) {
+ retVal = visit.visit(iterator, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return predicate != null ? visit.visit(predicate, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == iterator || ob == predicate ||
+ super.refersDirectlyTo(ob));
+ }
}
public static PyString __doc__tee = new PyString(
diff --git a/src/org/python/modules/itertools/izip.java b/src/org/python/modules/itertools/izip.java
--- a/src/org/python/modules/itertools/izip.java
+++ b/src/org/python/modules/itertools/izip.java
@@ -7,6 +7,7 @@
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.PyXRange;
+import org.python.core.Visitproc;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
@@ -110,4 +111,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/izipDerived.java b/src/org/python/modules/itertools/izipDerived.java
--- a/src/org/python/modules/itertools/izipDerived.java
+++ b/src/org/python/modules/itertools/izipDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class izipDerived extends izip implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class izipDerived extends izip implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/izipLongest.java b/src/org/python/modules/itertools/izipLongest.java
--- a/src/org/python/modules/itertools/izipLongest.java
+++ b/src/org/python/modules/itertools/izipLongest.java
@@ -6,6 +6,7 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -109,4 +110,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/izipLongestDerived.java b/src/org/python/modules/itertools/izipLongestDerived.java
--- a/src/org/python/modules/itertools/izipLongestDerived.java
+++ b/src/org/python/modules/itertools/izipLongestDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class izipLongestDerived extends izipLongest implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class izipLongestDerived extends izipLongest implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/permutations.java b/src/org/python/modules/itertools/permutations.java
--- a/src/org/python/modules/itertools/permutations.java
+++ b/src/org/python/modules/itertools/permutations.java
@@ -7,6 +7,7 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -111,4 +112,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/permutationsDerived.java b/src/org/python/modules/itertools/permutationsDerived.java
--- a/src/org/python/modules/itertools/permutationsDerived.java
+++ b/src/org/python/modules/itertools/permutationsDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class permutationsDerived extends permutations implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class permutationsDerived extends permutations implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/product.java b/src/org/python/modules/itertools/product.java
--- a/src/org/python/modules/itertools/product.java
+++ b/src/org/python/modules/itertools/product.java
@@ -6,6 +6,7 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -119,4 +120,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/productDerived.java b/src/org/python/modules/itertools/productDerived.java
--- a/src/org/python/modules/itertools/productDerived.java
+++ b/src/org/python/modules/itertools/productDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class productDerived extends product implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class productDerived extends product implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/repeat.java b/src/org/python/modules/itertools/repeat.java
--- a/src/org/python/modules/itertools/repeat.java
+++ b/src/org/python/modules/itertools/repeat.java
@@ -8,6 +8,7 @@
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -130,4 +131,26 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (object != null) {
+ retVal = visit.visit(object, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || object == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/repeatDerived.java b/src/org/python/modules/itertools/repeatDerived.java
--- a/src/org/python/modules/itertools/repeatDerived.java
+++ b/src/org/python/modules/itertools/repeatDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class repeatDerived extends repeat implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class repeatDerived extends repeat implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/starmap.java b/src/org/python/modules/itertools/starmap.java
--- a/src/org/python/modules/itertools/starmap.java
+++ b/src/org/python/modules/itertools/starmap.java
@@ -6,6 +6,7 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -82,4 +83,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/starmapDerived.java b/src/org/python/modules/itertools/starmapDerived.java
--- a/src/org/python/modules/itertools/starmapDerived.java
+++ b/src/org/python/modules/itertools/starmapDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class starmapDerived extends starmap implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class starmapDerived extends starmap implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/itertools/takewhile.java b/src/org/python/modules/itertools/takewhile.java
--- a/src/org/python/modules/itertools/takewhile.java
+++ b/src/org/python/modules/itertools/takewhile.java
@@ -5,6 +5,7 @@
import org.python.core.PyIterator;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -60,4 +61,20 @@
public PyObject next() {
return doNext(__iternext__());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return iter != null ? visit.visit(iter, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (iter == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/itertools/takewhileDerived.java b/src/org/python/modules/itertools/takewhileDerived.java
--- a/src/org/python/modules/itertools/takewhileDerived.java
+++ b/src/org/python/modules/itertools/takewhileDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class takewhileDerived extends takewhile implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class takewhileDerived extends takewhile implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/jffi/ArrayCData.java b/src/org/python/modules/jffi/ArrayCData.java
--- a/src/org/python/modules/jffi/ArrayCData.java
+++ b/src/org/python/modules/jffi/ArrayCData.java
@@ -9,6 +9,7 @@
import org.python.core.PySequenceList;
import org.python.core.PyType;
import org.python.core.SequenceIndexDelegate;
+import org.python.core.Visitproc;
import org.python.expose.ExposedClassMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -172,4 +173,19 @@
}
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ return componentType != null ? visit.visit(componentType, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (componentType == ob || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/jffi/ByReference.java b/src/org/python/modules/jffi/ByReference.java
--- a/src/org/python/modules/jffi/ByReference.java
+++ b/src/org/python/modules/jffi/ByReference.java
@@ -3,8 +3,10 @@
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Untraversable;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "jffi.ByReference", base = PyObject.class)
public final class ByReference extends PyObject implements Pointer {
public static final PyType TYPE = PyType.fromClass(ByReference.class);
diff --git a/src/org/python/modules/jffi/CData.java b/src/org/python/modules/jffi/CData.java
--- a/src/org/python/modules/jffi/CData.java
+++ b/src/org/python/modules/jffi/CData.java
@@ -4,11 +4,13 @@
import org.python.core.Py;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
@ExposedType(name = "jffi.CData", base = PyObject.class)
-public abstract class CData extends PyObject {
+public abstract class CData extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(CData.class);
private final CType ctype;
@@ -106,4 +108,16 @@
return sym.getMemory();
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return ctype != null ? visit.visit(ctype, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == ctype;
+ }
}
diff --git a/src/org/python/modules/jffi/DynamicLibrary.java b/src/org/python/modules/jffi/DynamicLibrary.java
--- a/src/org/python/modules/jffi/DynamicLibrary.java
+++ b/src/org/python/modules/jffi/DynamicLibrary.java
@@ -5,11 +5,13 @@
import org.python.core.Py;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Untraversable;
import org.python.expose.ExposeAsSuperclass;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "jffi.DynamicLibrary", base = PyObject.class)
public class DynamicLibrary extends PyObject {
diff --git a/src/org/python/modules/jffi/StructLayout.java b/src/org/python/modules/jffi/StructLayout.java
--- a/src/org/python/modules/jffi/StructLayout.java
+++ b/src/org/python/modules/jffi/StructLayout.java
@@ -12,6 +12,8 @@
import org.python.core.PyNewWrapper;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -40,7 +42,7 @@
}
@ExposedType(name = "jffi.StructLayout.Field", base = PyObject.class)
- public static class Field extends PyObject {
+ public static class Field extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(Field.class);
@ExposedGet
final CType ctype;
@@ -104,6 +106,24 @@
return value;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (name != null) {
+ int retVal = visit.visit(name, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return ctype != null ? visit.visit(ctype, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == name || ob == ctype);
+ }
}
/**
diff --git a/src/org/python/modules/operator.java b/src/org/python/modules/operator.java
--- a/src/org/python/modules/operator.java
+++ b/src/org/python/modules/operator.java
@@ -6,18 +6,21 @@
import org.python.core.Py;
import org.python.core.PyBuiltinFunctionSet;
import org.python.core.PyIgnoreMethodTag;
-import org.python.core.PyMethod;
import org.python.core.PyNewWrapper;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.PyUnicode;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
+import org.python.core.Untraversable;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
+ at Untraversable
class OperatorFunctions extends PyBuiltinFunctionSet
{
public OperatorFunctions(String name, int index, int argcount) {
@@ -117,6 +120,7 @@
}
}
+ at Untraversable
public class operator extends PyObject implements ClassDictInit
{
public static PyString __doc__ = new PyString(
@@ -274,7 +278,7 @@
* The attrgetter type.
*/
@ExposedType(name = "operator.attrgetter", isBaseType = false)
- static class PyAttrGetter extends PyObject {
+ static class PyAttrGetter extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyAttrGetter.class);
@@ -327,13 +331,43 @@
return obj;
}
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (attrs != null) {
+ int retVal;
+ for (PyObject ob: attrs) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null || attrs == null) {
+ return false;
+ }
+ for (PyObject obj: attrs) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ return false;
+ }
}
/**
* The itemgetter type.
*/
@ExposedType(name = "operator.itemgetter", isBaseType = false)
- static class PyItemGetter extends PyObject {
+ static class PyItemGetter extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyItemGetter.class);
@@ -373,13 +407,44 @@
}
return new PyTuple(result);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (items != null) {
+ int retVal;
+ for (PyObject ob: items) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null || items == null) {
+ return false;
+ }
+ for (PyObject obj: items) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ return false;
+ }
}
/**
* The methodcaller type.
*/
@ExposedType(name = "operator.methodcaller", isBaseType = false)
- static class PyMethodCaller extends PyObject {
+ static class PyMethodCaller extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyMethodCaller.class);
@@ -429,6 +494,37 @@
PyObject obj = ap.getPyObject(0);
return obj.invoke(name, this.args, this.keywords);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (args != null) {
+ int retVal;
+ for (PyObject ob: args) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ if (ob == null || args == null) {
+ return false;
+ }
+ for (PyObject obj: args) {
+ if (obj == ob) {
+ return true;
+ }
+ }
+ return false;
+ }
}
private static String ensureStringAttribute(PyObject name) {
diff --git a/src/org/python/modules/posix/PosixModule.java b/src/org/python/modules/posix/PosixModule.java
--- a/src/org/python/modules/posix/PosixModule.java
+++ b/src/org/python/modules/posix/PosixModule.java
@@ -48,6 +48,7 @@
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.imp;
+import org.python.core.Untraversable;
import org.python.core.io.FileIO;
import org.python.core.io.IOBase;
import org.python.core.io.RawIOBase;
@@ -161,6 +162,7 @@
intFD = fd;
javaFD = null;
}
+
FDUnion(FileDescriptor fd) {
intFD = -1;
javaFD = fd;
@@ -1138,6 +1140,7 @@
}
}
+ @Untraversable
static class LstatFunction extends PyBuiltinFunctionNarrow {
LstatFunction() {
super("lstat", 1, 1,
@@ -1171,6 +1174,7 @@
}
}
+ @Untraversable
static class StatFunction extends PyBuiltinFunctionNarrow {
StatFunction() {
super("stat", 1, 1,
@@ -1200,6 +1204,7 @@
// daylight savings time in timestamps.
//
// Another advantage is setting the st_mode the same as CPython would return.
+ @Untraversable
static class WindowsStatFunction extends PyBuiltinFunctionNarrow {
WindowsStatFunction() {
super("stat", 1, 1,
@@ -1252,6 +1257,7 @@
}
}
+ @Untraversable
static class FstatFunction extends PyBuiltinFunctionNarrow {
FstatFunction() {
super("fstat", 1, 1,
diff --git a/src/org/python/modules/posix/PyStatResult.java b/src/org/python/modules/posix/PyStatResult.java
--- a/src/org/python/modules/posix/PyStatResult.java
+++ b/src/org/python/modules/posix/PyStatResult.java
@@ -11,6 +11,7 @@
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
@@ -241,4 +242,76 @@
"st_mode=%r, st_ino=%r, st_dev=%r, st_nlink=%r, st_uid=%r, "+
"st_gid=%r, st_size=%r, st_atime=%r, st_mtime=%r, st_ctime=%r)").__mod__(this);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (st_mode != null) {
+ retVal = visit.visit(st_mode, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (st_ino != null) {
+ retVal = visit.visit(st_ino, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (st_dev != null) {
+ retVal = visit.visit(st_dev, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (st_nlink != null) {
+ retVal = visit.visit(st_nlink, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (st_uid != null) {
+ retVal = visit.visit(st_uid, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (st_gid != null) {
+ retVal = visit.visit(st_gid, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (st_size != null) {
+ retVal = visit.visit(st_size, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (st_atime != null) {
+ retVal = visit.visit(st_atime, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (st_mtime != null) {
+ retVal = visit.visit(st_mtime, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return st_ctime != null ? visit.visit(st_ctime, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == st_mode || ob == st_ino || ob == st_dev || ob == st_nlink
+ || ob == st_uid || ob == st_gid || ob == st_size || ob == st_atime
+ || ob == st_mtime || ob == st_ctime || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/random/PyRandom.java b/src/org/python/modules/random/PyRandom.java
--- a/src/org/python/modules/random/PyRandom.java
+++ b/src/org/python/modules/random/PyRandom.java
@@ -15,10 +15,12 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Untraversable;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
+ at Untraversable
@ExposedType(name = "_random.Random")
public class PyRandom extends PyObject {
diff --git a/src/org/python/modules/random/PyRandomDerived.java b/src/org/python/modules/random/PyRandomDerived.java
--- a/src/org/python/modules/random/PyRandomDerived.java
+++ b/src/org/python/modules/random/PyRandomDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyRandomDerived extends PyRandom implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyRandomDerived extends PyRandom implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/sre/MatchObject.java b/src/org/python/modules/sre/MatchObject.java
--- a/src/org/python/modules/sre/MatchObject.java
+++ b/src/org/python/modules/sre/MatchObject.java
@@ -22,10 +22,12 @@
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyTuple;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.core.imp;
-public class MatchObject extends PyObject {
+public class MatchObject extends PyObject implements Traverseproc {
public PyString string; /* link to the target string */
public PyObject regs; /* cached list of matching spans */
PatternObject pattern; /* link to the regex (pattern) object */
@@ -206,4 +208,29 @@
}
return super.__findattr_ex__(key);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (pattern != null) {
+ retVal = visit.visit(pattern, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (string != null) {
+ retVal = visit.visit(string, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return regs != null ? visit.visit(regs, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == pattern || ob == string || ob == regs);
+ }
}
diff --git a/src/org/python/modules/sre/PatternObject.java b/src/org/python/modules/sre/PatternObject.java
--- a/src/org/python/modules/sre/PatternObject.java
+++ b/src/org/python/modules/sre/PatternObject.java
@@ -20,7 +20,7 @@
import org.python.core.*;
import org.python.core.util.StringUtil;
-public class PatternObject extends PyObject {
+public class PatternObject extends PyObject implements Traverseproc {
int[] code; /* link to the code string object */
public PyString pattern; /* link to the pattern source (or None) */
public int groups;
@@ -382,4 +382,29 @@
// Neither of those things worked
throw Py.TypeError("expected string or buffer, but got " + obj.getType());
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (pattern != null) {
+ retVal = visit.visit(pattern, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (groupindex != null) {
+ retVal = visit.visit(groupindex, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return indexgroup != null ? visit.visit(indexgroup, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == pattern || ob == groupindex || ob == indexgroup);
+ }
}
diff --git a/src/org/python/modules/sre/ScannerObject.java b/src/org/python/modules/sre/ScannerObject.java
--- a/src/org/python/modules/sre/ScannerObject.java
+++ b/src/org/python/modules/sre/ScannerObject.java
@@ -17,7 +17,7 @@
import org.python.core.*;
-public class ScannerObject extends PyObject {
+public class ScannerObject extends PyObject implements Traverseproc {
public PatternObject pattern;
PyString string;
SRE_STATE state;
@@ -52,8 +52,22 @@
return match;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ if (pattern != null) {
+ int retVal = visit.visit(pattern, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return string != null ? visit.visit(string, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == pattern || ob == string);
+ }
}
-
-
-
-
diff --git a/src/org/python/modules/synchronize.java b/src/org/python/modules/synchronize.java
--- a/src/org/python/modules/synchronize.java
+++ b/src/org/python/modules/synchronize.java
@@ -9,6 +9,9 @@
import org.python.core.PyObject;
import org.python.core.PyMethod;
import org.python.core.Py;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
+
public class synchronize {
@@ -34,7 +37,7 @@
return new SynchronizedCallable(callable);
}
- public static class SynchronizedCallable extends PyObject {
+ public static class SynchronizedCallable extends PyObject implements Traverseproc {
PyObject callable;
@@ -94,5 +97,17 @@
public boolean isCallable() {
return true;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ return callable != null ? visit.visit(callable, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && ob == callable;
+ }
}
}
diff --git a/src/org/python/modules/thread/PyLocal.java b/src/org/python/modules/thread/PyLocal.java
--- a/src/org/python/modules/thread/PyLocal.java
+++ b/src/org/python/modules/thread/PyLocal.java
@@ -6,13 +6,15 @@
import org.python.core.PyNewWrapper;
import org.python.core.PyObject;
import org.python.core.PyType;
+import org.python.core.Traverseproc;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedSet;
import org.python.expose.ExposedType;
@ExposedType(name = "thread._local")
-public class PyLocal extends PyObject {
+public class PyLocal extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(PyLocal.class);
@@ -85,4 +87,57 @@
}
return ldict;
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal;
+ if (args != null) {
+ for (PyObject ob: args) {
+ if (ob != null) {
+ retVal = visit.visit(ob, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+
+ }
+ }
+ Object[] ob0 = tdict.get();
+ if (ob0 != null) {
+ for (Object obj: ob0) {
+ if (obj != null) {
+ if (obj instanceof PyObject) {
+ retVal = visit.visit((PyObject) obj, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ } else if (obj instanceof Traverseproc) {
+ retVal = ((Traverseproc) obj).traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
+ if (ob == null) {
+ return false;
+ }
+ if (args != null) {
+ for (PyObject obj: args) {
+ if (obj == ob) {
+ return true;
+ }
+
+ }
+ }
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/src/org/python/modules/thread/PyLocalDerived.java b/src/org/python/modules/thread/PyLocalDerived.java
--- a/src/org/python/modules/thread/PyLocalDerived.java
+++ b/src/org/python/modules/thread/PyLocalDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class PyLocalDerived extends PyLocal implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class PyLocalDerived extends PyLocal implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,17 +27,35 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
public PyLocalDerived(PyType subtype) {
super(subtype);
slots=new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return 0;
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/org/python/modules/thread/PyLock.java b/src/org/python/modules/thread/PyLock.java
--- a/src/org/python/modules/thread/PyLock.java
+++ b/src/org/python/modules/thread/PyLock.java
@@ -1,8 +1,14 @@
// Copyright (c) Corporation for National Research Initiatives
package org.python.modules.thread;
-import org.python.core.*;
+import org.python.core.PyObject;
+import org.python.core.ContextManager;
+import org.python.core.Py;
+import org.python.core.ThreadState;
+import org.python.core.PyException;
+import org.python.core.Untraversable;
+ at Untraversable
public class PyLock extends PyObject implements ContextManager {
private boolean locked = false;
diff --git a/src/org/python/modules/time/PyTimeTuple.java b/src/org/python/modules/time/PyTimeTuple.java
--- a/src/org/python/modules/time/PyTimeTuple.java
+++ b/src/org/python/modules/time/PyTimeTuple.java
@@ -8,6 +8,7 @@
import org.python.core.PyObject;
import org.python.core.PyTuple;
import org.python.core.PyType;
+import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -123,4 +124,70 @@
return String.format("time.struct_time(tm_year=%s, tm_mon=%s, tm_mday=%s, tm_hour=%s, tm_min=%s, tm_sec=%s, tm_wday=%s, tm_yday=%s, tm_isdst=%s)",
tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst);
}
+
+
+ /* Traverseproc implementation */
+ @Override
+ public int traverse(Visitproc visit, Object arg) {
+ int retVal = super.traverse(visit, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ if (tm_year != null) {
+ retVal = visit.visit(tm_year, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (tm_mon != null) {
+ retVal = visit.visit(tm_mon, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (tm_mday != null) {
+ retVal = visit.visit(tm_mday, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (tm_hour != null) {
+ retVal = visit.visit(tm_hour, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (tm_min != null) {
+ retVal = visit.visit(tm_min, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (tm_sec != null) {
+ retVal = visit.visit(tm_sec, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (tm_wday != null) {
+ retVal = visit.visit(tm_wday, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ if (tm_yday != null) {
+ retVal = visit.visit(tm_yday, arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return tm_isdst != null ? visit.visit(tm_isdst, arg) : 0;
+ }
+
+ @Override
+ public boolean refersDirectlyTo(PyObject ob) {
+ return ob != null && (ob == tm_year || ob == tm_mon || ob == tm_mday
+ || ob == tm_hour || ob == tm_min || ob == tm_sec || ob == tm_wday
+ || ob == tm_yday || ob == tm_isdst || super.refersDirectlyTo(ob));
+ }
}
diff --git a/src/org/python/modules/time/Time.java b/src/org/python/modules/time/Time.java
--- a/src/org/python/modules/time/Time.java
+++ b/src/org/python/modules/time/Time.java
@@ -13,17 +13,12 @@
package org.python.modules.time;
import java.text.DateFormatSymbols;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
-import java.util.HashMap;
-import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
import org.python.core.ClassDictInit;
import org.python.core.Py;
@@ -31,11 +26,12 @@
import org.python.core.PyException;
import org.python.core.PyInteger;
import org.python.core.PyObject;
-import org.python.core.PySequence;
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.__builtin__;
+import org.python.core.Untraversable;
+ at Untraversable
class TimeFunctions extends PyBuiltinFunctionSet
{
public TimeFunctions(String name, int index, int argcount) {
@@ -56,7 +52,7 @@
public class Time implements ClassDictInit
{
- public static PyString __doc__ = new PyString(
+ public static final PyString __doc__ = new PyString(
"This module provides various functions to manipulate time values.\n"+
"\n"+
"There are two standard representations of time. One is the "+
diff --git a/src/org/python/modules/zipimport/zipimporterDerived.java b/src/org/python/modules/zipimport/zipimporterDerived.java
--- a/src/org/python/modules/zipimport/zipimporterDerived.java
+++ b/src/org/python/modules/zipimport/zipimporterDerived.java
@@ -6,9 +6,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
-public class zipimporterDerived extends zipimporter implements Slotted,FinalizablePyObjectDerived {
-
- public FinalizeTrigger finalizeTrigger;
+public class zipimporterDerived extends zipimporter implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +27,23 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i<slots.length;++i) {
+ retVal=visit.visit(slots[i],arg);
+ if (retVal!=0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit,arg);
+ }
+
+ /* end of TraverseprocDerived implementation */
+
private PyObject dict;
public PyObject fastGetDict() {
@@ -45,8 +57,8 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
dict=newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&finalizeTrigger==null) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__"))!=null&&!JyAttribute.hasAttr(this,JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
} else {
throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
@@ -63,10 +75,14 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit,Object arg) {
+ return visit.visit(dict,arg);
+ }
+
public PyString __str__() {
PyType self_type=getType();
PyObject impl=self_type.lookup("__str__");
diff --git a/src/templates/dict.derived b/src/templates/dict.derived
--- a/src/templates/dict.derived
+++ b/src/templates/dict.derived
@@ -9,6 +9,6 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
diff --git a/src/templates/gderived-defs b/src/templates/gderived-defs
--- a/src/templates/gderived-defs
+++ b/src/templates/gderived-defs
@@ -7,8 +7,7 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.core.finalization.FinalizablePyObjectDerived;
- public class `concat`(`base,Derived) extends `base implements Slotted, FinalizablePyObjectDerived {
- public FinalizeTrigger finalizeTrigger;
+ public class `concat`(`base,Derived) extends `base implements Slotted, FinalizablePyObjectDerived, TraverseprocDerived {
public PyObject getSlot(int index) {
return slots[index];
@@ -29,9 +28,22 @@
}
public void __ensure_finalizer__() {
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit, Object arg) {
+ int retVal;
+ for (int i = 0; i < slots.length; ++i) {
+ retVal = visit.visit(slots[i], arg);
+ if (retVal != 0) {
+ return retVal;
+ }
+ }
+ return traverseDictIfAny(visit, arg);
+ }
+ /* end of TraverseprocDerived implementation */
+
`decls;
}
define: (ClassBodyDeclarations)pair
@@ -96,8 +108,9 @@
public void setDict(PyObject newDict) {
if (newDict instanceof PyStringMap || newDict instanceof PyDictionary ) {
dict = newDict;
- if (dict.__finditem__(PyString.fromInterned("__del__")) != null && finalizeTrigger == null) {
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ if (dict.__finditem__(PyString.fromInterned("__del__")) != null &&
+ !JyAttribute.hasAttr(this, JyAttribute.FINALIZE_TRIGGER_ATTR)) {
+ FinalizeTrigger.ensureFinalizer(this);
}
}
else {
@@ -115,20 +128,28 @@
super(subtype,`extra);
slots = new PyObject[subtype.getNumSlots()];
if (subtype.needsFinalizer()) {
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit, Object arg) {
+ return 0;
+ }
+
define: (ClassBodyDeclarations)ctr_userdict
public `concat`(`base,Derived)(PyType subtype,`extraargs) {
super(subtype,`extra);
slots = new PyObject[subtype.getNumSlots()];
dict = subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger = FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
+ public int traverseDictIfAny(Visitproc visit, Object arg) {
+ return visit.visit(dict, arg);
+ }
+
define: (ClassBodyDeclarations)toString
public String toString() {
PyType self_type = getType();
diff --git a/src/templates/set.derived b/src/templates/set.derived
--- a/src/templates/set.derived
+++ b/src/templates/set.derived
@@ -9,7 +9,7 @@
slots=new PyObject[subtype.getNumSlots()];
dict=subtype.instDict();
if (subtype.needsFinalizer()) {
- finalizeTrigger=FinalizeTrigger.makeTrigger(this);
+ FinalizeTrigger.ensureFinalizer(this);
}
}
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list