[pypy-svn] r78047 - in pypy/trunk/pypy: . annotation annotation/test config doc/config jit/backend/llgraph jit/backend/llsupport jit/backend/llsupport/test jit/backend/test jit/backend/x86/test jit/codewriter jit/codewriter/test jit/metainterp jit/metainterp/optimizeopt jit/metainterp/test jit/tl module/_ffi module/_rawffi module/_rawffi/test module/pypyjit module/pypyjit/test rlib rlib/test rpython rpython/lltypesystem rpython/test translator/c/test
antocuni at codespeak.net
antocuni at codespeak.net
Mon Oct 18 16:45:19 CEST 2010
Author: antocuni
Date: Mon Oct 18 16:45:16 2010
New Revision: 78047
Added:
pypy/trunk/pypy/doc/config/objspace.usemodules._ffi.txt
- copied unchanged from r78044, pypy/branch/jitffi/pypy/doc/config/objspace.usemodules._ffi.txt
pypy/trunk/pypy/jit/backend/llsupport/ffisupport.py
- copied unchanged from r78044, pypy/branch/jitffi/pypy/jit/backend/llsupport/ffisupport.py
pypy/trunk/pypy/jit/backend/llsupport/test/test_ffisupport.py
- copied unchanged from r78044, pypy/branch/jitffi/pypy/jit/backend/llsupport/test/test_ffisupport.py
pypy/trunk/pypy/jit/metainterp/optimizeopt/fficall.py
- copied unchanged from r78044, pypy/branch/jitffi/pypy/jit/metainterp/optimizeopt/fficall.py
pypy/trunk/pypy/jit/metainterp/test/test_fficall.py
- copied unchanged from r78044, pypy/branch/jitffi/pypy/jit/metainterp/test/test_fficall.py
pypy/trunk/pypy/jit/metainterp/test/test_optimizefficall.py
- copied unchanged from r78044, pypy/branch/jitffi/pypy/jit/metainterp/test/test_optimizefficall.py
pypy/trunk/pypy/module/_ffi/
- copied from r78044, pypy/branch/jitffi/pypy/module/_ffi/
pypy/trunk/pypy/rlib/clibffi.py
- copied unchanged from r78044, pypy/branch/jitffi/pypy/rlib/clibffi.py
pypy/trunk/pypy/rlib/libffi.py
- copied unchanged from r78044, pypy/branch/jitffi/pypy/rlib/libffi.py
pypy/trunk/pypy/rlib/test/test_clibffi.py
- copied unchanged from r78044, pypy/branch/jitffi/pypy/rlib/test/test_clibffi.py
pypy/trunk/pypy/rlib/test/test_libffi.py
- copied unchanged from r78044, pypy/branch/jitffi/pypy/rlib/test/test_libffi.py
Modified:
pypy/trunk/pypy/ (props changed)
pypy/trunk/pypy/annotation/model.py
pypy/trunk/pypy/annotation/test/test_model.py
pypy/trunk/pypy/config/pypyoption.py
pypy/trunk/pypy/jit/backend/llgraph/llimpl.py
pypy/trunk/pypy/jit/backend/llgraph/runner.py
pypy/trunk/pypy/jit/backend/llsupport/descr.py
pypy/trunk/pypy/jit/backend/llsupport/llmodel.py
pypy/trunk/pypy/jit/backend/test/runner_test.py
pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py
pypy/trunk/pypy/jit/backend/x86/test/test_ztranslation.py
pypy/trunk/pypy/jit/codewriter/effectinfo.py
pypy/trunk/pypy/jit/codewriter/jtransform.py
pypy/trunk/pypy/jit/codewriter/support.py
pypy/trunk/pypy/jit/codewriter/test/test_effectinfo.py
pypy/trunk/pypy/jit/metainterp/executor.py
pypy/trunk/pypy/jit/metainterp/optimize_nopspec.py (props changed)
pypy/trunk/pypy/jit/metainterp/optimizeopt/__init__.py
pypy/trunk/pypy/jit/metainterp/optimizeopt/virtualize.py
pypy/trunk/pypy/jit/metainterp/resoperation.py
pypy/trunk/pypy/jit/metainterp/test/test_loop_nopspec.py (props changed)
pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
pypy/trunk/pypy/jit/metainterp/warmstate.py
pypy/trunk/pypy/jit/tl/jittest.py (props changed)
pypy/trunk/pypy/jit/tl/pypyjit.py
pypy/trunk/pypy/jit/tl/pypyjit_child.py
pypy/trunk/pypy/module/_rawffi/__init__.py
pypy/trunk/pypy/module/_rawffi/callback.py
pypy/trunk/pypy/module/_rawffi/interp_rawffi.py
pypy/trunk/pypy/module/_rawffi/structure.py
pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py
pypy/trunk/pypy/module/pypyjit/policy.py
pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
pypy/trunk/pypy/rlib/jit.py
pypy/trunk/pypy/rlib/test/test_jit.py
pypy/trunk/pypy/rlib/test/test_rdynload.py
pypy/trunk/pypy/rpython/lltypesystem/lltype.py
pypy/trunk/pypy/rpython/rpbc.py
pypy/trunk/pypy/rpython/test/test_rclass.py
pypy/trunk/pypy/translator/c/test/test_newgc.py
Log:
merge the jitffi branch: it provides a new jit-friendly rlib.libffi module,
and an app-level _ffi module which exposes it.
Modified: pypy/trunk/pypy/annotation/model.py
==============================================================================
--- pypy/trunk/pypy/annotation/model.py (original)
+++ pypy/trunk/pypy/annotation/model.py Mon Oct 18 16:45:16 2010
@@ -574,11 +574,11 @@
NUMBER = object()
annotation_to_ll_map = [
+ (SomeSingleFloat(), lltype.SingleFloat),
(s_None, lltype.Void), # also matches SomeImpossibleValue()
(s_Bool, lltype.Bool),
(SomeInteger(knowntype=r_ulonglong), NUMBER),
(SomeFloat(), lltype.Float),
- (SomeSingleFloat(), lltype.SingleFloat),
(SomeChar(), lltype.Char),
(SomeUnicodeCodePoint(), lltype.UniChar),
(SomeAddress(), llmemory.Address),
Modified: pypy/trunk/pypy/annotation/test/test_model.py
==============================================================================
--- pypy/trunk/pypy/annotation/test/test_model.py (original)
+++ pypy/trunk/pypy/annotation/test/test_model.py Mon Oct 18 16:45:16 2010
@@ -128,7 +128,7 @@
assert isinstance(s_p, SomeOOInstance) and s_p.ootype == C
def test_annotation_to_lltype():
- from pypy.rlib.rarithmetic import r_uint
+ from pypy.rlib.rarithmetic import r_uint, r_singlefloat
s_i = SomeInteger()
s_pos = SomeInteger(nonneg=True)
s_1 = SomeInteger(nonneg=True); s_1.const = 1
@@ -151,6 +151,9 @@
C = ootype.Instance('C', ROOT, {})
ref = SomeOOInstance(C)
assert annotation_to_lltype(ref) == C
+ s_singlefloat = SomeSingleFloat()
+ s_singlefloat.const = r_singlefloat(0.0)
+ assert annotation_to_lltype(s_singlefloat) == lltype.SingleFloat
def test_ll_union():
PS1 = lltype.Ptr(lltype.GcStruct('s'))
Modified: pypy/trunk/pypy/config/pypyoption.py
==============================================================================
--- pypy/trunk/pypy/config/pypyoption.py (original)
+++ pypy/trunk/pypy/config/pypyoption.py Mon Oct 18 16:45:16 2010
@@ -73,9 +73,9 @@
}
module_import_dependencies = {
- # no _rawffi if importing pypy.rlib.libffi raises ImportError
+ # no _rawffi if importing pypy.rlib.clibffi raises ImportError
# or CompilationError
- "_rawffi" : ["pypy.rlib.libffi"],
+ "_rawffi" : ["pypy.rlib.clibffi"],
"zlib" : ["pypy.rlib.rzlib"],
"bz2" : ["pypy.module.bz2.interp_bz2"],
Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llgraph/llimpl.py (original)
+++ pypy/trunk/pypy/jit/backend/llgraph/llimpl.py Mon Oct 18 16:45:16 2010
@@ -10,7 +10,7 @@
BoxInt, BoxPtr, BoxObj, BoxFloat,
REF, INT, FLOAT)
from pypy.jit.codewriter import heaptracker
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rffi
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.module.support import LLSupport, OOSupport
from pypy.rpython.llinterp import LLException
@@ -305,12 +305,12 @@
loop = _from_opaque(loop)
loop.operations.append(Operation(opnum))
-def compile_add_descr(loop, ofs, type):
+def compile_add_descr(loop, ofs, type, arg_types):
from pypy.jit.backend.llgraph.runner import Descr
loop = _from_opaque(loop)
op = loop.operations[-1]
assert isinstance(type, str) and len(type) == 1
- op.descr = Descr(ofs, type)
+ op.descr = Descr(ofs, type, arg_types=arg_types)
def compile_add_loop_token(loop, descr):
if we_are_translated():
@@ -801,7 +801,7 @@
else:
raise TypeError(x)
try:
- return _do_call_common(func, args_in_order)
+ return _do_call_common(func, args_in_order, calldescr)
except LLException, lle:
_last_exception = lle
d = {'v': None,
@@ -1018,6 +1018,9 @@
if isinstance(TYPE, lltype.Ptr):
if isinstance(x, (int, long, llmemory.AddressAsInt)):
x = llmemory.cast_int_to_adr(x)
+ if TYPE is rffi.VOIDP:
+ # assume that we want a "C-style" cast, without typechecking the value
+ return rffi.cast(TYPE, x)
return llmemory.cast_adr_to_ptr(x, TYPE)
elif TYPE == llmemory.Address:
if isinstance(x, (int, long, llmemory.AddressAsInt)):
@@ -1411,10 +1414,26 @@
def do_call_pushfloat(x):
_call_args_f.append(x)
-def _do_call_common(f, args_in_order=None):
+kind2TYPE = {
+ 'i': lltype.Signed,
+ 'f': lltype.Float,
+ 'v': lltype.Void,
+ }
+
+def _do_call_common(f, args_in_order=None, calldescr=None):
ptr = llmemory.cast_int_to_adr(f).ptr
- FUNC = lltype.typeOf(ptr).TO
- ARGS = FUNC.ARGS
+ PTR = lltype.typeOf(ptr)
+ if PTR == rffi.VOIDP:
+ # it's a pointer to a C function, so we don't have a precise
+ # signature: create one from the descr
+ ARGS = map(kind2TYPE.get, calldescr.arg_types)
+ RESULT = kind2TYPE[calldescr.typeinfo]
+ FUNC = lltype.FuncType(ARGS, RESULT)
+ func_to_call = rffi.cast(lltype.Ptr(FUNC), ptr)
+ else:
+ FUNC = PTR.TO
+ ARGS = FUNC.ARGS
+ func_to_call = ptr._obj._callable
args = cast_call_args(ARGS, _call_args_i, _call_args_r, _call_args_f,
args_in_order)
del _call_args_i[:]
@@ -1426,7 +1445,7 @@
result = llinterp.eval_graph(ptr._obj.graph, args)
# ^^^ may raise, in which case we get an LLException
else:
- result = ptr._obj._callable(*args)
+ result = func_to_call(*args)
return result
def do_call_void(f):
Modified: pypy/trunk/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llgraph/runner.py (original)
+++ pypy/trunk/pypy/jit/backend/llgraph/runner.py Mon Oct 18 16:45:16 2010
@@ -154,7 +154,7 @@
llimpl.compile_add(c, op.getopnum())
descr = op.getdescr()
if isinstance(descr, Descr):
- llimpl.compile_add_descr(c, descr.ofs, descr.typeinfo)
+ llimpl.compile_add_descr(c, descr.ofs, descr.typeinfo, descr.arg_types)
if isinstance(descr, history.LoopToken) and op.getopnum() != rop.JUMP:
llimpl.compile_add_loop_token(c, descr)
if self.is_oo and isinstance(descr, (OODescr, MethDescr)):
@@ -297,6 +297,18 @@
return self.getdescr(0, token[0], extrainfo=extrainfo,
arg_types=''.join(arg_types))
+ def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo=None):
+ from pypy.jit.backend.llsupport.ffisupport import get_ffi_type_kind
+ arg_types = []
+ for arg in ffi_args:
+ kind = get_ffi_type_kind(arg)
+ if kind != history.VOID:
+ arg_types.append(kind)
+ reskind = get_ffi_type_kind(ffi_result)
+ return self.getdescr(0, reskind, extrainfo=extrainfo,
+ arg_types=''.join(arg_types))
+
+
def grab_exc_value(self):
return llimpl.grab_exc_value()
Modified: pypy/trunk/pypy/jit/backend/llsupport/descr.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llsupport/descr.py (original)
+++ pypy/trunk/pypy/jit/backend/llsupport/descr.py Mon Oct 18 16:45:16 2010
@@ -307,6 +307,21 @@
_return_type = history.INT
call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0)
+class DynamicIntCallDescr(BaseIntCallDescr):
+ """
+ calldescr that works for every integer type, by explicitly passing it the
+ size of the result. Used only by get_call_descr_dynamic
+ """
+ _clsname = 'DynamicIntCallDescr'
+
+ def __init__(self, arg_classes, result_size, extrainfo=None):
+ BaseIntCallDescr.__init__(self, arg_classes, extrainfo)
+ self._result_size = result_size
+
+ def get_result_size(self, translate_support_code):
+ return self._result_size
+
+
class NonGcPtrCallDescr(BaseIntCallDescr):
_clsname = 'NonGcPtrCallDescr'
def get_result_size(self, translate_support_code):
Modified: pypy/trunk/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llsupport/llmodel.py (original)
+++ pypy/trunk/pypy/jit/backend/llsupport/llmodel.py Mon Oct 18 16:45:16 2010
@@ -17,6 +17,7 @@
from pypy.jit.backend.llsupport.descr import get_call_descr
from pypy.jit.backend.llsupport.descr import BaseIntCallDescr, GcPtrCallDescr
from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr
+from pypy.jit.backend.llsupport.ffisupport import get_call_descr_dynamic
from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
@@ -231,6 +232,9 @@
def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None):
return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo)
+ def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo=None):
+ return get_call_descr_dynamic(ffi_args, ffi_result, extrainfo)
+
def get_overflow_error(self):
ovf_vtable = self.cast_adr_to_int(self._ovf_error_vtable)
ovf_inst = lltype.cast_opaque_ptr(llmemory.GCREF,
Modified: pypy/trunk/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/test/runner_test.py (original)
+++ pypy/trunk/pypy/jit/backend/test/runner_test.py Mon Oct 18 16:45:16 2010
@@ -421,6 +421,7 @@
assert x == 3.5 - 42
def test_call(self):
+ from pypy.rlib.libffi import types
def func_int(a, b):
return a + b
@@ -428,23 +429,31 @@
return chr(ord(c) + ord(c1))
functions = [
- (func_int, lltype.Signed, 655360),
- (func_int, rffi.SHORT, 1213),
- (func_char, lltype.Char, 12)
+ (func_int, lltype.Signed, types.sint, 655360),
+ (func_int, rffi.SHORT, types.sint16, 1213),
+ (func_char, lltype.Char, types.uchar, 12)
]
- for func, TP, num in functions:
+ for func, TP, ffi_type, num in functions:
cpu = self.cpu
#
FPTR = self.Ptr(self.FuncType([TP, TP], TP))
func_ptr = llhelper(FPTR, func)
FUNC = deref(FPTR)
- calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
funcbox = self.get_funcbox(cpu, func_ptr)
+ # first, try it with the "normal" calldescr
+ calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
res = self.execute_operation(rop.CALL,
[funcbox, BoxInt(num), BoxInt(num)],
'int', descr=calldescr)
assert res.value == 2 * num
+ # then, try it with the dynamic calldescr
+ dyn_calldescr = cpu.calldescrof_dynamic([ffi_type, ffi_type], ffi_type)
+ res = self.execute_operation(rop.CALL,
+ [funcbox, BoxInt(num), BoxInt(num)],
+ 'int', descr=dyn_calldescr)
+ assert res.value == 2 * num
+
if cpu.supports_floats:
def func(f0, f1, f2, f3, f4, f5, f6, i0, i1, f7, f8, f9):
@@ -507,6 +516,23 @@
'int', descr=calldescr)
assert res.value == func_ints(*args)
+ def test_call_to_c_function(self):
+ from pypy.rlib.libffi import CDLL, types, ArgChain
+ libc = CDLL('libc.so.6')
+ c_tolower = libc.getpointer('tolower', [types.uchar], types.sint)
+ argchain = ArgChain().arg(ord('A'))
+ assert c_tolower.call(argchain, rffi.INT) == ord('a')
+
+ func_adr = llmemory.cast_ptr_to_adr(c_tolower.funcsym)
+ funcbox = ConstInt(heaptracker.adr2int(func_adr))
+ calldescr = self.cpu.calldescrof_dynamic([types.uchar], types.sint)
+ res = self.execute_operation(rop.CALL,
+ [funcbox, BoxInt(ord('A'))],
+ 'int',
+ descr=calldescr)
+ assert res.value == ord('a')
+
+
def test_field_basic(self):
t_box, T_box = self.alloc_instance(self.T)
fielddescr = self.cpu.fielddescrof(self.S, 'value')
Modified: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py (original)
+++ pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py Mon Oct 18 16:45:16 2010
@@ -191,6 +191,33 @@
def run_orig(self, name, n, x):
self.main_allfuncs(name, n, x)
+ def define_libffi_workaround(cls):
+ # XXX: this is a workaround for a bug in database.py. It seems that
+ # the problem is triggered by optimizeopt/fficall.py, and in
+ # particular by the ``cast_base_ptr_to_instance(Func, llfunc)``: in
+ # these tests, that line is the only place where libffi.Func is
+ # referenced.
+ #
+ # The problem occurs because the gctransformer tries to annotate a
+ # low-level helper to call the __del__ of libffi.Func when it's too
+ # late.
+ #
+ # This workaround works by forcing the annotator (and all the rest of
+ # the toolchain) to see libffi.Func in a "proper" context, not just as
+ # the target of cast_base_ptr_to_instance. Note that the function
+ # below is *never* called by any actual test, it's just annotated.
+ #
+ from pypy.rlib.libffi import get_libc_name, CDLL, types, ArgChain
+ libc_name = get_libc_name()
+ def f(n, x, *args):
+ libc = CDLL(libc_name)
+ ptr = libc.getpointer('labs', [types.slong], types.slong)
+ chain = ArgChain()
+ chain.arg(n)
+ n = ptr.call(chain, lltype.Signed)
+ return (n, x) + args
+ return None, f, None
+
def define_compile_framework_1(cls):
# a moving GC. Supports malloc_varsize_nonmovable. Simple test, works
# without write_barriers and root stack enumeration.
Modified: pypy/trunk/pypy/jit/backend/x86/test/test_ztranslation.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/test/test_ztranslation.py (original)
+++ pypy/trunk/pypy/jit/backend/x86/test/test_ztranslation.py Mon Oct 18 16:45:16 2010
@@ -1,4 +1,4 @@
-import py, os
+import py, os, sys
from pypy.tool.udir import udir
from pypy.rlib.jit import JitDriver, OPTIMIZER_FULL, unroll_parameters
from pypy.rlib.jit import PARAMETERS, dont_look_inside
@@ -63,8 +63,32 @@
if k - abs(j): raise ValueError
if k - abs(-j): raise ValueError
return total * 10
+ #
+ from pypy.rpython.lltypesystem import lltype, rffi
+ from pypy.rlib.libffi import types, CDLL, ArgChain
+ from pypy.rlib.test.test_libffi import get_libm_name
+ libm_name = get_libm_name(sys.platform)
+ jitdriver2 = JitDriver(greens=[], reds = ['i', 'func', 'res', 'x'])
+ def libffi_stuff(i, j):
+ lib = CDLL(libm_name)
+ func = lib.getpointer('fabs', [types.double], types.double)
+ res = 0.0
+ x = float(j)
+ while i > 0:
+ jitdriver2.jit_merge_point(i=i, res=res, func=func, x=x)
+ jitdriver2.can_enter_jit(i=i, res=res, func=func, x=x)
+ func = hint(func, promote=True)
+ argchain = ArgChain()
+ argchain.arg(x)
+ res = func.call(argchain, rffi.DOUBLE)
+ i -= 1
+ return res
+ #
+ def main(i, j):
+ return f(i, j) + libffi_stuff(i, j)
+ expected = f(40, -49)
res = self.meta_interp(f, [40, -49])
- assert res == f(40, -49)
+ assert res == expected
def test_direct_assembler_call_translates(self):
class Thing(object):
Modified: pypy/trunk/pypy/jit/codewriter/effectinfo.py
==============================================================================
--- pypy/trunk/pypy/jit/codewriter/effectinfo.py (original)
+++ pypy/trunk/pypy/jit/codewriter/effectinfo.py Mon Oct 18 16:45:16 2010
@@ -19,7 +19,7 @@
OS_NONE = 0 # normal case, no oopspec
OS_ARRAYCOPY = 1 # "list.ll_arraycopy"
OS_STR2UNICODE = 2 # "str.str2unicode"
-
+ #
OS_STR_CONCAT = 22 # "stroruni.concat"
OS_STR_SLICE = 23 # "stroruni.slice"
OS_STR_EQUAL = 24 # "stroruni.equal"
@@ -30,7 +30,7 @@
OS_STREQ_NONNULL_CHAR = 29 # s1 == char (assert s1!=NULL)
OS_STREQ_CHECKNULL_CHAR = 30 # s1!=NULL and s1==char
OS_STREQ_LENGTHOK = 31 # s1 == s2 (assert len(s1)==len(s2))
-
+ #
OS_UNI_CONCAT = 42 #
OS_UNI_SLICE = 43 #
OS_UNI_EQUAL = 44 #
@@ -42,6 +42,10 @@
OS_UNIEQ_CHECKNULL_CHAR = 50 # STR, in the same order)
OS_UNIEQ_LENGTHOK = 51 #
_OS_offset_uni = OS_UNI_CONCAT - OS_STR_CONCAT
+ #
+ OS_LIBFFI_PREPARE = 60
+ OS_LIBFFI_PUSH_ARG = 61
+ OS_LIBFFI_CALL = 62
def __new__(cls, readonly_descrs_fields,
write_descrs_fields, write_descrs_arrays,
Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/trunk/pypy/jit/codewriter/jtransform.py (original)
+++ pypy/trunk/pypy/jit/codewriter/jtransform.py Mon Oct 18 16:45:16 2010
@@ -320,6 +320,8 @@
prepare = self._handle_str2unicode_call
elif oopspec_name.startswith('virtual_ref'):
prepare = self._handle_virtual_ref_call
+ elif oopspec_name.startswith('libffi_'):
+ prepare = self._handle_libffi_call
else:
prepare = self.prepare_builtin_call
try:
@@ -1030,8 +1032,10 @@
# ----------
# Strings and Unicodes.
- def _handle_oopspec_call(self, op, args, oopspecindex):
+ def _handle_oopspec_call(self, op, args, oopspecindex, extraeffect=None):
calldescr = self.callcontrol.getcalldescr(op, oopspecindex)
+ if extraeffect:
+ calldescr.get_extra_info().extraeffect = extraeffect
if isinstance(op.args[0].value, str):
pass # for tests only
else:
@@ -1132,6 +1136,23 @@
vrefinfo.JIT_VIRTUAL_REF)
return SpaceOperation(oopspec_name, list(args), op.result)
+ # -----------
+ # rlib.libffi
+
+ def _handle_libffi_call(self, op, oopspec_name, args):
+ if oopspec_name == 'libffi_prepare_call':
+ oopspecindex = EffectInfo.OS_LIBFFI_PREPARE
+ extraeffect = EffectInfo.EF_CANNOT_RAISE
+ elif oopspec_name.startswith('libffi_push_'):
+ oopspecindex = EffectInfo.OS_LIBFFI_PUSH_ARG
+ extraeffect = EffectInfo.EF_CANNOT_RAISE
+ elif oopspec_name.startswith('libffi_call_'):
+ oopspecindex = EffectInfo.OS_LIBFFI_CALL
+ extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
+ else:
+ assert False, 'unsupported oopspec: %s' % oopspec_name
+ return self._handle_oopspec_call(op, args, oopspecindex, extraeffect)
+
def rewrite_op_jit_force_virtual(self, op):
return self._do_builtin_call(op)
Modified: pypy/trunk/pypy/jit/codewriter/support.py
==============================================================================
--- pypy/trunk/pypy/jit/codewriter/support.py (original)
+++ pypy/trunk/pypy/jit/codewriter/support.py Mon Oct 18 16:45:16 2010
@@ -1,5 +1,5 @@
import sys
-from pypy.rpython.lltypesystem import lltype, rclass
+from pypy.rpython.lltypesystem import lltype, rclass, rffi
from pypy.rpython.ootypesystem import ootype
from pypy.rpython import rlist
from pypy.rpython.lltypesystem import rstr as ll_rstr, rdict as ll_rdict
@@ -8,6 +8,7 @@
from pypy.rpython.ootypesystem import rdict as oo_rdict
from pypy.rpython.llinterp import LLInterpreter
from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
from pypy.translator.simplify import get_funcobj
from pypy.translator.unsimplify import split_block
from pypy.objspace.flow.model import Constant
@@ -217,6 +218,33 @@
else:
return x
+
+# libffi support
+# --------------
+
+def func(llfunc):
+ from pypy.rlib.libffi import Func
+ return cast_base_ptr_to_instance(Func, llfunc)
+
+def _ll_1_libffi_prepare_call(llfunc):
+ return func(llfunc)._prepare()
+
+def _ll_4_libffi_push_int(llfunc, value, ll_args, i):
+ return func(llfunc)._push_int(value, ll_args, i)
+
+def _ll_4_libffi_push_float(llfunc, value, ll_args, i):
+ return func(llfunc)._push_float(value, ll_args, i)
+
+def _ll_3_libffi_call_int(llfunc, funcsym, ll_args):
+ return func(llfunc)._do_call(funcsym, ll_args, rffi.LONG)
+
+def _ll_3_libffi_call_float(llfunc, funcsym, ll_args):
+ return func(llfunc)._do_call(funcsym, ll_args, rffi.DOUBLE)
+
+def _ll_3_libffi_call_void(llfunc, funcsym, ll_args):
+ return func(llfunc)._do_call(funcsym, ll_args, lltype.Void)
+
+
# in the following calls to builtins, the JIT is allowed to look inside:
inline_calls_to = [
('int_floordiv_ovf_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
Modified: pypy/trunk/pypy/jit/codewriter/test/test_effectinfo.py
==============================================================================
--- pypy/trunk/pypy/jit/codewriter/test/test_effectinfo.py (original)
+++ pypy/trunk/pypy/jit/codewriter/test/test_effectinfo.py Mon Oct 18 16:45:16 2010
@@ -1,7 +1,8 @@
from pypy.rpython.lltypesystem.rclass import OBJECT
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.ootypesystem import ootype
-from pypy.jit.codewriter.effectinfo import effectinfo_from_writeanalyze
+from pypy.jit.codewriter.effectinfo import effectinfo_from_writeanalyze,\
+ EffectInfo
class FakeCPU:
def fielddescrof(self, T, fieldname):
@@ -9,6 +10,14 @@
def arraydescrof(self, A):
return ('arraydescr', A)
+def test_no_oopspec_duplicate():
+ # check that all the various EffectInfo.OS_* have unique values
+ oopspecs = set()
+ for name, value in EffectInfo.__dict__.iteritems():
+ if name.startswith('OS_'):
+ assert value not in oopspecs
+ oopspecs.add(value)
+
def test_include_read_field():
S = lltype.GcStruct("S", ("a", lltype.Signed))
effects = frozenset([("readstruct", lltype.Ptr(S), "a")])
Modified: pypy/trunk/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/executor.py (original)
+++ pypy/trunk/pypy/jit/metainterp/executor.py Mon Oct 18 16:45:16 2010
@@ -80,6 +80,9 @@
do_call_loopinvariant = do_call
do_call_may_force = do_call
+def do_call_c(cpu, metainterp, argboxes, descr):
+ raise NotImplementedError("Should never be called directly")
+
def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr):
array = arraybox.getref_base()
index = indexbox.getint()
Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt/__init__.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizeopt/__init__.py (original)
+++ pypy/trunk/pypy/jit/metainterp/optimizeopt/__init__.py Mon Oct 18 16:45:16 2010
@@ -3,6 +3,7 @@
from pypy.jit.metainterp.optimizeopt.intbounds import OptIntBounds
from pypy.jit.metainterp.optimizeopt.virtualize import OptVirtualize
from pypy.jit.metainterp.optimizeopt.heap import OptHeap
+from pypy.jit.metainterp.optimizeopt.fficall import OptFfiCall
from pypy.jit.metainterp.optimizeopt.string import OptString
def optimize_loop_1(metainterp_sd, loop, virtuals=True):
@@ -16,6 +17,7 @@
OptVirtualize(),
OptString(),
OptHeap(),
+ OptFfiCall(),
]
optimizer = Optimizer(metainterp_sd, loop, optimizations, virtuals)
optimizer.propagate_all_forward()
Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt/virtualize.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizeopt/virtualize.py (original)
+++ pypy/trunk/pypy/jit/metainterp/optimizeopt/virtualize.py Mon Oct 18 16:45:16 2010
@@ -134,6 +134,11 @@
fielddescrs = self._get_field_descr_list()
return modifier.make_virtual(self.known_class, fielddescrs)
+ def __repr__(self):
+ cls_name = self.known_class.value.adr.ptr._obj._TYPE._name
+ field_names = [field.name for field in self._fields]
+ return "<VirtualValue cls=%s fields=%s>" % (cls_name, field_names)
+
class VStructValue(AbstractVirtualStructValue):
def __init__(self, optimizer, structdescr, keybox, source_op=None):
Modified: pypy/trunk/pypy/jit/metainterp/resoperation.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/resoperation.py (original)
+++ pypy/trunk/pypy/jit/metainterp/resoperation.py Mon Oct 18 16:45:16 2010
@@ -463,7 +463,7 @@
'_CANRAISE_FIRST', # ----- start of can_raise operations -----
'CALL/*d',
- 'CALL_ASSEMBLER/*d',
+ 'CALL_ASSEMBLER/*d', # call already compiled assembler
'CALL_MAY_FORCE/*d',
'CALL_LOOPINVARIANT/*d',
#'OOSEND', # ootype operation
Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py Mon Oct 18 16:45:16 2010
@@ -132,14 +132,21 @@
# ____________________________________________________________
def equaloplists(oplist1, oplist2, strict_fail_args=True, remap={}):
- print '-'*20, 'Comparing lists', '-'*20
+ # try to use the full width of the terminal to display the list
+ # unfortunately, does not work with the default capture method of py.test
+ # (which is fd), you you need to use either -s or --capture=sys, else you
+ # get the standard 80 columns width
+ totwidth = py.io.get_terminal_width()
+ width = totwidth / 2 - 1
+ print ' Comparing lists '.center(totwidth, '-')
+ print '%s| %s' % ('optimized'.center(width), 'expected'.center(width))
for op1, op2 in zip(oplist1, oplist2):
txt1 = str(op1)
txt2 = str(op2)
while txt1 or txt2:
- print '%-39s| %s' % (txt1[:39], txt2[:39])
- txt1 = txt1[39:]
- txt2 = txt2[39:]
+ print '%s| %s' % (txt1[:width].ljust(width), txt2[:width])
+ txt1 = txt1[width:]
+ txt2 = txt2[width:]
assert op1.getopnum() == op2.getopnum()
assert op1.numargs() == op2.numargs()
for i in range(op1.numargs()):
@@ -262,6 +269,10 @@
expected = self.parse(optops)
print '\n'.join([str(o) for o in loop.operations])
self.assert_equal(loop, expected)
+ return loop
+
+
+class OptimizeOptTest(BaseTestOptimizeOpt):
def test_simple(self):
ops = """
@@ -2643,7 +2654,7 @@
''', rop.GUARD_TRUE)
-class TestLLtype(BaseTestOptimizeOpt, LLtypeMixin):
+class TestLLtype(OptimizeOptTest, LLtypeMixin):
def test_residual_call_does_not_invalidate_caches(self):
ops = """
@@ -4533,7 +4544,7 @@
# can be raised by ll_str2unicode()
-##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin):
+##class TestOOtype(OptimizeOptTest, OOtypeMixin):
## def test_instanceof(self):
## ops = """
Modified: pypy/trunk/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/warmstate.py (original)
+++ pypy/trunk/pypy/jit/metainterp/warmstate.py Mon Oct 18 16:45:16 2010
@@ -1,5 +1,5 @@
import sys
-from pypy.rpython.lltypesystem import lltype, llmemory, rstr
+from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.annlowlevel import hlstr, llstr, cast_base_ptr_to_instance
from pypy.rpython.annlowlevel import cast_object_to_ptr
@@ -24,7 +24,11 @@
"""
INPUT = lltype.typeOf(x)
if INPUT is lltype.Signed:
- return lltype.cast_primitive(TYPE, x) # XXX missing: Ptr(non-gc)
+ if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'raw':
+ # non-gc pointer
+ return rffi.cast(TYPE, x)
+ else:
+ return lltype.cast_primitive(TYPE, x)
elif INPUT is lltype.Float:
assert TYPE is lltype.Float
return x
Modified: pypy/trunk/pypy/jit/tl/pypyjit.py
==============================================================================
--- pypy/trunk/pypy/jit/tl/pypyjit.py (original)
+++ pypy/trunk/pypy/jit/tl/pypyjit.py Mon Oct 18 16:45:16 2010
@@ -40,6 +40,9 @@
config.objspace.usemodules.array = True
config.objspace.usemodules._weakref = False
config.objspace.usemodules._sre = False
+#
+config.objspace.usemodules._ffi = True
+#
set_pypy_opt_level(config, level='jit')
config.objspace.std.withinlineddict = True
Modified: pypy/trunk/pypy/jit/tl/pypyjit_child.py
==============================================================================
--- pypy/trunk/pypy/jit/tl/pypyjit_child.py (original)
+++ pypy/trunk/pypy/jit/tl/pypyjit_child.py Mon Oct 18 16:45:16 2010
@@ -16,7 +16,7 @@
interp.heap.malloc_nonmovable = returns_null # XXX
from pypy.jit.backend.llgraph.runner import LLtypeCPU
- LLtypeCPU.supports_floats = False # for now
+ #LLtypeCPU.supports_floats = False # for now
apply_jit(interp, graph, LLtypeCPU)
Modified: pypy/trunk/pypy/module/_rawffi/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/_rawffi/__init__.py (original)
+++ pypy/trunk/pypy/module/_rawffi/__init__.py Mon Oct 18 16:45:16 2010
@@ -1,5 +1,5 @@
-""" Low-level interface to libffi
+""" Low-level interface to clibffi
"""
from pypy.interpreter.mixedmodule import MixedModule
@@ -39,11 +39,11 @@
if hasattr(interp_rawffi, 'check_HRESULT'):
Module.interpleveldefs['check_HRESULT'] = 'interp_rawffi.check_HRESULT'
- from pypy.rlib import libffi
+ from pypy.rlib import clibffi
for name in ['FUNCFLAG_STDCALL', 'FUNCFLAG_CDECL', 'FUNCFLAG_PYTHONAPI',
]:
- if hasattr(libffi, name):
- Module.interpleveldefs[name] = "space.wrap(%r)" % getattr(libffi, name)
+ if hasattr(clibffi, name):
+ Module.interpleveldefs[name] = "space.wrap(%r)" % getattr(clibffi, name)
super(Module, cls).buildloaders()
buildloaders = classmethod(buildloaders)
Modified: pypy/trunk/pypy/module/_rawffi/callback.py
==============================================================================
--- pypy/trunk/pypy/module/_rawffi/callback.py (original)
+++ pypy/trunk/pypy/module/_rawffi/callback.py Mon Oct 18 16:45:16 2010
@@ -8,8 +8,8 @@
from pypy.module._rawffi.array import get_elem, push_elem
from pypy.module._rawffi.interp_rawffi import W_DataInstance, letter2tp, \
wrap_value, unwrap_value, unwrap_truncate_int
-from pypy.rlib.libffi import USERDATA_P, CallbackFuncPtr, FUNCFLAG_CDECL
-from pypy.rlib.libffi import ffi_type_void
+from pypy.rlib.clibffi import USERDATA_P, CallbackFuncPtr, FUNCFLAG_CDECL
+from pypy.rlib.clibffi import ffi_type_void
from pypy.module._rawffi.tracker import tracker
from pypy.interpreter.error import OperationError
from pypy.interpreter import gateway
Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py
==============================================================================
--- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original)
+++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Mon Oct 18 16:45:16 2010
@@ -5,7 +5,7 @@
from pypy.interpreter.gateway import interp2app, NoneNotWrapped
from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.rlib.libffi import *
+from pypy.rlib.clibffi import *
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rlib.unroll import unrolling_iterable
Modified: pypy/trunk/pypy/module/_rawffi/structure.py
==============================================================================
--- pypy/trunk/pypy/module/_rawffi/structure.py (original)
+++ pypy/trunk/pypy/module/_rawffi/structure.py Mon Oct 18 16:45:16 2010
@@ -15,7 +15,7 @@
from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value
from pypy.module._rawffi.interp_rawffi import unpack_shape_with_length
from pypy.module._rawffi.interp_rawffi import size_alignment
-from pypy.rlib import libffi
+from pypy.rlib import clibffi
from pypy.rlib.rarithmetic import intmask, r_uint
def unpack_fields(space, w_fields):
@@ -104,14 +104,14 @@
descr_fieldoffset.unwrap_spec = ['self', ObjSpace, str]
# get the corresponding ffi_type
- ffi_struct = lltype.nullptr(libffi.FFI_STRUCT_P.TO)
+ ffi_struct = lltype.nullptr(clibffi.FFI_STRUCT_P.TO)
def get_basic_ffi_type(self):
if not self.ffi_struct:
# Repeated fields are delicate. Consider for example
# struct { int a[5]; }
# or struct { struct {int x;} a[5]; }
- # Seeing no corresponding doc in libffi, let's just repeat
+ # Seeing no corresponding doc in clibffi, let's just repeat
# the field 5 times...
fieldtypes = []
for name, tp in self.fields:
@@ -122,7 +122,7 @@
while count + basic_size <= total_size:
fieldtypes.append(basic_ffi_type)
count += basic_size
- self.ffi_struct = libffi.make_struct_ffitype_e(self.size,
+ self.ffi_struct = clibffi.make_struct_ffitype_e(self.size,
self.alignment,
fieldtypes)
return self.ffi_struct.ffistruct
Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py
==============================================================================
--- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original)
+++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Mon Oct 18 16:45:16 2010
@@ -191,7 +191,7 @@
prepare_c_example = staticmethod(prepare_c_example)
def setup_class(cls):
- from pypy.rlib.libffi import get_libc_name
+ from pypy.rlib.clibffi import get_libc_name
space = gettestobjspace(usemodules=('_rawffi', 'struct'))
cls.space = space
cls.w_lib_name = space.wrap(cls.prepare_c_example())
Modified: pypy/trunk/pypy/module/pypyjit/policy.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/policy.py (original)
+++ pypy/trunk/pypy/module/pypyjit/policy.py Mon Oct 18 16:45:16 2010
@@ -11,7 +11,7 @@
if '.' in modname:
modname, _ = modname.split('.', 1)
if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions',
- 'imp', 'sys', 'array']:
+ 'imp', 'sys', 'array', '_ffi']:
return True
return False
Modified: pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py (original)
+++ pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py Mon Oct 18 16:45:16 2010
@@ -79,8 +79,11 @@
class PyPyCJITTests(object):
- def run_source(self, source, expected_max_ops, *testcases):
+ def run_source(self, source, expected_max_ops, *testcases, **kwds):
assert isinstance(expected_max_ops, int)
+ threshold = kwds.pop('threshold', 3)
+ if kwds:
+ raise TypeError, 'Unsupported keyword arguments: %s' % kwds.keys()
source = py.code.Source(source)
filepath = self.tmpdir.join('case%d.py' % self.counter)
logfilepath = filepath.new(ext='.log')
@@ -92,7 +95,7 @@
import sys
try: # make the file runnable by CPython
import pypyjit
- pypyjit.set_param(threshold=3)
+ pypyjit.set_param(threshold=%d)
except ImportError:
pass
@@ -102,7 +105,7 @@
print >> sys.stderr, 'got:', repr(result)
assert result == expected
assert type(result) is type(expected)
- """)
+ """ % threshold)
for testcase in testcases * 2:
print >> f, "check(%r, %r)" % testcase
print >> f, "print 'OK :-)'"
@@ -123,6 +126,7 @@
if self.total_ops > expected_max_ops:
assert 0, "too many operations: got %d, expected maximum %d" % (
self.total_ops, expected_max_ops)
+ return result
def parse_loops(self, opslogfile):
from pypy.jit.metainterp.test.oparser import parse
@@ -1134,6 +1138,39 @@
return sa
''', 88, ([], 1997001))
+ def test__ffi_call(self):
+ from pypy.rlib.test.test_libffi import get_libm_name
+ libm_name = get_libm_name(sys.platform)
+ out = self.run_source('''
+ def main():
+ from _ffi import CDLL, types
+ libm = CDLL('%(libm_name)s')
+ pow = libm.getfunc('pow', [types.double, types.double],
+ types.double)
+ print pow.getaddr()
+ i = 0
+ res = 0
+ while i < 2000:
+ res += pow(2, 3)
+ i += 1
+ return res
+ ''' % locals(),
+ 76, ([], 8.0*2000), threshold=1000)
+ pow_addr = int(out.splitlines()[0])
+ ops = self.get_by_bytecode('CALL_FUNCTION')
+ assert len(ops) == 2 # we get two loops, because of specialization
+ call_function = ops[0]
+ last_ops = [op.getopname() for op in call_function[-5:]]
+ assert last_ops == ['force_token',
+ 'setfield_gc',
+ 'call_may_force',
+ 'guard_not_forced',
+ 'guard_no_exception']
+ call = call_function[-3]
+ assert call.getarg(0).value == pow_addr
+ assert call.getarg(1).value == 2.0
+ assert call.getarg(2).value == 3.0
+
# test_circular
class AppTestJIT(PyPyCJITTests):
Modified: pypy/trunk/pypy/rlib/jit.py
==============================================================================
--- pypy/trunk/pypy/rlib/jit.py (original)
+++ pypy/trunk/pypy/rlib/jit.py Mon Oct 18 16:45:16 2010
@@ -77,6 +77,12 @@
return result
return decorator
+def oopspec(spec):
+ def decorator(func):
+ func.oopspec = spec
+ return func
+ return decorator
+
class Entry(ExtRegistryEntry):
_about_ = hint
Modified: pypy/trunk/pypy/rlib/test/test_jit.py
==============================================================================
--- pypy/trunk/pypy/rlib/test/test_jit.py (original)
+++ pypy/trunk/pypy/rlib/test/test_jit.py Mon Oct 18 16:45:16 2010
@@ -1,10 +1,16 @@
import py
from pypy.rlib.jit import hint, we_are_jitted, JitDriver, purefunction_promote
-from pypy.rlib.jit import JitHintError
+from pypy.rlib.jit import JitHintError, oopspec
from pypy.translator.translator import TranslationContext, graphof
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
from pypy.rpython.lltypesystem import lltype
+def test_oopspec():
+ @oopspec('foobar')
+ def fn():
+ pass
+ assert fn.oopspec == 'foobar'
+
class BaseTestJIT(BaseRtypingTest):
def test_hint(self):
def f():
Modified: pypy/trunk/pypy/rlib/test/test_rdynload.py
==============================================================================
--- pypy/trunk/pypy/rlib/test/test_rdynload.py (original)
+++ pypy/trunk/pypy/rlib/test/test_rdynload.py Mon Oct 18 16:45:16 2010
@@ -1,5 +1,5 @@
from pypy.rlib.rdynload import *
-from pypy.rlib.libffi import get_libc_name
+from pypy.rlib.clibffi import get_libc_name
from pypy.rpython.lltypesystem import rffi, lltype
import py
Modified: pypy/trunk/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/trunk/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/trunk/pypy/rpython/lltypesystem/lltype.py Mon Oct 18 16:45:16 2010
@@ -794,6 +794,8 @@
return llmemory.cast_adr_to_ptr(value, TGT)
elif TGT == llmemory.Address and isinstance(ORIG, Ptr):
return llmemory.cast_ptr_to_adr(value)
+ elif TGT == Signed and isinstance(ORIG, Ptr) and ORIG.TO._gckind == 'raw':
+ return llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(value), 'symbolic')
raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT))
Modified: pypy/trunk/pypy/rpython/rpbc.py
==============================================================================
--- pypy/trunk/pypy/rpython/rpbc.py (original)
+++ pypy/trunk/pypy/rpython/rpbc.py Mon Oct 18 16:45:16 2010
@@ -256,6 +256,8 @@
def convert_const(self, value):
if isinstance(value, types.MethodType) and value.im_self is None:
value = value.im_func # unbound method -> bare function
+ elif isinstance(value, staticmethod):
+ value = value.__get__(42) # hackish, get the function wrapped by staticmethod
if self.lowleveltype is Void:
return None
if value is None:
Modified: pypy/trunk/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/trunk/pypy/rpython/test/test_rclass.py (original)
+++ pypy/trunk/pypy/rpython/test/test_rclass.py Mon Oct 18 16:45:16 2010
@@ -319,6 +319,17 @@
res = self.interpret(f, [])
assert res == 42
+ def test_staticmethod2(self):
+ class A(object):
+ f = staticmethod(lambda x, y: x*y)
+ class B(A):
+ f = staticmethod(lambda x, y: x+y)
+ def f():
+ b = B()
+ return b.f(6, 7)
+ res = self.interpret(f, [])
+ assert res == 13
+
def test_is(self):
class A: pass
class B(A): pass
Modified: pypy/trunk/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/trunk/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/trunk/pypy/translator/c/test/test_newgc.py Mon Oct 18 16:45:16 2010
@@ -624,13 +624,13 @@
os.unlink(self.filename)
def define_callback_with_collect(cls):
- from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\
+ from pypy.rlib.clibffi import ffi_type_pointer, cast_type_to_ffitype,\
CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint
from pypy.rpython.lltypesystem import rffi, ll2ctypes
import gc
ffi_size_t = cast_type_to_ffitype(rffi.SIZE_T)
- from pypy.rlib.libffi import get_libc_name
+ from pypy.rlib.clibffi import get_libc_name
def callback(ll_args, ll_res, stuff):
gc.collect()
More information about the Pypy-commit
mailing list