[pypy-commit] pypy numpy-dtype-refactor: merged default in
alex_gaynor
noreply at buildbot.pypy.org
Tue Nov 15 23:13:11 CET 2011
Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: numpy-dtype-refactor
Changeset: r49448:0b6ec862fb6e
Date: 2011-11-15 17:01 -0500
http://bitbucket.org/pypy/pypy/changeset/0b6ec862fb6e/
Log: merged default in
diff --git a/pypy/interpreter/test/test_executioncontext.py b/pypy/interpreter/test/test_executioncontext.py
--- a/pypy/interpreter/test/test_executioncontext.py
+++ b/pypy/interpreter/test/test_executioncontext.py
@@ -292,7 +292,7 @@
import os, sys
print sys.executable, self.tmpfile
if sys.platform == "win32":
- cmdformat = '""%s" "%s""' # excellent! tons of "!
+ cmdformat = '"%s" "%s"'
else:
cmdformat = "'%s' '%s'"
g = os.popen(cmdformat % (sys.executable, self.tmpfile), 'r')
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -20,6 +20,7 @@
from pypy.jit.backend.llgraph import symbolic
from pypy.jit.codewriter import longlong
+from pypy.rlib import libffi
from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
from pypy.rlib.rarithmetic import ovfcheck
from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
@@ -325,12 +326,12 @@
loop = _from_opaque(loop)
loop.operations.append(Operation(opnum))
-def compile_add_descr(loop, ofs, type, arg_types):
+def compile_add_descr(loop, ofs, type, arg_types, extrainfo, width):
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, arg_types=arg_types)
+ op.descr = Descr(ofs, type, arg_types=arg_types, extrainfo=extrainfo, width=width)
def compile_add_descr_arg(loop, ofs, type, arg_types):
from pypy.jit.backend.llgraph.runner import Descr
@@ -825,6 +826,16 @@
else:
raise NotImplementedError
+ def op_getinteriorfield_raw(self, descr, array, index):
+ if descr.typeinfo == REF:
+ return do_getinteriorfield_raw_ptr(array, index, descr.width, descr.ofs)
+ elif descr.typeinfo == INT:
+ return do_getinteriorfield_raw_int(array, index, descr.width, descr.ofs)
+ elif descr.typeinfo == FLOAT:
+ return do_getinteriorfield_raw_float(array, index, descr.width, descr.ofs)
+ else:
+ raise NotImplementedError
+
def op_setinteriorfield_gc(self, descr, array, index, newvalue):
if descr.typeinfo == REF:
return do_setinteriorfield_gc_ptr(array, index, descr.ofs,
@@ -838,6 +849,16 @@
else:
raise NotImplementedError
+ def op_setinteriorfield_raw(self, descr, array, index, newvalue):
+ if descr.typeinfo == REF:
+ return do_setinteriorfield_raw_ptr(array, index, newvalue, descr.width, descr.ofs)
+ elif descr.typeinfo == INT:
+ return do_setinteriorfield_raw_int(array, index, newvalue, descr.width, descr.ofs)
+ elif descr.typeinfo == FLOAT:
+ return do_setinteriorfield_raw_float(array, index, newvalue, descr.width, descr.ofs)
+ else:
+ raise NotImplementedError
+
def op_setfield_gc(self, fielddescr, struct, newvalue):
if fielddescr.typeinfo == REF:
do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
@@ -1403,6 +1424,14 @@
struct = array._obj.container.getitem(index)
return cast_to_ptr(_getinteriorfield_gc(struct, fieldnum))
+def _getinteriorfield_raw(ffitype, array, index, width, ofs):
+ addr = rffi.cast(rffi.VOIDP, array)
+ return libffi.array_getitem(ffitype, width, addr, index, ofs)
+
+def do_getinteriorfield_raw_int(array, index, width, ofs):
+ res = _getinteriorfield_raw(libffi.types.slong, array, index, width, ofs)
+ return res
+
def _getfield_raw(struct, fieldnum):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
ptr = cast_from_int(lltype.Ptr(STRUCT), struct)
@@ -1479,7 +1508,14 @@
return do_setinteriorfield_gc
do_setinteriorfield_gc_int = new_setinteriorfield_gc(cast_from_int)
do_setinteriorfield_gc_float = new_setinteriorfield_gc(cast_from_floatstorage)
-do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)
+do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)
+
+def new_setinteriorfield_raw(ffitype):
+ def do_setinteriorfield_raw(array, index, newvalue, width, ofs):
+ addr = rffi.cast(rffi.VOIDP, array)
+ return libffi.array_setitem(ffitype, width, addr, index, ofs, newvalue)
+ return do_setinteriorfield_raw
+do_setinteriorfield_raw_int = new_setinteriorfield_raw(libffi.types.slong)
def do_setfield_raw_int(struct, fieldnum, newvalue):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -23,8 +23,10 @@
class Descr(history.AbstractDescr):
def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
- arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
+ arg_types=None, count_fields_if_immut=-1, ffi_flags=0, width=-1):
+
self.ofs = ofs
+ self.width = width
self.typeinfo = typeinfo
self.extrainfo = extrainfo
self.name = name
@@ -119,14 +121,14 @@
return False
def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
- arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
+ arg_types=None, count_fields_if_immut=-1, ffi_flags=0, width=-1):
key = (ofs, typeinfo, extrainfo, name, arg_types,
- count_fields_if_immut, ffi_flags)
+ count_fields_if_immut, ffi_flags, width)
try:
return self._descrs[key]
except KeyError:
descr = Descr(ofs, typeinfo, extrainfo, name, arg_types,
- count_fields_if_immut, ffi_flags)
+ count_fields_if_immut, ffi_flags, width)
self._descrs[key] = descr
return descr
@@ -179,7 +181,8 @@
descr = op.getdescr()
if isinstance(descr, Descr):
llimpl.compile_add_descr(c, descr.ofs, descr.typeinfo,
- descr.arg_types)
+ descr.arg_types, descr.extrainfo,
+ descr.width)
if (isinstance(descr, history.LoopToken) and
op.getopnum() != rop.JUMP):
llimpl.compile_add_loop_token(c, descr)
@@ -324,10 +327,22 @@
def interiorfielddescrof(self, A, fieldname):
S = A.OF
- ofs2 = symbolic.get_size(A)
+ width = symbolic.get_size(A)
ofs, size = symbolic.get_field_token(S, fieldname)
token = history.getkind(getattr(S, fieldname))
- return self.getdescr(ofs, token[0], name=fieldname, extrainfo=ofs2)
+ return self.getdescr(ofs, token[0], name=fieldname, width=width)
+
+ def interiorfielddescrof_dynamic(self, offset, width, fieldsize,
+ is_pointer, is_float, is_signed):
+
+ if is_pointer:
+ typeinfo = REF
+ elif is_float:
+ typeinfo = FLOAT
+ else:
+ typeinfo = INT
+ # we abuse the arg_types field to distinguish dynamic and static descrs
+ return Descr(offset, typeinfo, arg_types='dynamic', name='<dynamic interior field>', width=width)
def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
arg_types = []
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -111,6 +111,16 @@
def repr_of_descr(self):
return '<%s %s %s>' % (self._clsname, self.name, self.offset)
+class DynamicFieldDescr(BaseFieldDescr):
+ def __init__(self, offset, fieldsize, is_pointer, is_float, is_signed):
+ self.offset = offset
+ self._fieldsize = fieldsize
+ self._is_pointer_field = is_pointer
+ self._is_float_field = is_float
+ self._is_field_signed = is_signed
+
+ def get_field_size(self, translate_support_code):
+ return self._fieldsize
class NonGcPtrFieldDescr(BaseFieldDescr):
_clsname = 'NonGcPtrFieldDescr'
@@ -182,6 +192,7 @@
def repr_of_descr(self):
return '<%s>' % self._clsname
+
class NonGcPtrArrayDescr(BaseArrayDescr):
_clsname = 'NonGcPtrArrayDescr'
def get_item_size(self, translate_support_code):
@@ -211,6 +222,13 @@
def get_ofs_length(self, translate_support_code):
return -1
+class DynamicArrayNoLengthDescr(BaseArrayNoLengthDescr):
+ def __init__(self, itemsize):
+ self.itemsize = itemsize
+
+ def get_item_size(self, translate_support_code):
+ return self.itemsize
+
class NonGcPtrArrayNoLengthDescr(BaseArrayNoLengthDescr):
_clsname = 'NonGcPtrArrayNoLengthDescr'
def get_item_size(self, translate_support_code):
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -9,9 +9,10 @@
from pypy.jit.backend.llsupport import symbolic
from pypy.jit.backend.llsupport.symbolic import WORD, unroll_basic_sizes
from pypy.jit.backend.llsupport.descr import (get_size_descr,
- get_field_descr, BaseFieldDescr, get_array_descr, BaseArrayDescr,
- get_call_descr, BaseIntCallDescr, GcPtrCallDescr, FloatCallDescr,
- VoidCallDescr, InteriorFieldDescr, get_interiorfield_descr)
+ get_field_descr, BaseFieldDescr, DynamicFieldDescr, get_array_descr,
+ BaseArrayDescr, DynamicArrayNoLengthDescr, get_call_descr,
+ BaseIntCallDescr, GcPtrCallDescr, FloatCallDescr, VoidCallDescr,
+ InteriorFieldDescr, get_interiorfield_descr)
from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
@@ -238,6 +239,12 @@
def interiorfielddescrof(self, A, fieldname):
return get_interiorfield_descr(self.gc_ll_descr, A, A.OF, fieldname)
+ def interiorfielddescrof_dynamic(self, offset, width, fieldsize,
+ is_pointer, is_float, is_signed):
+ arraydescr = DynamicArrayNoLengthDescr(width)
+ fielddescr = DynamicFieldDescr(offset, fieldsize, is_pointer, is_float, is_signed)
+ return InteriorFieldDescr(arraydescr, fielddescr)
+
def unpack_arraydescr(self, arraydescr):
assert isinstance(arraydescr, BaseArrayDescr)
return arraydescr.get_base_size(self.translate_support_code)
diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -183,38 +183,35 @@
lst[n] = None
self.fail_descr_free_list.extend(faildescr_indices)
- @staticmethod
- def sizeof(S):
+ def sizeof(self, S):
raise NotImplementedError
- @staticmethod
- def fielddescrof(S, fieldname):
+ def fielddescrof(self, S, fieldname):
"""Return the Descr corresponding to field 'fieldname' on the
structure 'S'. It is important that this function (at least)
caches the results."""
raise NotImplementedError
- @staticmethod
- def arraydescrof(A):
+ def interiorfielddescrof(self, A, fieldname):
raise NotImplementedError
- @staticmethod
- def calldescrof(FUNC, ARGS, RESULT):
+ def interiorfielddescrof_dynamic(self, offset, width, fieldsize, is_pointer,
+ is_float, is_signed):
+ raise NotImplementedError
+
+ def arraydescrof(self, A):
+ raise NotImplementedError
+
+ def calldescrof(self, FUNC, ARGS, RESULT):
# FUNC is the original function type, but ARGS is a list of types
# with Voids removed
raise NotImplementedError
- @staticmethod
- def methdescrof(SELFTYPE, methname):
+ def methdescrof(self, SELFTYPE, methname):
# must return a subclass of history.AbstractMethDescr
raise NotImplementedError
- @staticmethod
- def typedescrof(TYPE):
- raise NotImplementedError
-
- @staticmethod
- def interiorfielddescrof(A, fieldname):
+ def typedescrof(self, TYPE):
raise NotImplementedError
# ---------- the backend-dependent operations ----------
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -8,8 +8,8 @@
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.annlowlevel import llhelper
from pypy.jit.backend.model import CompiledLoopToken
-from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs,
- _get_scale, gpr_reg_mgr_cls)
+from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale,
+ gpr_reg_mgr_cls, _valid_addressing_size)
from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD,
IS_X86_32, IS_X86_64)
@@ -1601,8 +1601,10 @@
assert isinstance(itemsize_loc, ImmedLoc)
if isinstance(index_loc, ImmedLoc):
temp_loc = imm(index_loc.value * itemsize_loc.value)
+ elif _valid_addressing_size(itemsize_loc.value):
+ return AddressLoc(base_loc, index_loc, _get_scale(itemsize_loc.value), ofs_loc.value)
else:
- # XXX should not use IMUL in most cases
+ # XXX should not use IMUL in more cases, it can use a clever LEA
assert isinstance(temp_loc, RegLoc)
assert isinstance(index_loc, RegLoc)
assert not temp_loc.is_xmm
@@ -1619,6 +1621,8 @@
ofs_loc)
self.load_from_mem(resloc, src_addr, fieldsize_loc, sign_loc)
+ genop_getinteriorfield_raw = genop_getinteriorfield_gc
+
def genop_discard_setfield_gc(self, op, arglocs):
base_loc, ofs_loc, size_loc, value_loc = arglocs
@@ -1634,6 +1638,8 @@
ofs_loc)
self.save_into_mem(dest_addr, value_loc, fieldsize_loc)
+ genop_discard_setinteriorfield_raw = genop_discard_setinteriorfield_gc
+
def genop_discard_setarrayitem_gc(self, op, arglocs):
base_loc, ofs_loc, value_loc, size_loc, baseofs = arglocs
assert isinstance(baseofs, ImmedLoc)
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -1067,6 +1067,8 @@
self.PerformDiscard(op, [base_loc, ofs, itemsize, fieldsize,
index_loc, temp_loc, value_loc])
+ consider_setinteriorfield_raw = consider_setinteriorfield_gc
+
def consider_strsetitem(self, op):
args = op.getarglist()
base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
@@ -1158,6 +1160,8 @@
self.Perform(op, [base_loc, ofs, itemsize, fieldsize,
index_loc, temp_loc, sign_loc], result_loc)
+ consider_getinteriorfield_raw = consider_getinteriorfield_gc
+
def consider_int_is_true(self, op, guard_op):
# doesn't need arg to be in a register
argloc = self.loc(op.getarg(0))
@@ -1430,8 +1434,11 @@
# i.e. the n'th word beyond the fixed frame size.
return -WORD * (FRAME_FIXED_SIZE + position)
+def _valid_addressing_size(size):
+ return size == 1 or size == 2 or size == 4 or size == 8
+
def _get_scale(size):
- assert size == 1 or size == 2 or size == 4 or size == 8
+ assert _valid_addressing_size(size)
if size < 4:
return size - 1 # 1, 2 => 0, 1
else:
diff --git a/pypy/jit/backend/x86/test/test_fficall.py b/pypy/jit/backend/x86/test/test_fficall.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/x86/test/test_fficall.py
@@ -0,0 +1,8 @@
+import py
+from pypy.jit.metainterp.test import test_fficall
+from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
+
+class TestFfiLookups(Jit386Mixin, test_fficall.FfiLookupTests):
+ # for the individual tests see
+ # ====> ../../../metainterp/test/test_fficall.py
+ supports_all = True
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -48,6 +48,8 @@
OS_LIBFFI_PREPARE = 60
OS_LIBFFI_PUSH_ARG = 61
OS_LIBFFI_CALL = 62
+ OS_LIBFFI_GETARRAYITEM = 63
+ OS_LIBFFI_SETARRAYITEM = 64
#
OS_LLONG_INVERT = 69
OS_LLONG_ADD = 70
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -1615,6 +1615,12 @@
elif oopspec_name.startswith('libffi_call_'):
oopspecindex = EffectInfo.OS_LIBFFI_CALL
extraeffect = EffectInfo.EF_RANDOM_EFFECTS
+ elif oopspec_name == 'libffi_array_getitem':
+ oopspecindex = EffectInfo.OS_LIBFFI_GETARRAYITEM
+ extraeffect = EffectInfo.EF_CANNOT_RAISE
+ elif oopspec_name == 'libffi_array_setitem':
+ oopspecindex = EffectInfo.OS_LIBFFI_SETARRAYITEM
+ extraeffect = EffectInfo.EF_CANNOT_RAISE
else:
assert False, 'unsupported oopspec: %s' % oopspec_name
return self._handle_oopspec_call(op, args, oopspecindex, extraeffect)
diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -340,6 +340,8 @@
rop.DEBUG_MERGE_POINT,
rop.JIT_DEBUG,
rop.SETARRAYITEM_RAW,
+ rop.GETINTERIORFIELD_RAW,
+ rop.SETINTERIORFIELD_RAW,
rop.CALL_RELEASE_GIL,
rop.QUASIIMMUT_FIELD,
): # list of opcodes never executed by pyjitpl
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -1,11 +1,13 @@
+from pypy.jit.codewriter.effectinfo import EffectInfo
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.rlib import clibffi, libffi
+from pypy.rlib.debug import debug_print
+from pypy.rlib.libffi import Func
+from pypy.rlib.objectmodel import we_are_translated
from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.libffi import Func
-from pypy.rlib.debug import debug_print
-from pypy.jit.codewriter.effectinfo import EffectInfo
-from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
-from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.rpython.lltypesystem import llmemory
class FuncInfo(object):
@@ -78,7 +80,7 @@
def new(self):
return OptFfiCall()
-
+
def begin_optimization(self, funcval, op):
self.rollback_maybe('begin_optimization', op)
self.funcinfo = FuncInfo(funcval, self.optimizer.cpu, op)
@@ -116,6 +118,9 @@
ops = self.do_push_arg(op)
elif oopspec == EffectInfo.OS_LIBFFI_CALL:
ops = self.do_call(op)
+ elif (oopspec == EffectInfo.OS_LIBFFI_GETARRAYITEM or
+ oopspec == EffectInfo.OS_LIBFFI_SETARRAYITEM):
+ ops = self.do_getsetarrayitem(op, oopspec)
#
for op in ops:
self.emit_operation(op)
@@ -190,6 +195,53 @@
ops.append(newop)
return ops
+ def do_getsetarrayitem(self, op, oopspec):
+ ffitypeval = self.getvalue(op.getarg(1))
+ widthval = self.getvalue(op.getarg(2))
+ offsetval = self.getvalue(op.getarg(5))
+ if not ffitypeval.is_constant() or not widthval.is_constant() or not offsetval.is_constant():
+ return [op]
+
+ ffitypeaddr = ffitypeval.box.getaddr()
+ ffitype = llmemory.cast_adr_to_ptr(ffitypeaddr, clibffi.FFI_TYPE_P)
+ offset = offsetval.box.getint()
+ width = widthval.box.getint()
+ descr = self._get_interior_descr(ffitype, width, offset)
+
+ arglist = [
+ self.getvalue(op.getarg(3)).force_box(self.optimizer),
+ self.getvalue(op.getarg(4)).force_box(self.optimizer),
+ ]
+ if oopspec == EffectInfo.OS_LIBFFI_GETARRAYITEM:
+ opnum = rop.GETINTERIORFIELD_RAW
+ elif oopspec == EffectInfo.OS_LIBFFI_SETARRAYITEM:
+ opnum = rop.SETINTERIORFIELD_RAW
+ arglist.append(self.getvalue(op.getarg(6)).force_box(self.optimizer))
+ else:
+ assert False
+ return [
+ ResOperation(opnum, arglist, op.result, descr=descr),
+ ]
+
+ def _get_interior_descr(self, ffitype, width, offset):
+ kind = libffi.types.getkind(ffitype)
+ is_pointer = is_float = is_signed = False
+ if ffitype is libffi.types.pointer:
+ is_pointer = True
+ elif kind == 'i':
+ is_signed = True
+ elif kind == 'f' or kind == 'I' or kind == 'U':
+ # longlongs are treated as floats, see
+ # e.g. llsupport/descr.py:getDescrClass
+ is_float = True
+ else:
+ assert False, "unsupported ffitype or kind"
+ #
+ fieldsize = ffitype.c_size
+ return self.optimizer.cpu.interiorfielddescrof_dynamic(
+ offset, width, fieldsize, is_pointer, is_float, is_signed
+ )
+
def propagate_forward(self, op):
if self.logops is not None:
debug_print(self.logops.repr_of_resop(op))
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -461,6 +461,7 @@
'GETARRAYITEM_GC/2d',
'GETARRAYITEM_RAW/2d',
'GETINTERIORFIELD_GC/2d',
+ 'GETINTERIORFIELD_RAW/2d',
'GETFIELD_GC/1d',
'GETFIELD_RAW/1d',
'_MALLOC_FIRST',
@@ -479,6 +480,7 @@
'SETARRAYITEM_GC/3d',
'SETARRAYITEM_RAW/3d',
'SETINTERIORFIELD_GC/3d',
+ 'SETINTERIORFIELD_RAW/3d',
'SETFIELD_GC/2d',
'SETFIELD_RAW/2d',
'STRSETITEM/3',
diff --git a/pypy/jit/metainterp/test/test_fficall.py b/pypy/jit/metainterp/test/test_fficall.py
--- a/pypy/jit/metainterp/test/test_fficall.py
+++ b/pypy/jit/metainterp/test/test_fficall.py
@@ -1,19 +1,18 @@
+import py
-import py
+from pypy.jit.metainterp.test.support import LLJitMixin
+from pypy.rlib.jit import JitDriver, promote, dont_look_inside
+from pypy.rlib.libffi import (ArgChain, IS_32_BIT, array_getitem, array_setitem,
+ types)
+from pypy.rlib.objectmodel import specialize
from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
-from pypy.rlib.jit import JitDriver, promote, dont_look_inside
+from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
from pypy.rlib.unroll import unrolling_iterable
-from pypy.rlib.libffi import ArgChain
-from pypy.rlib.libffi import IS_32_BIT
-from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rlib.objectmodel import specialize
from pypy.tool.sourcetools import func_with_new_name
-from pypy.jit.metainterp.test.support import LLJitMixin
-class TestFfiCall(LLJitMixin, _TestLibffiCall):
- supports_all = False # supports_{floats,longlong,singlefloats}
+class FfiCallTests(_TestLibffiCall):
# ===> ../../../rlib/test/test_libffi.py
def call(self, funcspec, args, RESULT, is_struct=False, jitif=[]):
@@ -92,6 +91,69 @@
test_byval_result.__doc__ = _TestLibffiCall.test_byval_result.__doc__
test_byval_result.dont_track_allocations = True
+class FfiLookupTests(object):
+ def test_array_fields(self):
+ myjitdriver = JitDriver(
+ greens = [],
+ reds = ["n", "i", "points", "result_point"],
+ )
-class TestFfiCallSupportAll(TestFfiCall):
+ POINT = lltype.Struct("POINT",
+ ("x", lltype.Signed),
+ ("y", lltype.Signed),
+ )
+ def f(points, result_point, n):
+ i = 0
+ while i < n:
+ myjitdriver.jit_merge_point(i=i, points=points, n=n,
+ result_point=result_point)
+ x = array_getitem(
+ types.slong, rffi.sizeof(lltype.Signed) * 2, points, i, 0
+ )
+ y = array_getitem(
+ types.slong, rffi.sizeof(lltype.Signed) * 2, points, i, rffi.sizeof(lltype.Signed)
+ )
+
+ cur_x = array_getitem(
+ types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, 0
+ )
+ cur_y = array_getitem(
+ types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, rffi.sizeof(lltype.Signed)
+ )
+
+ array_setitem(
+ types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, 0, cur_x + x
+ )
+ array_setitem(
+ types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, rffi.sizeof(lltype.Signed), cur_y + y
+ )
+ i += 1
+
+ def main(n):
+ with lltype.scoped_alloc(rffi.CArray(POINT), n) as points:
+ with lltype.scoped_alloc(rffi.CArray(POINT), 1) as result_point:
+ for i in xrange(n):
+ points[i].x = i * 2
+ points[i].y = i * 2 + 1
+ points = rffi.cast(rffi.CArrayPtr(lltype.Char), points)
+ result_point[0].x = 0
+ result_point[0].y = 0
+ result_point = rffi.cast(rffi.CArrayPtr(lltype.Char), result_point)
+ f(points, result_point, n)
+ result_point = rffi.cast(rffi.CArrayPtr(POINT), result_point)
+ return result_point[0].x * result_point[0].y
+
+ assert self.meta_interp(main, [10]) == main(10) == 9000
+ self.check_loops({"int_add": 3, "jump": 1, "int_lt": 1, "guard_true": 1,
+ "getinteriorfield_raw": 4, "setinteriorfield_raw": 2
+ })
+
+
+class TestFfiCall(FfiCallTests, LLJitMixin):
+ supports_all = False
+
+class TestFfiCallSupportAll(FfiCallTests, LLJitMixin):
supports_all = True # supports_{floats,longlong,singlefloats}
+
+class TestFfiLookup(FfiLookupTests, LLJitMixin):
+ pass
\ No newline at end of file
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -1022,6 +1022,12 @@
assert ret.y == 1234500, "ret.y == %d" % (ret.y,)
s.free()
+ def test_ffi_type(self):
+ import _rawffi
+ EMPTY = _rawffi.Structure([])
+ S2E = _rawffi.Structure([('bah', (EMPTY, 1))])
+ S2E.get_ffi_type() # does not hang
+
class AppTestAutoFree:
def setup_class(cls):
space = gettestobjspace(usemodules=('_rawffi', 'struct'))
diff --git a/pypy/module/cpyext/include/eval.h b/pypy/module/cpyext/include/eval.h
--- a/pypy/module/cpyext/include/eval.h
+++ b/pypy/module/cpyext/include/eval.h
@@ -14,8 +14,8 @@
PyObject * PyEval_CallFunction(PyObject *obj, const char *format, ...);
PyObject * PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...);
-PyObject * PyObject_CallFunction(PyObject *obj, char *format, ...);
-PyObject * PyObject_CallMethod(PyObject *obj, char *name, char *format, ...);
+PyObject * PyObject_CallFunction(PyObject *obj, const char *format, ...);
+PyObject * PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...);
PyObject * PyObject_CallFunctionObjArgs(PyObject *callable, ...);
PyObject * PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...);
diff --git a/pypy/module/cpyext/include/pycobject.h b/pypy/module/cpyext/include/pycobject.h
--- a/pypy/module/cpyext/include/pycobject.h
+++ b/pypy/module/cpyext/include/pycobject.h
@@ -33,7 +33,7 @@
PyAPI_FUNC(void *) PyCObject_GetDesc(PyObject *);
/* Import a pointer to a C object from a module using a PyCObject. */
-PyAPI_FUNC(void *) PyCObject_Import(char *module_name, char *cobject_name);
+PyAPI_FUNC(void *) PyCObject_Import(const char *module_name, const char *cobject_name);
/* Modify a C object. Fails (==0) if object has a destructor. */
PyAPI_FUNC(int) PyCObject_SetVoidPtr(PyObject *self, void *cobj);
diff --git a/pypy/module/cpyext/include/pyerrors.h b/pypy/module/cpyext/include/pyerrors.h
--- a/pypy/module/cpyext/include/pyerrors.h
+++ b/pypy/module/cpyext/include/pyerrors.h
@@ -11,8 +11,8 @@
(PyClass_Check((x)) || (PyType_Check((x)) && \
PyObject_IsSubclass((x), PyExc_BaseException)))
-PyObject *PyErr_NewException(char *name, PyObject *base, PyObject *dict);
-PyObject *PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict);
+PyObject *PyErr_NewException(const char *name, PyObject *base, PyObject *dict);
+PyObject *PyErr_NewExceptionWithDoc(const char *name, const char *doc, PyObject *base, PyObject *dict);
PyObject *PyErr_Format(PyObject *exception, const char *format, ...);
/* These APIs aren't really part of the error implementation, but
diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py
--- a/pypy/module/cpyext/modsupport.py
+++ b/pypy/module/cpyext/modsupport.py
@@ -54,9 +54,15 @@
modname = rffi.charp2str(name)
state = space.fromcache(State)
f_name, f_path = state.package_context
- w_mod = PyImport_AddModule(space, f_name)
+ if f_name is not None:
+ modname = f_name
+ w_mod = PyImport_AddModule(space, modname)
+ state.package_context = None, None
- dict_w = {'__file__': space.wrap(f_path)}
+ if f_path is not None:
+ dict_w = {'__file__': space.wrap(f_path)}
+ else:
+ dict_w = {}
convert_method_defs(space, dict_w, methods, None, w_self, modname)
for key, w_value in dict_w.items():
space.setattr(w_mod, space.wrap(key), w_value)
diff --git a/pypy/module/cpyext/src/cobject.c b/pypy/module/cpyext/src/cobject.c
--- a/pypy/module/cpyext/src/cobject.c
+++ b/pypy/module/cpyext/src/cobject.c
@@ -77,7 +77,7 @@
}
void *
-PyCObject_Import(char *module_name, char *name)
+PyCObject_Import(const char *module_name, const char *name)
{
PyObject *m, *c;
void *r = NULL;
diff --git a/pypy/module/cpyext/src/modsupport.c b/pypy/module/cpyext/src/modsupport.c
--- a/pypy/module/cpyext/src/modsupport.c
+++ b/pypy/module/cpyext/src/modsupport.c
@@ -541,7 +541,7 @@
}
PyObject *
-PyObject_CallFunction(PyObject *callable, char *format, ...)
+PyObject_CallFunction(PyObject *callable, const char *format, ...)
{
va_list va;
PyObject *args;
@@ -558,7 +558,7 @@
}
PyObject *
-PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
+PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
{
va_list va;
PyObject *args;
diff --git a/pypy/module/cpyext/src/pyerrors.c b/pypy/module/cpyext/src/pyerrors.c
--- a/pypy/module/cpyext/src/pyerrors.c
+++ b/pypy/module/cpyext/src/pyerrors.c
@@ -21,7 +21,7 @@
}
PyObject *
-PyErr_NewException(char *name, PyObject *base, PyObject *dict)
+PyErr_NewException(const char *name, PyObject *base, PyObject *dict)
{
char *dot;
PyObject *modulename = NULL;
@@ -72,7 +72,7 @@
/* Create an exception with docstring */
PyObject *
-PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict)
+PyErr_NewExceptionWithDoc(const char *name, const char *doc, PyObject *base, PyObject *dict)
{
int result;
PyObject *ret = NULL;
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -513,7 +513,7 @@
space.warn(msg, space.w_ImportWarning)
modtype, suffix, filemode = find_modtype(space, filepart)
try:
- if modtype in (PY_SOURCE, PY_COMPILED):
+ if modtype in (PY_SOURCE, PY_COMPILED, C_EXTENSION):
assert suffix is not None
filename = filepart + suffix
stream = streamio.open_file_as_stream(filename, filemode)
@@ -522,9 +522,6 @@
except:
stream.close()
raise
- if modtype == C_EXTENSION:
- filename = filepart + suffix
- return FindInfo(modtype, filename, None, suffix, filemode)
except StreamErrors:
pass # XXX! must not eat all exceptions, e.g.
# Out of file descriptors.
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -285,6 +285,11 @@
guard_false(ticker_cond1, descr=...)
"""
src = src.replace('--EXC-TICK--', exc_ticker_check)
+ #
+ # ISINF is done as a macro; fix it here
+ r = re.compile('(\w+) = --ISINF--[(](\w+)[)]')
+ src = r.sub(r'\2\B999 = float_add(\2, ...)\n\1 = float_eq(\2\B999, \2)',
+ src)
return src
@classmethod
diff --git a/pypy/module/pypyjit/test_pypy_c/test_math.py b/pypy/module/pypyjit/test_pypy_c/test_math.py
--- a/pypy/module/pypyjit/test_pypy_c/test_math.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_math.py
@@ -1,3 +1,4 @@
+import py
from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
@@ -49,10 +50,7 @@
guard_true(i2, descr=...)
guard_not_invalidated(descr=...)
f1 = cast_int_to_float(i0)
- i3 = float_eq(f1, inf)
- i4 = float_eq(f1, -inf)
- i5 = int_or(i3, i4)
- i6 = int_is_true(i5)
+ i6 = --ISINF--(f1)
guard_false(i6, descr=...)
f2 = call(ConstClass(sin), f1, descr=<FloatCallDescr>)
f3 = call(ConstClass(cos), f1, descr=<FloatCallDescr>)
@@ -64,6 +62,7 @@
""")
def test_fmod(self):
+ py.test.skip("test relies on the old and broken ll_math_fmod")
def main(n):
import math
@@ -90,4 +89,4 @@
i6 = int_sub(i0, 1)
--TICK--
jump(..., descr=)
- """)
\ No newline at end of file
+ """)
diff --git a/pypy/module/test_lib_pypy/test_pwd.py b/pypy/module/test_lib_pypy/test_pwd.py
--- a/pypy/module/test_lib_pypy/test_pwd.py
+++ b/pypy/module/test_lib_pypy/test_pwd.py
@@ -1,7 +1,10 @@
+import py, sys
from pypy.conftest import gettestobjspace
class AppTestPwd:
def setup_class(cls):
+ if sys.platform == 'win32':
+ py.test.skip("Unix only")
cls.space = gettestobjspace(usemodules=('_ffi', '_rawffi'))
cls.space.appexec((), "(): import pwd")
diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py
--- a/pypy/objspace/std/bytearraytype.py
+++ b/pypy/objspace/std/bytearraytype.py
@@ -122,10 +122,11 @@
return -1
def descr_fromhex(space, w_type, w_hexstring):
- "bytearray.fromhex(string) -> bytearray\n\nCreate a bytearray object "
- "from a string of hexadecimal numbers.\nSpaces between two numbers are "
- "accepted.\nExample: bytearray.fromhex('B9 01EF') -> "
- "bytearray(b'\\xb9\\x01\\xef')."
+ "bytearray.fromhex(string) -> bytearray\n"
+ "\n"
+ "Create a bytearray object from a string of hexadecimal numbers.\n"
+ "Spaces between two numbers are accepted.\n"
+ "Example: bytearray.fromhex('B9 01EF') -> bytearray(b'\\xb9\\x01\\xef')."
hexstring = space.str_w(w_hexstring)
hexstring = hexstring.lower()
data = []
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -16,7 +16,10 @@
something CPython does not do anymore.
"""
-class W_IntObject(W_Object):
+class W_AbstractIntObject(W_Object):
+ __slots__ = ()
+
+class W_IntObject(W_AbstractIntObject):
__slots__ = 'intval'
_immutable_fields_ = ['intval']
diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -4,7 +4,10 @@
from pypy.objspace.std.register_all import register_all
-class W_AbstractSeqIterObject(W_Object):
+class W_AbstractIterObject(W_Object):
+ __slots__ = ()
+
+class W_AbstractSeqIterObject(W_AbstractIterObject):
from pypy.objspace.std.itertype import iter_typedef as typedef
def __init__(w_self, w_seq, index=0):
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -11,7 +11,10 @@
from pypy.rlib.listsort import make_timsort_class
from pypy.interpreter.argument import Signature
-class W_ListObject(W_Object):
+class W_AbstractListObject(W_Object):
+ __slots__ = ()
+
+class W_ListObject(W_AbstractListObject):
from pypy.objspace.std.listtype import list_typedef as typedef
def __init__(w_self, wrappeditems):
diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -8,7 +8,10 @@
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.rlib.rbigint import rbigint, SHIFT
-class W_LongObject(W_Object):
+class W_AbstractLongObject(W_Object):
+ __slots__ = ()
+
+class W_LongObject(W_AbstractLongObject):
"""This is a wrapper of rbigint."""
from pypy.objspace.std.longtype import long_typedef as typedef
_immutable_fields_ = ['num']
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -83,12 +83,7 @@
if self.config.objspace.std.withtproxy:
transparent.setup(self)
- interplevel_classes = {}
- for type, classes in self.model.typeorder.iteritems():
- if len(classes) >= 3: # XXX what does this 3 mean??!
- # W_Root, AnyXxx and actual object
- interplevel_classes[self.gettypefor(type)] = classes[0][0]
- self._interplevel_classes = interplevel_classes
+ self.setup_isinstance_cache()
def get_builtin_types(self):
return self.builtin_types
@@ -592,6 +587,63 @@
def isinstance_w(space, w_inst, w_type):
return space._type_isinstance(w_inst, w_type)
+ def setup_isinstance_cache(self):
+ # This assumes that all classes in the stdobjspace implementing a
+ # particular app-level type are distinguished by a common base class.
+ # Alternatively, you can turn off the cache on specific classes,
+ # like e.g. proxyobject. It is just a bit less performant but
+ # should not have any bad effect.
+ from pypy.objspace.std.model import W_Root, W_Object
+ #
+ # Build a dict {class: w_typeobject-or-None}. The value None is used
+ # on classes that are known to be abstract base classes.
+ class2type = {}
+ class2type[W_Root] = None
+ class2type[W_Object] = None
+ for cls in self.model.typeorder.keys():
+ if getattr(cls, 'typedef', None) is None:
+ continue
+ if getattr(cls, 'ignore_for_isinstance_cache', False):
+ continue
+ w_type = self.gettypefor(cls)
+ w_oldtype = class2type.setdefault(cls, w_type)
+ assert w_oldtype is w_type
+ #
+ # Build the real dict {w_typeobject: class-or-base-class}. For every
+ # w_typeobject we look for the most precise common base class of all
+ # the registered classes. If no such class is found, we will find
+ # W_Object or W_Root, and complain. Then you must either add an
+ # artificial common base class, or disable caching on one of the
+ # two classes with ignore_for_isinstance_cache.
+ def getmro(cls):
+ while True:
+ yield cls
+ if cls is W_Root:
+ break
+ cls = cls.__bases__[0]
+ self._interplevel_classes = {}
+ for cls, w_type in class2type.items():
+ if w_type is None:
+ continue
+ if w_type not in self._interplevel_classes:
+ self._interplevel_classes[w_type] = cls
+ else:
+ cls1 = self._interplevel_classes[w_type]
+ mro1 = list(getmro(cls1))
+ for base in getmro(cls):
+ if base in mro1:
+ break
+ if base in class2type and class2type[base] is not w_type:
+ if class2type.get(base) is None:
+ msg = ("cannot find a common interp-level base class"
+ " between %r and %r" % (cls1, cls))
+ else:
+ msg = ("%s is a base class of both %r and %r" % (
+ class2type[base], cls1, cls))
+ raise AssertionError("%r: %s" % (w_type, msg))
+ class2type[base] = w_type
+ self._interplevel_classes[w_type] = base
+
@specialize.memo()
def _get_interplevel_cls(self, w_type):
if not hasattr(self, "_interplevel_classes"):
diff --git a/pypy/objspace/std/proxyobject.py b/pypy/objspace/std/proxyobject.py
--- a/pypy/objspace/std/proxyobject.py
+++ b/pypy/objspace/std/proxyobject.py
@@ -16,6 +16,8 @@
def transparent_class(name, BaseCls):
class W_Transparent(BaseCls):
+ ignore_for_isinstance_cache = True
+
def __init__(self, space, w_type, w_controller):
self.w_type = w_type
self.w_controller = w_controller
diff --git a/pypy/objspace/std/rangeobject.py b/pypy/objspace/std/rangeobject.py
--- a/pypy/objspace/std/rangeobject.py
+++ b/pypy/objspace/std/rangeobject.py
@@ -5,7 +5,7 @@
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.objspace.std.inttype import wrapint
from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
-from pypy.objspace.std.listobject import W_ListObject
+from pypy.objspace.std.listobject import W_AbstractListObject, W_ListObject
from pypy.objspace.std import listtype, iterobject, slicetype
from pypy.interpreter import gateway, baseobjspace
@@ -21,7 +21,7 @@
return (start - stop - step - 1)/-step
-class W_RangeListObject(W_Object):
+class W_RangeListObject(W_AbstractListObject):
typedef = listtype.list_typedef
def __init__(w_self, start, step, length):
diff --git a/pypy/objspace/std/ropeobject.py b/pypy/objspace/std/ropeobject.py
--- a/pypy/objspace/std/ropeobject.py
+++ b/pypy/objspace/std/ropeobject.py
@@ -6,7 +6,7 @@
from pypy.rlib.objectmodel import we_are_translated
from pypy.objspace.std.inttype import wrapint
from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
-from pypy.objspace.std import slicetype
+from pypy.objspace.std import stringobject, slicetype, iterobject
from pypy.objspace.std.listobject import W_ListObject
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.objspace.std.tupleobject import W_TupleObject
@@ -19,7 +19,7 @@
str_format__String as str_format__Rope,
_upper, _lower, DEFAULT_NOOP_TABLE)
-class W_RopeObject(W_Object):
+class W_RopeObject(stringobject.W_AbstractStringObject):
from pypy.objspace.std.stringtype import str_typedef as typedef
_immutable_fields_ = ['_node']
@@ -59,7 +59,7 @@
registerimplementation(W_RopeObject)
-class W_RopeIterObject(W_Object):
+class W_RopeIterObject(iterobject.W_AbstractIterObject):
from pypy.objspace.std.itertype import iter_typedef as typedef
def __init__(w_self, w_rope, index=0):
diff --git a/pypy/objspace/std/ropeunicodeobject.py b/pypy/objspace/std/ropeunicodeobject.py
--- a/pypy/objspace/std/ropeunicodeobject.py
+++ b/pypy/objspace/std/ropeunicodeobject.py
@@ -9,7 +9,7 @@
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.rlib import rope
from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
-from pypy.objspace.std import slicetype
+from pypy.objspace.std import unicodeobject, slicetype, iterobject
from pypy.objspace.std.tupleobject import W_TupleObject
from pypy.rlib.rarithmetic import intmask, ovfcheck
from pypy.module.unicodedata import unicodedb
@@ -76,7 +76,7 @@
return encode_object(space, w_unistr, encoding, errors)
-class W_RopeUnicodeObject(W_Object):
+class W_RopeUnicodeObject(unicodeobject.W_AbstractUnicodeObject):
from pypy.objspace.std.unicodetype import unicode_typedef as typedef
_immutable_fields_ = ['_node']
@@ -117,7 +117,7 @@
return rope.LiteralUnicodeNode(space.unicode_w(w_str))
-class W_RopeUnicodeIterObject(W_Object):
+class W_RopeUnicodeIterObject(iterobject.W_AbstractIterObject):
from pypy.objspace.std.itertype import iter_typedef as typedef
def __init__(w_self, w_rope, index=0):
diff --git a/pypy/objspace/std/smallintobject.py b/pypy/objspace/std/smallintobject.py
--- a/pypy/objspace/std/smallintobject.py
+++ b/pypy/objspace/std/smallintobject.py
@@ -6,7 +6,7 @@
from pypy.objspace.std.model import registerimplementation, W_Object
from pypy.objspace.std.register_all import register_all
from pypy.objspace.std.noneobject import W_NoneObject
-from pypy.objspace.std.intobject import W_IntObject
+from pypy.objspace.std.intobject import W_AbstractIntObject, W_IntObject
from pypy.interpreter.error import OperationError
from pypy.rlib.objectmodel import UnboxedValue
from pypy.rlib.rbigint import rbigint
@@ -14,7 +14,7 @@
from pypy.tool.sourcetools import func_with_new_name
from pypy.objspace.std.inttype import wrapint
-class W_SmallIntObject(W_Object, UnboxedValue):
+class W_SmallIntObject(W_AbstractIntObject, UnboxedValue):
__slots__ = 'intval'
from pypy.objspace.std.inttype import int_typedef as typedef
diff --git a/pypy/objspace/std/smalllongobject.py b/pypy/objspace/std/smalllongobject.py
--- a/pypy/objspace/std/smalllongobject.py
+++ b/pypy/objspace/std/smalllongobject.py
@@ -9,7 +9,7 @@
from pypy.rlib.rarithmetic import r_longlong, r_int, r_uint
from pypy.rlib.rarithmetic import intmask, LONGLONG_BIT
from pypy.rlib.rbigint import rbigint
-from pypy.objspace.std.longobject import W_LongObject
+from pypy.objspace.std.longobject import W_AbstractLongObject, W_LongObject
from pypy.objspace.std.intobject import W_IntObject
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.interpreter.error import OperationError
@@ -17,7 +17,7 @@
LONGLONG_MIN = r_longlong((-1) << (LONGLONG_BIT-1))
-class W_SmallLongObject(W_Object):
+class W_SmallLongObject(W_AbstractLongObject):
from pypy.objspace.std.longtype import long_typedef as typedef
_immutable_fields_ = ['longlong']
diff --git a/pypy/objspace/std/smalltupleobject.py b/pypy/objspace/std/smalltupleobject.py
--- a/pypy/objspace/std/smalltupleobject.py
+++ b/pypy/objspace/std/smalltupleobject.py
@@ -9,9 +9,9 @@
from pypy.interpreter import gateway
from pypy.rlib.debug import make_sure_not_resized
from pypy.rlib.unroll import unrolling_iterable
-from pypy.objspace.std.tupleobject import W_TupleObject
+from pypy.objspace.std.tupleobject import W_AbstractTupleObject, W_TupleObject
-class W_SmallTupleObject(W_Object):
+class W_SmallTupleObject(W_AbstractTupleObject):
from pypy.objspace.std.tupletype import tuple_typedef as typedef
def tolist(self):
diff --git a/pypy/objspace/std/strbufobject.py b/pypy/objspace/std/strbufobject.py
--- a/pypy/objspace/std/strbufobject.py
+++ b/pypy/objspace/std/strbufobject.py
@@ -1,11 +1,12 @@
from pypy.objspace.std.model import registerimplementation, W_Object
from pypy.objspace.std.register_all import register_all
+from pypy.objspace.std.stringobject import W_AbstractStringObject
from pypy.objspace.std.stringobject import W_StringObject
from pypy.objspace.std.unicodeobject import delegate_String2Unicode
from pypy.rlib.rstring import StringBuilder
from pypy.interpreter.buffer import Buffer
-class W_StringBufferObject(W_Object):
+class W_StringBufferObject(W_AbstractStringObject):
from pypy.objspace.std.stringtype import str_typedef as typedef
w_str = None
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -19,7 +19,10 @@
from pypy.objspace.std.formatting import mod_format
-class W_StringObject(W_Object):
+class W_AbstractStringObject(W_Object):
+ __slots__ = ()
+
+class W_StringObject(W_AbstractStringObject):
from pypy.objspace.std.stringtype import str_typedef as typedef
_immutable_fields_ = ['_value']
diff --git a/pypy/objspace/std/strjoinobject.py b/pypy/objspace/std/strjoinobject.py
--- a/pypy/objspace/std/strjoinobject.py
+++ b/pypy/objspace/std/strjoinobject.py
@@ -1,11 +1,12 @@
from pypy.objspace.std.model import registerimplementation, W_Object
from pypy.objspace.std.register_all import register_all
+from pypy.objspace.std.stringobject import W_AbstractStringObject
from pypy.objspace.std.stringobject import W_StringObject
from pypy.objspace.std.unicodeobject import delegate_String2Unicode
from pypy.objspace.std.stringtype import wrapstr
-class W_StringJoinObject(W_Object):
+class W_StringJoinObject(W_AbstractStringObject):
from pypy.objspace.std.stringtype import str_typedef as typedef
def __init__(w_self, joined_strs, until=-1):
diff --git a/pypy/objspace/std/strsliceobject.py b/pypy/objspace/std/strsliceobject.py
--- a/pypy/objspace/std/strsliceobject.py
+++ b/pypy/objspace/std/strsliceobject.py
@@ -1,6 +1,7 @@
from pypy.interpreter.error import OperationError
from pypy.objspace.std.model import registerimplementation, W_Object
from pypy.objspace.std.register_all import register_all
+from pypy.objspace.std.stringobject import W_AbstractStringObject
from pypy.objspace.std.stringobject import W_StringObject
from pypy.objspace.std.unicodeobject import delegate_String2Unicode
from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
@@ -12,7 +13,7 @@
stringendswith, stringstartswith
-class W_StringSliceObject(W_Object):
+class W_StringSliceObject(W_AbstractStringObject):
from pypy.objspace.std.stringtype import str_typedef as typedef
def __init__(w_self, str, start, stop):
diff --git a/pypy/objspace/std/test/test_sliceobject.py b/pypy/objspace/std/test/test_sliceobject.py
--- a/pypy/objspace/std/test/test_sliceobject.py
+++ b/pypy/objspace/std/test/test_sliceobject.py
@@ -1,3 +1,4 @@
+import sys
from pypy.objspace.std.sliceobject import normalize_simple_slice
@@ -56,8 +57,9 @@
sl = space.newslice(w(start), w(stop), w(step))
mystart, mystop, mystep, slicelength = sl.indices4(space, length)
assert len(range(length)[start:stop:step]) == slicelength
- assert slice(start, stop, step).indices(length) == (
- mystart, mystop, mystep)
+ if sys.version_info >= (2, 6): # doesn't work in 2.5
+ assert slice(start, stop, step).indices(length) == (
+ mystart, mystop, mystep)
class AppTest_SliceObject:
def test_new(self):
diff --git a/pypy/objspace/std/test/test_stdobjspace.py b/pypy/objspace/std/test/test_stdobjspace.py
--- a/pypy/objspace/std/test/test_stdobjspace.py
+++ b/pypy/objspace/std/test/test_stdobjspace.py
@@ -50,6 +50,8 @@
def test_fastpath_isinstance(self):
from pypy.objspace.std.stringobject import W_StringObject
from pypy.objspace.std.intobject import W_IntObject
+ from pypy.objspace.std.iterobject import W_AbstractSeqIterObject
+ from pypy.objspace.std.iterobject import W_SeqIterObject
space = self.space
assert space._get_interplevel_cls(space.w_str) is W_StringObject
@@ -62,9 +64,13 @@
assert space.isinstance_w(X(), space.w_str)
+ w_sequenceiterator = space.gettypefor(W_SeqIterObject)
+ cls = space._get_interplevel_cls(w_sequenceiterator)
+ assert cls is W_AbstractSeqIterObject
+
def test_withstrbuf_fastpath_isinstance(self):
- from pypy.objspace.std.stringobject import W_StringObject
+ from pypy.objspace.std.stringobject import W_AbstractStringObject
- space = gettestobjspace(withstrbuf=True)
- assert space._get_interplevel_cls(space.w_str) is W_StringObject
-
+ space = gettestobjspace(withstrbuf=True)
+ cls = space._get_interplevel_cls(space.w_str)
+ assert cls is W_AbstractStringObject
diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py
--- a/pypy/objspace/std/tupleobject.py
+++ b/pypy/objspace/std/tupleobject.py
@@ -9,7 +9,10 @@
from pypy.interpreter import gateway
from pypy.rlib.debug import make_sure_not_resized
-class W_TupleObject(W_Object):
+class W_AbstractTupleObject(W_Object):
+ __slots__ = ()
+
+class W_TupleObject(W_AbstractTupleObject):
from pypy.objspace.std.tupletype import tuple_typedef as typedef
_immutable_fields_ = ['wrappeditems[*]']
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -19,7 +19,10 @@
from pypy.objspace.std.formatting import mod_format
from pypy.objspace.std.stringtype import stringstartswith, stringendswith
-class W_UnicodeObject(W_Object):
+class W_AbstractUnicodeObject(W_Object):
+ __slots__ = ()
+
+class W_UnicodeObject(W_AbstractUnicodeObject):
from pypy.objspace.std.unicodetype import unicode_typedef as typedef
_immutable_fields_ = ['_value']
diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py
--- a/pypy/rlib/clibffi.py
+++ b/pypy/rlib/clibffi.py
@@ -30,9 +30,6 @@
_MAC_OS = platform.name == "darwin"
_FREEBSD_7 = platform.name == "freebsd7"
-_LITTLE_ENDIAN = sys.byteorder == 'little'
-_BIG_ENDIAN = sys.byteorder == 'big'
-
if _WIN32:
from pypy.rlib import rwin32
@@ -213,26 +210,48 @@
elif sz == 8: return ffi_type_uint64
else: raise ValueError("unsupported type size for %r" % (TYPE,))
-TYPE_MAP = {
- rffi.DOUBLE : ffi_type_double,
- rffi.FLOAT : ffi_type_float,
- rffi.LONGDOUBLE : ffi_type_longdouble,
- rffi.UCHAR : ffi_type_uchar,
- rffi.CHAR : ffi_type_schar,
- rffi.SHORT : ffi_type_sshort,
- rffi.USHORT : ffi_type_ushort,
- rffi.UINT : ffi_type_uint,
- rffi.INT : ffi_type_sint,
+__int_type_map = [
+ (rffi.UCHAR, ffi_type_uchar),
+ (rffi.SIGNEDCHAR, ffi_type_schar),
+ (rffi.SHORT, ffi_type_sshort),
+ (rffi.USHORT, ffi_type_ushort),
+ (rffi.UINT, ffi_type_uint),
+ (rffi.INT, ffi_type_sint),
# xxx don't use ffi_type_slong and ffi_type_ulong - their meaning
# changes from a libffi version to another :-((
- rffi.ULONG : _unsigned_type_for(rffi.ULONG),
- rffi.LONG : _signed_type_for(rffi.LONG),
- rffi.ULONGLONG : _unsigned_type_for(rffi.ULONGLONG),
- rffi.LONGLONG : _signed_type_for(rffi.LONGLONG),
- lltype.Void : ffi_type_void,
- lltype.UniChar : _unsigned_type_for(lltype.UniChar),
- lltype.Bool : _unsigned_type_for(lltype.Bool),
- }
+ (rffi.ULONG, _unsigned_type_for(rffi.ULONG)),
+ (rffi.LONG, _signed_type_for(rffi.LONG)),
+ (rffi.ULONGLONG, _unsigned_type_for(rffi.ULONGLONG)),
+ (rffi.LONGLONG, _signed_type_for(rffi.LONGLONG)),
+ (lltype.UniChar, _unsigned_type_for(lltype.UniChar)),
+ (lltype.Bool, _unsigned_type_for(lltype.Bool)),
+ ]
+
+__float_type_map = [
+ (rffi.DOUBLE, ffi_type_double),
+ (rffi.FLOAT, ffi_type_float),
+ (rffi.LONGDOUBLE, ffi_type_longdouble),
+ ]
+
+__ptr_type_map = [
+ (rffi.VOIDP, ffi_type_pointer),
+ ]
+
+__type_map = __int_type_map + __float_type_map + [
+ (lltype.Void, ffi_type_void)
+ ]
+
+TYPE_MAP_INT = dict(__int_type_map)
+TYPE_MAP_FLOAT = dict(__float_type_map)
+TYPE_MAP = dict(__type_map)
+
+ffitype_map_int = unrolling_iterable(__int_type_map)
+ffitype_map_int_or_ptr = unrolling_iterable(__int_type_map + __ptr_type_map)
+ffitype_map_float = unrolling_iterable(__float_type_map)
+ffitype_map = unrolling_iterable(__type_map)
+
+del __int_type_map, __float_type_map, __ptr_type_map, __type_map
+
def external(name, args, result, **kwds):
return rffi.llexternal(name, args, result, compilation_info=eci, **kwds)
@@ -341,38 +360,15 @@
cast_type_to_ffitype._annspecialcase_ = 'specialize:memo'
def push_arg_as_ffiptr(ffitp, arg, ll_buf):
- # This is for primitive types. Note that the exact type of 'arg' may be
- # different from the expected 'c_size'. To cope with that, we fall back
- # to a byte-by-byte copy.
+ # this is for primitive types. For structures and arrays
+ # would be something different (more dynamic)
TP = lltype.typeOf(arg)
TP_P = lltype.Ptr(rffi.CArray(TP))
- TP_size = rffi.sizeof(TP)
- c_size = intmask(ffitp.c_size)
- # if both types have the same size, we can directly write the
- # value to the buffer
- if c_size == TP_size:
- buf = rffi.cast(TP_P, ll_buf)
- buf[0] = arg
- else:
- # needs byte-by-byte copying. Make sure 'arg' is an integer type.
- # Note that this won't work for rffi.FLOAT/rffi.DOUBLE.
- assert TP is not rffi.FLOAT and TP is not rffi.DOUBLE
- if TP_size <= rffi.sizeof(lltype.Signed):
- arg = rffi.cast(lltype.Unsigned, arg)
- else:
- arg = rffi.cast(lltype.UnsignedLongLong, arg)
- if _LITTLE_ENDIAN:
- for i in range(c_size):
- ll_buf[i] = chr(arg & 0xFF)
- arg >>= 8
- elif _BIG_ENDIAN:
- for i in range(c_size-1, -1, -1):
- ll_buf[i] = chr(arg & 0xFF)
- arg >>= 8
- else:
- raise AssertionError
+ buf = rffi.cast(TP_P, ll_buf)
+ buf[0] = arg
push_arg_as_ffiptr._annspecialcase_ = 'specialize:argtype(1)'
+
# type defs for callback and closure userdata
USERDATA_P = lltype.Ptr(lltype.ForwardReference())
CALLBACK_TP = lltype.Ptr(lltype.FuncType([rffi.VOIDPP, rffi.VOIDP, USERDATA_P],
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -140,7 +140,7 @@
self.last.next = arg
self.last = arg
self.numargs += 1
-
+
class AbstractArg(object):
next = None
@@ -410,3 +410,22 @@
def getaddressindll(self, name):
return dlsym(self.lib, name)
+
+ at jit.oopspec("libffi_array_getitem(ffitype, width, addr, index, offset)")
+def array_getitem(ffitype, width, addr, index, offset):
+ for TYPE, ffitype2 in clibffi.ffitype_map:
+ if ffitype is ffitype2:
+ addr = rffi.ptradd(addr, index * width)
+ addr = rffi.ptradd(addr, offset)
+ return rffi.cast(rffi.CArrayPtr(TYPE), addr)[0]
+ assert False
+
+ at jit.oopspec("libffi_array_setitem(ffitype, width, addr, index, offset, value)")
+def array_setitem(ffitype, width, addr, index, offset, value):
+ for TYPE, ffitype2 in clibffi.ffitype_map:
+ if ffitype is ffitype2:
+ addr = rffi.ptradd(addr, index * width)
+ addr = rffi.ptradd(addr, offset)
+ rffi.cast(rffi.CArrayPtr(TYPE), addr)[0] = value
+ return
+ assert False
\ No newline at end of file
diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py
--- a/pypy/rlib/test/test_libffi.py
+++ b/pypy/rlib/test/test_libffi.py
@@ -1,11 +1,13 @@
+import sys
+
import py
-import sys
+
+from pypy.rlib.libffi import (CDLL, Func, get_libc_name, ArgChain, types,
+ IS_32_BIT, array_getitem, array_setitem)
+from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
+from pypy.rlib.test.test_clibffi import BaseFfiTest, get_libm_name, make_struct_ffitype_e
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED
-from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
-from pypy.rlib.test.test_clibffi import BaseFfiTest, get_libm_name, make_struct_ffitype_e
-from pypy.rlib.libffi import CDLL, Func, get_libc_name, ArgChain, types
-from pypy.rlib.libffi import IS_32_BIT
class TestLibffiMisc(BaseFfiTest):
@@ -52,6 +54,34 @@
del lib
assert not ALLOCATED
+ def test_array_fields(self):
+ POINT = lltype.Struct("POINT",
+ ("x", lltype.Float),
+ ("y", lltype.Float),
+ )
+ points = lltype.malloc(rffi.CArray(POINT), 2, flavor="raw")
+ points[0].x = 1.0
+ points[0].y = 2.0
+ points[1].x = 3.0
+ points[1].y = 4.0
+ points = rffi.cast(rffi.CArrayPtr(lltype.Char), points)
+ assert array_getitem(types.double, 16, points, 0, 0) == 1.0
+ assert array_getitem(types.double, 16, points, 0, 8) == 2.0
+ assert array_getitem(types.double, 16, points, 1, 0) == 3.0
+ assert array_getitem(types.double, 16, points, 1, 8) == 4.0
+
+ array_setitem(types.double, 16, points, 0, 0, 10.0)
+ array_setitem(types.double, 16, points, 0, 8, 20.0)
+ array_setitem(types.double, 16, points, 1, 0, 30.0)
+ array_setitem(types.double, 16, points, 1, 8, 40.0)
+
+ assert array_getitem(types.double, 16, points, 0, 0) == 10.0
+ assert array_getitem(types.double, 16, points, 0, 8) == 20.0
+ assert array_getitem(types.double, 16, points, 1, 0) == 30.0
+ assert array_getitem(types.double, 16, points, 1, 8) == 40.0
+
+ lltype.free(points, flavor="raw")
+
class TestLibffiCall(BaseFfiTest):
"""
Test various kind of calls through libffi.
@@ -109,7 +139,7 @@
This method is overridden by metainterp/test/test_fficall.py in
order to do the call in a loop and JIT it. The optional arguments are
used only by that overridden method.
-
+
"""
lib, name, argtypes, restype = funcspec
func = lib.getpointer(name, argtypes, restype)
@@ -132,7 +162,7 @@
return x - y;
}
"""
- libfoo = self.get_libfoo()
+ libfoo = self.get_libfoo()
func = (libfoo, 'diff_xy', [types.sint, types.slong], types.sint)
res = self.call(func, [50, 8], lltype.Signed)
assert res == 42
@@ -144,7 +174,7 @@
return (x + (int)y);
}
"""
- libfoo = self.get_libfoo()
+ libfoo = self.get_libfoo()
func = (libfoo, 'sum_xy', [types.sint, types.double], types.sint)
res = self.call(func, [38, 4.2], lltype.Signed, jitif=["floats"])
assert res == 42
@@ -249,7 +279,7 @@
};
struct pair my_static_pair = {10, 20};
-
+
long* get_pointer_to_b()
{
return &my_static_pair.b;
@@ -340,7 +370,7 @@
def test_wrong_number_of_arguments(self):
from pypy.rpython.llinterp import LLException
- libfoo = self.get_libfoo()
+ libfoo = self.get_libfoo()
func = (libfoo, 'sum_xy', [types.sint, types.double], types.sint)
glob = globals()
diff --git a/pypy/rpython/lltypesystem/rstr.py b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -331,6 +331,8 @@
# unlike CPython, there is no reason to avoid to return -1
# but our malloc initializes the memory to zero, so we use zero as the
# special non-computed-yet value.
+ if not s:
+ return 0
x = s.hash
if x == 0:
x = _hash_string(s.chars)
diff --git a/pypy/rpython/lltypesystem/test/test_rffi.py b/pypy/rpython/lltypesystem/test/test_rffi.py
--- a/pypy/rpython/lltypesystem/test/test_rffi.py
+++ b/pypy/rpython/lltypesystem/test/test_rffi.py
@@ -742,7 +742,7 @@
assert sizeof(ll) == ctypes.sizeof(ctp)
assert sizeof(lltype.Typedef(ll, 'test')) == sizeof(ll)
assert not size_and_sign(lltype.Signed)[1]
- assert not size_and_sign(lltype.Char)[1]
+ assert size_and_sign(lltype.Char) == (1, True)
assert not size_and_sign(lltype.UniChar)[1]
assert size_and_sign(UINT)[1]
diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -116,6 +116,8 @@
return ootype.oounicode(ch, -1)
def ll_strhash(s):
+ if not s:
+ return 0
return s.ll_hash()
def ll_strfasthash(s):
diff --git a/pypy/rpython/test/test_rtuple.py b/pypy/rpython/test/test_rtuple.py
--- a/pypy/rpython/test/test_rtuple.py
+++ b/pypy/rpython/test/test_rtuple.py
@@ -180,6 +180,19 @@
res2 = self.interpret(f, [27, 12])
assert res1 != res2
+ def test_constant_tuple_hash_str(self):
+ from pypy.rlib.objectmodel import compute_hash
+ def f(i):
+ if i:
+ t = (None, "abc")
+ else:
+ t = ("abc", None)
+ return compute_hash(t)
+
+ res1 = self.interpret(f, [0])
+ res2 = self.interpret(f, [1])
+ assert res1 != res2
+
def test_tuple_to_list(self):
def f(i, j):
return list((i, j))
diff --git a/pypy/translator/platform/__init__.py b/pypy/translator/platform/__init__.py
--- a/pypy/translator/platform/__init__.py
+++ b/pypy/translator/platform/__init__.py
@@ -42,6 +42,8 @@
so_prefixes = ('',)
+ extra_libs = ()
+
def __init__(self, cc):
if self.__class__ is Platform:
raise TypeError("You should not instantiate Platform class directly")
@@ -181,7 +183,8 @@
link_files = self._linkfiles(eci.link_files)
export_flags = self._exportsymbols_link_flags(eci)
return (library_dirs + list(self.link_flags) + export_flags +
- link_files + list(eci.link_extra) + libraries)
+ link_files + list(eci.link_extra) + libraries +
+ list(self.extra_libs))
def _exportsymbols_link_flags(self, eci, relto=None):
if eci.export_symbols:
diff --git a/pypy/translator/platform/linux.py b/pypy/translator/platform/linux.py
--- a/pypy/translator/platform/linux.py
+++ b/pypy/translator/platform/linux.py
@@ -6,7 +6,8 @@
class BaseLinux(BasePosix):
name = "linux"
- link_flags = ('-pthread', '-lrt')
+ link_flags = ('-pthread',)
+ extra_libs = ('-lrt',)
cflags = ('-O3', '-pthread', '-fomit-frame-pointer',
'-Wall', '-Wno-unused')
standalone_only = ()
diff --git a/pypy/translator/platform/posix.py b/pypy/translator/platform/posix.py
--- a/pypy/translator/platform/posix.py
+++ b/pypy/translator/platform/posix.py
@@ -140,7 +140,7 @@
('DEFAULT_TARGET', exe_name.basename),
('SOURCES', rel_cfiles),
('OBJECTS', rel_ofiles),
- ('LIBS', self._libs(eci.libraries)),
+ ('LIBS', self._libs(eci.libraries) + list(self.extra_libs)),
('LIBDIRS', self._libdirs(rel_libdirs)),
('INCLUDEDIRS', self._includedirs(rel_includedirs)),
('CFLAGS', cflags),
diff --git a/pypy/translator/platform/test/test_posix.py b/pypy/translator/platform/test/test_posix.py
--- a/pypy/translator/platform/test/test_posix.py
+++ b/pypy/translator/platform/test/test_posix.py
@@ -41,6 +41,7 @@
if self.strict_on_stderr:
assert res.err == ''
assert res.returncode == 0
+ assert '-lrt' in tmpdir.join("Makefile").read()
def test_link_files(self):
tmpdir = udir.join('link_files' + self.__class__.__name__).ensure(dir=1)
More information about the pypy-commit
mailing list