[pypy-svn] r25729 - in pypy/dist/pypy: rpython rpython/lltypesystem translator/c translator/c/test translator/c/winproj/extension
tismer at codespeak.net
tismer at codespeak.net
Wed Apr 12 19:39:11 CEST 2006
Author: tismer
Date: Wed Apr 12 19:39:05 2006
New Revision: 25729
Modified:
pypy/dist/pypy/rpython/lltypesystem/rclass.py
pypy/dist/pypy/rpython/rtyper.py
pypy/dist/pypy/translator/c/database.py
pypy/dist/pypy/translator/c/genc.py
pypy/dist/pypy/translator/c/pyobj.py
pypy/dist/pypy/translator/c/test/test_wrapping.py
pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj
pypy/dist/pypy/translator/c/wrapper.py
Log:
made object instantiation implicit, to be called during __init__.
This is much more efficient than the former approach, although
the wrapping is slightly more delicate. This also required to
add an extra hook which I dislike, since the rtyper needs to
know which function is actually being wrapped, in order to figure
out whether we are wrapping __init__ or something else.
Temporary (but tested) check-in before refactoring.
Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Wed Apr 12 19:39:05 2006
@@ -594,6 +594,7 @@
#
# _________________________ Conversions for CPython _________________________
+# part I: wrapping, destructor, preserving object identity
def call_destructor(thing, repr):
ll_call_destructor(thing, repr)
@@ -602,13 +603,13 @@
return 42 # will be mapped
def rtype_destruct_object(hop):
- v_any, c_spec = hop.inputargs(*hop.args_r)
+ v_inst, c_spec = hop.inputargs(*hop.args_r)
repr = c_spec.value
if repr.has_wrapper:
null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
# XXX this is a hack! We need an operation to remove a broken PyObject
- repr.setfield(v_any, '_wrapper_', null, hop.llops, opname='bare_setfield')
- hop.genop('gc_unprotect', [v_any])
+ repr.setfield(v_inst, '_wrapper_', null, hop.llops, opname='bare_setfield')
+ hop.genop('gc_unprotect', [v_inst])
extregistry.register_value(ll_call_destructor,
compute_result_annotation=lambda *args: None,
@@ -623,16 +624,16 @@
def rtype_wrap_object_create(hop):
gencapi = hop.llops.gencapicall
pyptr = hop.r_result
- v_any, c_spec = hop.inputargs(*hop.args_r)
+ v_inst, c_spec = hop.inputargs(*hop.args_r)
repr = c_spec.value
f = call_destructor
- hop.genop('gc_protect', [v_any])
+ hop.genop('gc_protect', [v_inst])
ARG = repr.lowleveltype
reprPBC = hop.rtyper.annotator.bookkeeper.immutablevalue(repr)
fp_dtor = hop.rtyper.annotate_helper_fn(f, [ARG, reprPBC])
FUNC = FuncType([ARG, Void], Void)
c_dtor = hop.inputconst(Ptr(FUNC), fp_dtor)
- res = gencapi('PyCObject_FromVoidPtr', [v_any, c_dtor], resulttype=hop.r_result)
+ res = gencapi('PyCObject_FromVoidPtr', [v_inst, c_dtor], resulttype=pyptr)
if repr.has_wrapper:
cobj = res
c_cls = hop.inputconst(pyobj_repr, repr.classdef.classdesc.pyobj)
@@ -640,7 +641,7 @@
res = gencapi('PyType_GenericAlloc', [c_cls, c_0], resulttype=pyptr)
c_self = hop.inputconst(pyobj_repr, '__self__')
v_result = hop.genop('setattr', [res, c_self, cobj], resulttype=pyptr)
- repr.setfield(v_any, '_wrapper_', res, hop.llops)
+ repr.setfield(v_inst, '_wrapper_', res, hop.llops)
hop.genop('gc_unprotect', [res]) # yes a weak ref
return res
@@ -655,10 +656,10 @@
return 42
def rtype_wrap_object_fetch(hop):
- v_any, c_spec = hop.inputargs(*hop.args_r)
+ v_inst, c_spec = hop.inputargs(*hop.args_r)
repr = c_spec.value
if repr.has_wrapper:
- return repr.getfield(v_any, '_wrapper_', hop.llops)
+ return repr.getfield(v_inst, '_wrapper_', hop.llops)
else:
null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
return null
@@ -673,15 +674,6 @@
ret = create_pywrapper(obj, repr)
return ret
-class __extend__(pairtype(PyObjRepr, InstanceRepr)):
- def convert_from_to((r_from, r_to), v, llops):
- if r_to.has_wrapper:
- c_self = inputconst(pyobj_repr, '__self__')
- v = llops.genop('getattr', [v, c_self], resulttype=r_from)
- v_adr = llops.gencapicall('PyCObject_AsVoidPtr', [v], resulttype=r_to)
- llops.genop('gc_protect', [v_adr])
- return v_adr
-
class __extend__(pairtype(InstanceRepr, PyObjRepr)):
def convert_from_to((r_from, r_to), v, llops):
c_repr = inputconst(Void, r_from)
@@ -690,6 +682,38 @@
else:
return llops.gendirectcall(create_pywrapper, v, c_repr)
+# part II: unwrapping, creating the instance
+
+class __extend__(pairtype(PyObjRepr, InstanceRepr)):
+ def convert_from_to((r_from, r_to), v, llops):
+ if r_to.has_wrapper:
+ init, context = llops.rtyper.get_wrapping_hint(r_to.classdef)
+ if context is init:
+ # saving an extra __new__ method, we create the instance on __init__
+ v_inst = r_to.new_instance(llops)
+ gencapi = llops.gencapicall
+ rtyper = llops.rtyper
+ pyptr = r_from
+ f = call_destructor
+ ARG = r_to.lowleveltype
+ reprPBC = rtyper.annotator.bookkeeper.immutablevalue(r_to)
+ fp_dtor = rtyper.annotate_helper_fn(f, [ARG, reprPBC])
+ FUNC = FuncType([ARG, Void], Void)
+ c_dtor = inputconst(Ptr(FUNC), fp_dtor)
+ v_cobj = gencapi('PyCObject_FromVoidPtr', [v_inst, c_dtor], resulttype=pyptr)
+ c_self = inputconst(pyobj_repr, '__self__')
+ llops.genop('setattr', [v, c_self, v_cobj], resulttype=pyptr)
+ r_to.setfield(v_inst, '_wrapper_', v, llops)
+ llops.genop('gc_protect', [v_inst])
+ llops.genop('gc_unprotect', [v])
+ return v_inst
+
+ c_self = inputconst(pyobj_repr, '__self__')
+ v = llops.genop('getattr', [v, c_self], resulttype=r_from)
+ v_inst = llops.gencapicall('PyCObject_AsVoidPtr', [v], resulttype=r_to)
+ llops.genop('gc_protect', [v_inst])
+ return v_inst
+
# ____________________________________________________________
def ll_both_none(ins1, ins2):
Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py (original)
+++ pypy/dist/pypy/rpython/rtyper.py Wed Apr 12 19:39:05 2006
@@ -57,6 +57,7 @@
self.instance_reprs = {}
self.pbc_reprs = {}
self.classdefs_with_wrapper = {}
+ self.wrapper_context = None # or add an extra arg to convertvar?
self.concrete_calltables = {}
self.class_pbc_attributes = {}
self.oo_meth_impls = {}
@@ -89,7 +90,13 @@
self.crash_on_first_typeerror = True
def add_wrapper(self, clsdef):
- self.classdefs_with_wrapper[clsdef] = clsdef
+ # record that this class has a wrapper, and what the __init__ is
+ init = getattr(clsdef.classdesc.pyobj.__init__, 'im_func', None)
+ self.classdefs_with_wrapper[clsdef] = init
+
+ def set_wrapper_context(self, obj):
+ # not nice, but we sometimes need to know which function we are wrapping
+ self.wrapper_context = obj
def add_pendingsetup(self, repr):
assert isinstance(repr, Repr)
@@ -546,6 +553,9 @@
def needs_wrapper(self, clsdef):
return clsdef in self.classdefs_with_wrapper
+ def get_wrapping_hint(self, clsdef):
+ return self.classdefs_with_wrapper[clsdef], self.wrapper_context
+
def getcallable(self, graph):
def getconcretetype(v):
return self.bindingrepr(v).lowleveltype
Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py (original)
+++ pypy/dist/pypy/translator/c/database.py Wed Apr 12 19:39:05 2006
@@ -21,8 +21,7 @@
class LowLevelDatabase(object):
- def __init__(self, translator=None, standalone=False, gcpolicy=None, thread_enabled=False,
- instantiators={}):
+ def __init__(self, translator=None, standalone=False, gcpolicy=None, thread_enabled=False):
self.translator = translator
self.standalone = standalone
self.structdefnodes = {}
@@ -38,7 +37,7 @@
self.infs = []
self.namespace = CNameManager()
if not standalone:
- self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator, instantiators)
+ self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator)
if gcpolicy is None:
from pypy.translator.c import gc
polname = conftest.option.gcpolicy
Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py (original)
+++ pypy/dist/pypy/translator/c/genc.py Wed Apr 12 19:39:05 2006
@@ -33,11 +33,10 @@
self.libraries = libraries
self.exports = {}
- def build_database(self, exports=[], instantiators={}):
+ def build_database(self, exports=[]):
translator = self.translator
db = LowLevelDatabase(translator, standalone=self.standalone,
- gcpolicy=self.gcpolicy, thread_enabled=self.thread_enabled,
- instantiators=instantiators)
+ gcpolicy=self.gcpolicy, thread_enabled=self.thread_enabled)
if self.stackless:
from pypy.translator.c.stackless import StacklessData
Modified: pypy/dist/pypy/translator/c/pyobj.py
==============================================================================
--- pypy/dist/pypy/translator/c/pyobj.py (original)
+++ pypy/dist/pypy/translator/c/pyobj.py Wed Apr 12 19:39:05 2006
@@ -23,7 +23,7 @@
reconstruct them.
"""
- def __init__(self, namespace, getvalue, translator=None, instantiators={}):
+ def __init__(self, namespace, getvalue, translator=None):
self.namespace = namespace
self.getvalue = getvalue
self.translator = translator
@@ -38,7 +38,6 @@
self.wrappers = {} # {'pycfunctionvariable': ('name', 'wrapperfn')}
self.import_hints = {} # I don't seem to need it any longer.
# leaving the import support intact, doesn't hurt.
- self.instantiators = instantiators
def nameof(self, obj, debug=None):
if debug:
@@ -336,7 +335,8 @@
return name
def nameof_classobj(self, cls):
- if cls in self.instantiators:
+ clsdef = self.translator.annotator.bookkeeper.getuniqueclassdef(cls)
+ if self.translator.rtyper.needs_wrapper(clsdef):
return self.wrap_exported_class(cls)
if cls.__doc__ and cls.__doc__.lstrip().startswith('NOT_RPYTHON'):
@@ -551,16 +551,9 @@
if baseargs:
baseargs = '(%s)' % baseargs
- # fishing for the instantiator
- instantiator = self.nameof(self.instantiators[cls])
a = self.initcode.append
a('class %s%s:' % (name, baseargs) )
a(' __metaclass__ = type')
a(' __slots__ = ["__self__"] # for PyCObject')
- a(' def __new__(cls, *args, **kwds):')
- a(' return %s()' % instantiator )
- # XXX
- # I would like to use instantiator directly, but don't know
- # how to create a function that ignores all args
self.later(initclassobj())
return name
Modified: pypy/dist/pypy/translator/c/test/test_wrapping.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_wrapping.py (original)
+++ pypy/dist/pypy/translator/c/test/test_wrapping.py Wed Apr 12 19:39:05 2006
@@ -4,7 +4,6 @@
from pypy.rpython import extregistry
from pypy.annotation import model as annmodel
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython.objectmodel import instantiate
from pypy.rpython import robject, rclass
import sys
@@ -35,7 +34,6 @@
t.buildannotator()
rtyper = t.buildrtyper()
bk = rtyper.annotator.bookkeeper
- instantiators = {}
t.annotator.build_types(func, get_annotation(func))
if not exports:
exports = []
@@ -43,14 +41,7 @@
exports = exports + [('__all__', all)]
for obj in exports:
if isinstance(obj, type):
- cls = obj
- def make():
- obj = instantiate(cls)
- return obj
- make.__name__ = cls.__name__ + '__new__'
- t.annotator.build_types(make, [])
- instantiators[cls] = make
- clsdef = bk.getuniqueclassdef(cls)
+ clsdef = bk.getuniqueclassdef(obj)
rtyper.add_wrapper(clsdef)
elif callable(obj):
t.annotator.build_types(obj, get_annotation(obj))
@@ -71,7 +62,7 @@
cbuilder = CExtModuleBuilder(t, func, gcpolicy=gcpolicy)
# explicit build of database
- db = cbuilder.build_database(exports=exports, instantiators=instantiators)
+ db = cbuilder.build_database(exports=exports)
cbuilder.generate_source(db)
cbuilder.compile()
@@ -263,9 +254,9 @@
DemoClass.__init__(self, b, a)
self.c = c
-# def demo(self, *other):
+ def demo(self, *other):
#if other: print other
- # return float(DemoClass.demo(self))
+ return float(DemoClass.demo(self))
def otherdemo(self):
return 'this is the DemoSubclass', self.a, self.b
@@ -319,38 +310,8 @@
# _______________________________________________
# creating our own setup function for the module
-def do_the_import():
- from twisted.internet import reactor
- return reactor
-
-def rtype_wraptest(hop):
- #v_obj, = hop.inputargs((robject.pyobj_repr, ))
- from pypy.objspace.flow.model import Constant
- v_obj = Constant(hop.args_s[0].const)
- v = hop.genop('simple_call', [v_obj], resulttype = robject.pyobj_repr)
- return v
-
-def wraptest(obj):
- return obj
-extregistry.register_value(wraptest,
- compute_result_annotation = annmodel.SomeObject(),
- specialize_call = rtype_wraptest)
-
-# not sure what to do with the above.
-# use genpickle facility to produce a plain function?
-# create a space and run geninterp on it?
-# tweak flow space to delay the imports for this func?
-
-### XXX write up the rules how to use this ###
-
-def t2():
- global sys
- import sys
-
def setup_new_module(mod, modname):
# note the name clash with py.test on setup_module
- #t1()
- #t2()
return
from types import module
m = module(modname)
@@ -392,6 +353,7 @@
res = obj.demo()
assert res == DemoClass(2, 3).demo()
+
if __name__=='__main__':
test_expose_classes()
Modified: pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj
==============================================================================
--- pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj (original)
+++ pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj Wed Apr 12 19:39:05 2006
@@ -208,7 +208,7 @@
</File>
</Filter>
<File
- RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-1751\testing_1\testing_1.c">
+ RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-1965\testing_1\testing_1.c">
</File>
</Files>
<Globals>
Modified: pypy/dist/pypy/translator/c/wrapper.py
==============================================================================
--- pypy/dist/pypy/translator/c/wrapper.py (original)
+++ pypy/dist/pypy/translator/c/wrapper.py Wed Apr 12 19:39:05 2006
@@ -98,9 +98,12 @@
assert rtyper is not None, (
"needs the rtyper to perform argument conversions")
r_arg = rtyper.bindingrepr(inputargs[i])
+ # give the rtyper a chance to know which function we are wrapping
+ rtyper.set_wrapper_context(func)
varguments[i] = newops.convertvar(varguments[i],
r_from = pyobj_repr,
r_to = r_arg)
+ rtyper.set_wrapper_context(None)
# "result = direct_call(func, argument_0, argument_1, ..)"
vlist = [inputconst(typeOf(f), f)] + varguments
More information about the Pypy-commit
mailing list