Reverse finalizer
This commit is contained in:
parent
5fc5ba2e66
commit
371e940c83
7 changed files with 41 additions and 111 deletions
|
|
@ -6,9 +6,7 @@ __version__ = '0.9.1'
|
||||||
|
|
||||||
|
|
||||||
from weakref import WeakValueDictionary
|
from weakref import WeakValueDictionary
|
||||||
from llvm._utils.finalizer import track as track_resource
|
import _core
|
||||||
from llvm._utils.finalizer import OwnerMixin as _OwnerMixin
|
|
||||||
from llvm import _core
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# LLVM Version
|
# LLVM Version
|
||||||
|
|
@ -33,26 +31,11 @@ class LLVMException(Exception):
|
||||||
Exception.__init__(self, msg)
|
Exception.__init__(self, msg)
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
|
||||||
# Resource Handle
|
|
||||||
#===----------------------------------------------------------------------===
|
|
||||||
|
|
||||||
class Handle(_OwnerMixin):
|
|
||||||
_finalizer = NotImplemented
|
|
||||||
|
|
||||||
def __init__(self, ptr):
|
|
||||||
self.ptr = ptr
|
|
||||||
self._finalizer_track(self.ptr)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _finalize(cls, ptr):
|
|
||||||
cls._finalizer(ptr)
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Ownables
|
# Ownables
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class Ownable(Handle):
|
class Ownable(object):
|
||||||
"""Objects that can be owned.
|
"""Objects that can be owned.
|
||||||
|
|
||||||
Modules and Module Providers can be owned, i.e., the responsibility of
|
Modules and Module Providers can be owned, i.e., the responsibility of
|
||||||
|
|
@ -61,21 +44,25 @@ class Ownable(Handle):
|
||||||
is NOT intended for public use.
|
is NOT intended for public use.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr, del_fn):
|
||||||
Handle.__init__(self, ptr)
|
self.ptr = ptr
|
||||||
self.owner = None
|
self.owner = None
|
||||||
|
self.del_fn = del_fn
|
||||||
|
|
||||||
def _own(self, owner):
|
def _own(self, owner):
|
||||||
if self.owner:
|
if self.owner:
|
||||||
raise LLVMException("object already owned")
|
raise LLVMException("object already owned")
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
self._finalizer_untrack(self.ptr)
|
|
||||||
|
|
||||||
def _disown(self):
|
def _disown(self):
|
||||||
if not self.owner:
|
if not self.owner:
|
||||||
raise LLVMException("not owned")
|
raise LLVMException("not owned")
|
||||||
self.owner = None
|
self.owner = None
|
||||||
self._finalizer_track(self.ptr)
|
|
||||||
|
def __del__(self):
|
||||||
|
if not self.owner:
|
||||||
|
self.del_fn(self.ptr)
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Dummy owner, will not delete ownee. Be careful.
|
# Dummy owner, will not delete ownee. Be careful.
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
'''
|
|
||||||
Modified C-level finalizer by Benjamin Peterson <benjamin@python.org>
|
|
||||||
Available at http://code.activestate.com/recipes/577242-calling-c-level-finalizers-without-__del__/
|
|
||||||
'''
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
import weakref
|
|
||||||
|
|
||||||
class OwnerRef(weakref.ref):
|
|
||||||
"""A simple weakref.ref subclass, so attributes can be added."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _run_finalizer(ref):
|
|
||||||
"""Internal weakref callback to run finalizers"""
|
|
||||||
del _finalize_refs[ref.owner]
|
|
||||||
for item, finalizer in ref.items:
|
|
||||||
try:
|
|
||||||
finalizer(item)
|
|
||||||
except Exception:
|
|
||||||
print>>sys.stderr, "Exception running {}:".format(finalizer)
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
_finalize_refs = {}
|
|
||||||
|
|
||||||
def track(owner, item, finalizer):
|
|
||||||
"""Register an object for finalization.
|
|
||||||
|
|
||||||
``owner`` is the the object which is responsible for ``item``.
|
|
||||||
``finalizer`` will be called with ``item`` as its only argument when
|
|
||||||
``owner`` is destroyed by the garbage collector.
|
|
||||||
"""
|
|
||||||
if id(owner) in _finalize_refs:
|
|
||||||
ref = _finalize_refs[id(owner)]
|
|
||||||
else:
|
|
||||||
ref = OwnerRef(owner, _run_finalizer)
|
|
||||||
ref.owner = id(owner)
|
|
||||||
ref.items = []
|
|
||||||
ref.items.append((item, finalizer))
|
|
||||||
_finalize_refs[id(owner)] = ref
|
|
||||||
|
|
||||||
def untrack(owner, item):
|
|
||||||
ref = _finalize_refs[id(owner)]
|
|
||||||
# search and remove the item from the ref
|
|
||||||
for i, (item_i, _) in enumerate(ref.items):
|
|
||||||
if item_i is item:
|
|
||||||
del ref.items[i]
|
|
||||||
# remove the ref if it is empty
|
|
||||||
if not ref.items:
|
|
||||||
del _finalize_refs[id(owner)]
|
|
||||||
|
|
||||||
class OwnerMixin(object):
|
|
||||||
def _finalizer_track(self, item):
|
|
||||||
if not hasattr(self, '_finalize'):
|
|
||||||
raise AttributeError("%s must define a _finalize method" % self)
|
|
||||||
track(self, item, type(self)._finalize)
|
|
||||||
|
|
||||||
def _finalizer_untrack(self, item):
|
|
||||||
untrack(self, item)
|
|
||||||
18
llvm/core.py
18
llvm/core.py
|
|
@ -397,9 +397,7 @@ class Module(llvm.Ownable, llvm.Cacheable):
|
||||||
|
|
||||||
Use the static method `Module.new' instead.
|
Use the static method `Module.new' instead.
|
||||||
"""
|
"""
|
||||||
llvm.Ownable.__init__(self, ptr)
|
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModule)
|
||||||
|
|
||||||
_finalizer = _core.LLVMDisposeModule
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Text representation of a module.
|
"""Text representation of a module.
|
||||||
|
|
@ -1801,7 +1799,7 @@ def _make_value(ptr):
|
||||||
# Builder
|
# Builder
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class Builder(llvm.Handle):
|
class Builder(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(basic_block):
|
def new(basic_block):
|
||||||
|
|
@ -1811,9 +1809,10 @@ class Builder(llvm.Handle):
|
||||||
return b
|
return b
|
||||||
|
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr):
|
||||||
llvm.Handle.__init__(self, ptr)
|
self.ptr = ptr
|
||||||
|
|
||||||
_finalizer = _core.LLVMDisposeBuilder
|
def __del__(self):
|
||||||
|
_core.LLVMDisposeBuilder(self.ptr)
|
||||||
|
|
||||||
def position_at_beginning(self, bblk):
|
def position_at_beginning(self, bblk):
|
||||||
"""Position the builder at the beginning of the given block.
|
"""Position the builder at the beginning of the given block.
|
||||||
|
|
@ -2302,7 +2301,7 @@ class Builder(llvm.Handle):
|
||||||
# Memory buffer
|
# Memory buffer
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class MemoryBuffer(llvm.Handle):
|
class MemoryBuffer(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_file(fname):
|
def from_file(fname):
|
||||||
|
|
@ -2323,9 +2322,10 @@ class MemoryBuffer(llvm.Handle):
|
||||||
return (obj, "")
|
return (obj, "")
|
||||||
|
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr):
|
||||||
llvm.Handle.__init__(self, ptr)
|
self.ptr = ptr
|
||||||
|
|
||||||
_finalizer = _core.LLVMDisposeMemoryBuffer
|
def __del__(self):
|
||||||
|
_core.LLVMDisposeMemoryBuffer(self.ptr)
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
|
||||||
25
llvm/ee.py
25
llvm/ee.py
|
|
@ -63,7 +63,7 @@ CM_LARGE = 5
|
||||||
# Generic value
|
# Generic value
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class GenericValue(llvm.Handle):
|
class GenericValue(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def int(ty, intval):
|
def int(ty, intval):
|
||||||
|
|
@ -106,9 +106,10 @@ class GenericValue(llvm.Handle):
|
||||||
return GenericValue(ptr)
|
return GenericValue(ptr)
|
||||||
|
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr):
|
||||||
llvm.Handle.__init__(self, ptr)
|
self.ptr = ptr
|
||||||
|
|
||||||
_finalizer = _core.LLVMDisposeGenericValue
|
def __del__(self):
|
||||||
|
_core.LLVMDisposeGenericValue(self.ptr)
|
||||||
|
|
||||||
def as_int(self):
|
def as_int(self):
|
||||||
return _core.LLVMGenericValueToInt(self.ptr, 0)
|
return _core.LLVMGenericValueToInt(self.ptr, 0)
|
||||||
|
|
@ -134,7 +135,7 @@ def _unpack_generic_values(objlist):
|
||||||
# Engine builder
|
# Engine builder
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class EngineBuilder(llvm.Handle):
|
class EngineBuilder(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(module):
|
def new(module):
|
||||||
core.check_is_module(module)
|
core.check_is_module(module)
|
||||||
|
|
@ -143,10 +144,11 @@ class EngineBuilder(llvm.Handle):
|
||||||
return EngineBuilder(obj, module)
|
return EngineBuilder(obj, module)
|
||||||
|
|
||||||
def __init__(self, ptr, module):
|
def __init__(self, ptr, module):
|
||||||
llvm.Handle.__init__(self, ptr)
|
self.ptr = ptr
|
||||||
self._module = module
|
self._module = module
|
||||||
|
|
||||||
_finalizer = _core.LLVMDisposeEngineBuilder
|
def __del__(self):
|
||||||
|
_core.LLVMDisposeEngineBuilder(self.ptr)
|
||||||
|
|
||||||
def force_jit(self):
|
def force_jit(self):
|
||||||
_core.LLVMEngineBuilderForceJIT(self.ptr)
|
_core.LLVMEngineBuilderForceJIT(self.ptr)
|
||||||
|
|
@ -199,7 +201,7 @@ class EngineBuilder(llvm.Handle):
|
||||||
# Execution engine
|
# Execution engine
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class ExecutionEngine(llvm.Handle):
|
class ExecutionEngine(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(module, force_interpreter=False):
|
def new(module, force_interpreter=False):
|
||||||
|
|
@ -211,10 +213,11 @@ class ExecutionEngine(llvm.Handle):
|
||||||
return ExecutionEngine(ret, module)
|
return ExecutionEngine(ret, module)
|
||||||
|
|
||||||
def __init__(self, ptr, module):
|
def __init__(self, ptr, module):
|
||||||
llvm.Handle.__init__(self, ptr)
|
self.ptr = ptr
|
||||||
module._own(self)
|
module._own(self)
|
||||||
|
|
||||||
_finalizer = _core.LLVMDisposeExecutionEngine
|
def __del__(self):
|
||||||
|
_core.LLVMDisposeExecutionEngine(self.ptr)
|
||||||
|
|
||||||
def run_function(self, fn, args):
|
def run_function(self, fn, args):
|
||||||
core.check_is_function(fn)
|
core.check_is_function(fn)
|
||||||
|
|
@ -313,9 +316,7 @@ class TargetMachine(llvm.Ownable):
|
||||||
return TargetMachine(ptr)
|
return TargetMachine(ptr)
|
||||||
|
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr):
|
||||||
llvm.Ownable.__init__(self, ptr)
|
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeTargetMachine)
|
||||||
|
|
||||||
_finalizer = _core.LLVMDisposeTargetMachine
|
|
||||||
|
|
||||||
def emit_assembly(self, module):
|
def emit_assembly(self, module):
|
||||||
'''returns byte string of the module as assembly code of the target machine
|
'''returns byte string of the module as assembly code of the target machine
|
||||||
|
|
|
||||||
|
|
@ -45,15 +45,16 @@ import warnings
|
||||||
# Pass manager builder
|
# Pass manager builder
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class PassManagerBuilder(llvm.Handle):
|
class PassManagerBuilder(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new():
|
def new():
|
||||||
return PassManagerBuilder(_core.LLVMPassManagerBuilderCreate())
|
return PassManagerBuilder(_core.LLVMPassManagerBuilderCreate())
|
||||||
|
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr):
|
||||||
llvm.Handle.__init__(self, ptr)
|
self.ptr = ptr
|
||||||
|
|
||||||
_finalizer = _core.LLVMPassManagerBuilderDispose
|
def __del__(self):
|
||||||
|
_core.LLVMPassManagerBuilderDispose(self.ptr)
|
||||||
|
|
||||||
def populate(self, pm):
|
def populate(self, pm):
|
||||||
if isinstance(pm, FunctionPassManager):
|
if isinstance(pm, FunctionPassManager):
|
||||||
|
|
@ -141,7 +142,7 @@ class PassManagerBuilder(llvm.Handle):
|
||||||
# Pass manager
|
# Pass manager
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class PassManager(llvm.Handle):
|
class PassManager(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new():
|
def new():
|
||||||
|
|
@ -150,7 +151,8 @@ class PassManager(llvm.Handle):
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr):
|
||||||
self.ptr = ptr
|
self.ptr = ptr
|
||||||
|
|
||||||
_finalizer = _core.LLVMDisposePassManager
|
def __del__(self):
|
||||||
|
_core.LLVMDisposePassManager(self.ptr)
|
||||||
|
|
||||||
def add(self, pass_obj):
|
def add(self, pass_obj):
|
||||||
'''Add a pass to the pass manager.
|
'''Add a pass to the pass manager.
|
||||||
|
|
@ -206,11 +208,9 @@ class Pass(llvm.Ownable):
|
||||||
'''Pass Inferface
|
'''Pass Inferface
|
||||||
'''
|
'''
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr):
|
||||||
llvm.Ownable.__init__(self, ptr)
|
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposePass)
|
||||||
self.__name = ''
|
self.__name = ''
|
||||||
|
|
||||||
_finalizer = _core.LLVMDisposePass
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(name):
|
def new(name):
|
||||||
'''Create a new pass by name.
|
'''Create a new pass by name.
|
||||||
|
|
|
||||||
2
setup.py
2
setup.py
|
|
@ -131,7 +131,7 @@ setup(
|
||||||
maintainer = 'Continuum Analytics, Inc.',
|
maintainer = 'Continuum Analytics, Inc.',
|
||||||
maintainer_email = 'llvmpy@continuum.io',
|
maintainer_email = 'llvmpy@continuum.io',
|
||||||
url = 'http://www.llvmpy.org/',
|
url = 'http://www.llvmpy.org/',
|
||||||
packages = ['llvm', 'llvm_cbuilder', 'llpython', 'llvm._utils'],
|
packages = ['llvm', 'llvm_cbuilder', 'llpython'],
|
||||||
py_modules = ['llvm.core'],
|
py_modules = ['llvm.core'],
|
||||||
license = "BSD",
|
license = "BSD",
|
||||||
classifiers = [
|
classifiers = [
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue